安卓智能地图开发与实施十三:空间查询与展示 - ArcGIS Runtime SDK for Android(Version 100.0.0)
2017-05-31 11:06
816 查看
空间查询与展示
空间查询需要入口(屏幕触摸、文字输入,甚至绘制个Geometry进行查询),也需要展示容器,如果查询仅仅返回一条记录,在地图中弹出窗口展示信息足矣。当返回多条记录,特别是多个图层的多条记录便需要类似AnimatedExpandableListView的容器来放置查询结果。查询效果(脖子不好时):
写在开头
源程序请自行下载:
链接:http://pan.baidu.com/s/1qXJ6LxM 密码:uh2d
若失效,可发邮件给韩源萌(polyline@126.com)索要。
后面的都是废话(代码解释)
搜索菜单
空间查询的入口可以是个按钮,找一个类似ArcMap中的Identify图标的图片作为菜单的icon 即可。SearchView是Android原生的搜索框控件,它提供了一个用户界面,用于用户搜索查询。main_activity_header_menu.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <!--搜索菜单--> <item android:id="@+id/action_identify" android:orderInCategory="50" android:title="空间查询" app:showAsAction="always" android:icon="@drawable/ic_action_search_identity"/> <item android:id="@+id/action_search" android:icon="@drawable/ic_action_search" android:orderInCategory="50" android:title="属性搜索" app:actionViewClass="android.support.v7.widget.SearchView" app:showAsAction="always"/> </menu>
处理空间查询
@Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_identify) { //this.OpenBottomPanelFunction(); mainConfigurations.ChangeMapViewOnTouchFunction(Configurations.MapTouchType.TOTALIDENTIFY); return true; } return super.onOptionsItemSelected(item); }
处理文本查询
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main_activity_header_menu, menu); MenuItem menuItemSearch = menu.findItem(R.id.action_search);//在菜单中找到对应控件的item mainSearchView = (SearchView) MenuItemCompat.getActionView(menuItemSearch); mainSearchView.setQueryHint("查找..."); mainSearchView.setSubmitButtonEnabled(false); mainSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { final MapQueryClass mapQueryClass = new MapQueryClass(); mapQueryClass.Search(mainConfigurations.getMainReadOperationsFL(), query, new IQueryResult() { @Override public void getQuery() { List<MapQueryClass.MapQueryResult> mapQueryResults= mapQueryClass.getMapQueryResult(); for (MapQueryClass.MapQueryResult mapQueryResult:mapQueryResults ) { mapQueryResult.labelField = mainConfigurations.GetLayerLabelFieldName(mapQueryResult.featureLayer.getName()); } mainSearchView.onActionViewCollapsed(); mainSearchView.clearFocus(); ShowSearchResultFunction(mapQueryResults); } }); return false; } @Override public boolean onQueryTextChange(String newText) { return false; } }); MenuItem menuItemidentify = menu.findItem(R.id.action_identify);//在菜单中找到对应控件的item return true; }
MapView的触摸事件
MapView的setOnTouchListener没有对应的移除机制。public void ChangeMapViewOnTouchFunction(MapTouchType type) { ChangeMapViewOnTouchFunction(type, null); } public void ChangeMapViewOnTouchFunction(MapTouchType type, FeatureLayer featureLayer) { if (mainCallout.isShowing()) { mainCallout.dismiss(); } switch (type) { case SKETCH: mainSketchGraphicsOverlay.mCanMapTouch = true; canLayerTouchidentity = false; canMapTouchidentity = false; break; case LAYERIDENTIFY: mainSketchGraphicsOverlay.mCanMapTouch = false; canLayerTouchidentity = true; canMapTouchidentity = false; StartLayerTouchFunction(featureLayer); break; case TOTALIDENTIFY: mainSketchGraphicsOverlay.mCanMapTouch = false; canLayerTouchidentity = false; canMapTouchidentity = true; StartMapTouchFunction(); break; case CLEAR: mainSketchGraphicsOverlay.mCanMapTouch = false; canLayerTouchidentity = false; canMapTouchidentity = false; break; } }
这里的代码处理的比较乱,合适的方式是定义一个枚举的变量,没必要弄这么多Boolean。
StartLayerTouchFunction
protected void StartLayerTouchFunction(FeatureLayer featureLayer) { if(featureLayer == null) { return; } ClearLayerFunction(); final FeatureLayer mainFeatureLayer = featureLayer; mainMapView.setOnTouchListener(new DefaultMapViewOnTouchListener(this, mainMapView) { @Override public boolean onSingleTapConfirmed(MotionEvent e) { // remove any existing callouts if (canLayerTouchidentity == false) { return super.onSingleTapConfirmed(e); } android.graphics.Point screenPoint = new android.graphics.Point(Math.round(e.getX()), Math.round(e.getY())); final Point clickPoint = MapViewMethodsClass.GetMapPointFromScreenPointFunction(mainMapView,screenPoint); Envelope mapEnvelope = MapViewMethodsClass.GetEnvelopeFromMapPointFunction( mainMapView,screenPoint,10); final MapQueryClass mapQueryClass = new MapQueryClass(); mapQueryClass.Select( mainFeatureLayer, mapEnvelope, new IQueryResult() { @Override public void getQuery() { List<MapQueryClass.MapQueryResult> mapQueryResults= mapQueryClass.getMapQueryResult(); for (MapQueryClass.MapQueryResult mapQueryResult:mapQueryResults ) { mapQueryResult.labelField = GetLayerLabelFieldName(mapQueryResult.featureLayer.getName()); //mapQueryResult.setFeatureLayerSelected(true); } HymnActivity.mainHymnActivity.ShowSearchResultFunction(mapQueryResults); } } ); return super.onSingleTapConfirmed(e); } }); }
StartMapTouchFunction
protected void StartMapTouchFunction(){ mainMapView.setOnTouchListener(new DefaultMapViewOnTouchListener(this,mainMapView) { @Override public boolean onSingleTapConfirmed(MotionEvent e) { if (canMapTouchidentity == false) { return super.onSingleTapConfirmed(e); } ClearLayerFunction(); android.graphics.Point screenPoint = new android.graphics.Point(Math.round(e.getX()), Math.round(e.getY())); Envelope mapEnvelope = MapViewMethodsClass.GetEnvelopeFromMapPointFunction(mainMapView,screenPoint,10); final MapQueryClass mapQueryClass = new MapQueryClass(); mapQueryClass.Select( mainReadOperationsFL, mapEnvelope, new IQueryResult() { @Override public void getQuery() { List<MapQueryClass.MapQueryResult> mapQueryResults= mapQueryClass.getMapQueryResult(); for (MapQueryClass.MapQueryResult mapQueryResult:mapQueryResults ) { mapQueryResult.labelField = GetLayerLabelFieldName(mapQueryResult.featureLayer.getName()); //mapQueryResult.setFeatureLayerSelected(true); } HymnActivity.mainHymnActivity.ShowSearchResultFunction(mapQueryResults); } } ); return super.onSingleTapConfirmed(e); } }); }
ShowMapCallOutFunction
public void ShowMapCallOutFunction(Feature feature){ TextView calloutContent = new TextView(getApplicationContext()); calloutContent.setTextColor(Color.BLACK); calloutContent.setSingleLine(false); calloutContent.setVerticalScrollBarEnabled(true); calloutContent.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET); calloutContent.setMovementMethod(new ScrollingMovementMethod()); calloutContent.setMaxWidth(600); calloutContent.setLines(5); calloutContent.setText( AttributeMethodsClass.GetCalloutStringByAttributeFunction( feature.getAttributes())); mainCallout.setLocation(GeometryMethodsClass.GetFeatureCenterFunction(feature)); mainCallout.setContent(calloutContent); mainCallout.show(); }
查询结果的承载 - AnimatedExpandableListView
对AnimatedExpandableListView感兴趣的可参考
https://github.com/idunnololz/AnimatedExpandableListView
main_search_result_group_item.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingRight="10dp" android:paddingLeft="40dp"> <TextView android:paddingTop="10dp" android:paddingBottom="10dp" android:id="@+id/resultGroupContainer" android:layout_width="wrap_content" android:layout_height="wrap_content" tools:layout_editor_absoluteY="0dp" android:layout_marginLeft="0dp" app:layout_constraintLeft_toLeftOf="parent" /> <TextView android:paddingTop="10dp" android:paddingBottom="10dp" android:text="10" android:id="@+id/resultGroupCountContainer" android:layout_width="wrap_content" android:layout_height="wrap_content" tools:layout_editor_absoluteY="0dp" android:layout_marginRight="8dp" app:layout_constraintRight_toRightOf="parent" /> </android.support.constraint.ConstraintLayout>
main_search_result_list_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingRight="10dp" android:paddingLeft="50dp"> <TextView android:paddingTop="10dp" android:paddingBottom="10dp" android:id="@+id/resultListContainer" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
SearchResultAdapter.java
package esrichina.hymn.usingmappingbyhymnlocal.Adapters; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.esri.arcgisruntime.data.Feature; import com.esri.arcgisruntime.layers.FeatureLayer; import java.util.ArrayList; import java.util.List; import esrichina.hymn.ListView.AnimatedExpandableListView; import esrichina.hymn.MapQuery.MapQueryClass; import esrichina.hymn.usingmappingbyhymnlocal.R; /** * Created by HymnHan on 2017/5/17. */ public class SearchResultAdapter extends AnimatedExpandableListView.AnimatedExpandableListAdapter { private LayoutInflater inflater; private List<MapQueryClass.MapQueryResult> items = new ArrayList<>(); public SearchResultAdapter(Context context) { inflater = LayoutInflater.from(context); } public void setData(List<MapQueryClass.MapQueryResult> items) { this.items = items; } @Override public Feature getChild(int groupPosition, int childPosition) { return items.get(groupPosition).features.get(childPosition); } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public View getRealChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { ChildHolder holder; MapQueryClass.MapQueryResult mapQueryResult = getGroup(groupPosition); if (convertView == null) { holder = new ChildHolder(); convertView = inflater.inflate(R.layout.main_search_result_list_item, parent, false); holder.title = (TextView) convertView.findViewById(R.id.resultListContainer); convertView.setTag(holder); } else { holder = (ChildHolder) convertView.getTag(); } holder.title.setText(mapQueryResult.getTitle(childPosition)); holder.mapQueryResult = mapQueryResult; //holder.hint.setText(item.hint); return convertView; } @Override public int getRealChildrenCount(int groupPosition) { return items.get(groupPosition).features.size(); } @Override public MapQueryClass.MapQueryResult getGroup(int groupPosition) { return items.get(groupPosition); } @Override public int getGroupCount() { return items.size(); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { GroupHolder holder; MapQueryClass.MapQueryResult mapQueryResult = getGroup(groupPosition); if (convertView == null) { holder = new GroupHolder(); convertView = inflater.inflate(R.layout.main_search_result_group_item, parent, false); holder.title = (TextView) convertView.findViewById(R.id.resultGroupContainer); holder.count = (TextView) convertView.findViewById(R.id.resultGroupCountContainer); convertView.setTag(holder); } else { holder = (GroupHolder) convertView.getTag(); } holder.title.setText(mapQueryResult.getLayerTitle()); holder.count.setText("共 " + String.valueOf(mapQueryResult.getFeatureCount()) + " 条"); holder.mapQueryResult = mapQueryResult; return convertView; } @Override public boolean hasStableIds() { return true; } @Override public boolean isChildSelectable(int arg0, int arg1) { return true; } public static class ChildHolder { public TextView title; public MapQueryClass.MapQueryResult mapQueryResult; } public static class GroupHolder { public TextView title; public TextView count; public MapQueryClass.MapQueryResult mapQueryResult; } }
SearchResultComponent.java
package esrichina.hymn.usingmappingbyhymnlocal.Components; import android.view.View; import android.widget.ExpandableListView; import com.esri.arcgisruntime.data.Feature; import java.util.ArrayList; import java.util.List; import esrichina.hymn.ListView.AnimatedExpandableListView; import esrichina.hymn.MapQuery.MapQueryClass; import esrichina.hymn.Methods.MapViewMethodsClass; import esrichina.hymn.usingmappingbyhymnlocal.Adapters.SearchResultAdapter; import esrichina.hymn.usingmappingbyhymnlocal.R; /** * Created by HymnHan on 2017/5/19. */ public class SearchResultComponent extends BaseComponent { private AnimatedExpandableListView searchResultContainer; private SearchResultAdapter searchResultAdapter; public SearchResultComponent() { searchResultAdapter = new SearchResultAdapter(mainHymnActivity); searchResultContainer = (AnimatedExpandableListView) mainHymnActivity.findViewById(R.id.searchResultContainer); searchResultContainer.setAdapter(searchResultAdapter); searchResultContainer.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { SearchResultAdapter.ChildHolder childHolder = (SearchResultAdapter.ChildHolder) v.getTag(); Feature feature = childHolder.mapQueryResult.features.get(childPosition); MapViewMethodsClass.CenterMapViewByGeometryFunction( mainHymnActivity.getMainMapView(), feature, 10); childHolder.mapQueryResult.selectFeature(feature); mainConfigurations.ShowMapCallOutFunction(feature); return false; } }); } public void ClearSearchResultFunction() { searchResultAdapter.setData(new ArrayList<MapQueryClass.MapQueryResult>()); searchResultAdapter.notifyDataSetChanged(); } public void ShowSearchResultFunction(List<MapQueryClass.MapQueryResult> mapQueryResults) { searchResultAdapter.setData(mapQueryResults); searchResultAdapter.notifyDataSetChanged(); searchResultContainer.expandGroupWithAnimation(0); } }
查询结果的承载 - SlidingUpPanelLayout
对SlidingUpPanelLayout感兴趣的可参考
https://github.com/umano/AndroidSlidingUpPanel
<esrichina.hymn.DragUpPanel.SlidingUpPanelLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/mainSliding" android:gravity="bottom" app:umanoPanelHeight="20dp" app:umanoShadowHeight="4dp" app:umanoParallaxOffset="100dp" app:umanoDragView="@+id/dragView" app:umanoOverlay="false" app:umanoScrollableView="@+id/searchResultContainer" app:umanoAnchorPoint="0.565" app:umanoFadeColor="@color/geometry_swatch_background" app:umanoInitialState="hidden"> <android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <include layout="@layout/main_map_container"/> <include layout="@layout/main_activity_header_container"/> </android.support.design.widget.CoordinatorLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffffff" android:orientation="vertical" android:clickable="true" android:focusable="false" android:id="@+id/dragView"> <LinearLayout android:layout_width="match_parent" android:layout_height="@dimen/bottom_panel_header" android:orientation="horizontal" android:background="@color/bootstrap_brand_info"> </LinearLayout> <include layout="@layout/main_search_result_container"/> </LinearLayout> </esrichina.hymn.DragUpPanel.SlidingUpPanelLayout>
查询结果的清除
相关文章推荐
- 安卓智能地图开发与实施七:在线业务图层(浏览查询) - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施十一:业务数据查询 - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施三:创建第一个地图程序 - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施二十:栅格图层展示 - ArcGIS Runtime SDK for Android(Version 100.1.0)
- 安卓智能地图开发与实施十:图层管理 - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施一:配置离线SDK - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施四:二维地图的MapView与Layers - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施五:在线基础底图 - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施六:离线基础底图 - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施十五:离线与同步 - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施二十二:展示三维场景 - ArcGIS Runtime SDK for Android(Version 100.1.0)
- 安卓智能地图开发与实施九:地图缩放与旋转 - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施二:开发环境准备 - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施十八:空间要素绘制 - ArcGIS Runtime SDK for Android(Version 100.1.0)
- 安卓智能地图开发与实施十四:业务数据编辑 - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施二十四:关于源代码的放送 - ArcGIS Runtime SDK for Android(Version 100.1.0)
- 安卓智能地图开发与实施二十三:三维场景中的可视化 - ArcGIS Runtime SDK for Android(Version 100.1.0)
- 安卓智能地图开发与实施十二:空间查询与模糊搜索 - ArcGIS Runtime SDK for Android(Version 100.0.0)
- 安卓智能地图开发与实施二十五:Shapefile文件的可视化与编辑 - ArcGIS Runtime SDK for Android(Version 100.2.0)
- 安卓智能地图开发与实施十六:三维地图 - ArcGIS Runtime SDK for Android(Version 100.1.0)