空间查询与展示

空间查询需要入口(屏幕触摸、文字输入,甚至绘制个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>

查询结果的清除

这里写图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐