移动图例过滤功能 · Fellow Travellers
简介
图例过滤是对于多图例图层的一种查看方式,这种查看方式方便对特定类型的图块进行统一查看。多图例图层一般为DynamicLayer与FeatureLayer,而且单个图例的图层与多个图例的图层,其渲染器也是不同的,单个图例的为SimpleRenderer,多个图例为UniqueValueRenderer。
在本文中,图例过滤主要为对图例进行特定过滤达到多图层互斥过滤的效果,另外对于在线图例过滤使用了Layer Definition进行图层Visible控制问题。
实现逻辑略析
- 可视化与相关功能操作监听的基本实现
- 加载功能基础的分析操作图层与其图例
- 单个图例的点击并获取其LabelName
- 在线将ArcGisDynamicServiceLayer通过ArcGisFeatureLayer加载,并获取其Renderer转为UniqueValueRenderer(离线获取FeatureLayer的Renderer) 并获取Render中的Feild1字段(配置的过滤字段)
- WhereClause语句的拼接(过滤字段与LabelName中的值拼接成Sql Where语句)
-
在线通过设置ArcGisDynamicServiceLayer的LayerDefinition(离线通过设置FeatureLayer的DefinitionExpression)进行过滤
-
对于在线DynamicLayer多图层控制显示问题,将Visible控制可视改为Layer Definition控制可视,只维护一套属性。
重要部分代码实现
1.LayerDefinition控制可视
/**
** 根据visibleIds 更新DynamicLayer 通过DynamicLayer的Definition进行控制显示
** Definition中 1-> “1=1” 表示图层 1 全部显示
**/
//要存储的LayerDefinitions
Map<String, Map<Integer, String>> dynamicLayerDefinitionMap = TotalApplication.getDynamicLayerDefinitionMap();
//要操作的LayerDefinitions
Map<Integer, String> layerDefinitions = dynamicLayer.getLayerDefinitions();
if (layerDefinitions==null) {
layerDefinitions=new HashMap<>();
}
if (isOpenLayer) {
//显示
if (dynamicLayerDefinitionMap.containsKey(dynamicLayer.getUrl())) {
//从存储语句中获取之前的过滤语句
for (int visibleId : visibleIds) {
Map<Integer, String> integerStringMap = dynamicLayerDefinitionMap.get(dynamicLayer.getUrl());
if (integerStringMap.containsKey(visibleId)
&&integerStringMap.get(visibleId)!=null
&&!Constants.SQL_FALSE.equalsIgnoreCase(integerStringMap.get(visibleId))) {
//已存该layer的id的Layer Definition Sql 语句
layerDefinitions.put(visibleId,integerStringMap.get(visibleId));
}else {
//全部显示
layerDefinitions.put(visibleId,Constants.SQL_TURE);
}
}
}else {
//全部显示
for (int visibleId : visibleIds) {
layerDefinitions.put(visibleId,Constants.SQL_TURE);
}
}
}else {
//关闭
if (!layerDefinitions.isEmpty()) {
Map<Integer, String> integerStringMap;
if (dynamicLayerDefinitionMap.containsKey(dynamicLayer.getUrl())) {
//存储中有这个Layer的Definition
integerStringMap = dynamicLayerDefinitionMap.get(dynamicLayer.getUrl());
}else {
//存储中没有这个layer的definition
integerStringMap=new HashMap<>();
}
for (int visibleId : visibleIds) {
if (layerDefinitions.containsKey(visibleId)
&&layerDefinitions.get(visibleId)!=null
&&!Constants.SQL_FALSE.equalsIgnoreCase(layerDefinitions.get(visibleId))) {
//有可视语句,进行储存
integerStringMap.put(visibleId,layerDefinitions.get(visibleId));
}
//取消可视
layerDefinitions.put(visibleId,Constants.SQL_FALSE);
}
TotalApplication.getDynamicLayerDefinitionMap().put(dynamicLayer.getUrl(),integerStringMap);
}else {
//一般走不到这,避免花里胡哨的操作
for (int visibleId : visibleIds) {
//取消可视
layerDefinitions.put(visibleId,Constants.SQL_FALSE);
}
}
}
dynamicLayer.setLayerDefinitions(layerDefinitions);
dynamicLayer.refresh();
2.Render获取与过滤字段获取
离线获取
离线用的FeatureLayer.getRenderer()
FeatureLayer featureLayer= (FeatureLayer) layer;
//判断是否获取过,避免重复查询
if (TotalApplication.getInstanceFilterFieldMap().containsKey(layerName)) {
filterField=TotalApplication.getInstanceFilterFieldMap().get(layerName);
}else{
//记录已查询 以免无结果 重复查询
TotalApplication.getInstanceFilterFieldMap().put(layerName,Constants.NO_FILTER_FIELD);
filterField=Constants.NO_FILTER_FIELD;
//获取过滤字段
Renderer renderer = featureLayer.getRenderer();
if (renderer instanceof UniqueValueRenderer) {
UniqueValueRenderer uniqueValueRenderer= (UniqueValueRenderer) renderer;
filterField = uniqueValueRenderer.getField1();
TotalApplication.getInstanceFilterFieldMap().put(layerName,filterField);
}
}
在线获取
在线通过加载ArcGisFeatureLayer获取Renderer中的过滤字段
//Renderer中过滤字段的查询和保存,避免重复加载 例:RDDM
if (TotalApplication.getInstanceFilterFieldMap().keySet().contains(url+Constants.SPLIT_SYMBOL[4]+layerID)) {
//通知过滤
}else{
final ArcGISFeatureLayer arcGISFeatureLayer= new ArcGISFeatureLayer(url+Constants.SPLIT_SYMBOL[4]+layerID, ArcGISFeatureLayer.MODE.SELECTION);
final String finalUrl = url;
final String finalLayerID = layerID;
arcGISFeatureLayer.setOnStatusChangedListener(new OnStatusChangedListener() {
@Override
public void onStatusChanged(Object o, STATUS status) {
if (status== STATUS.INITIALIZED) {
//记录已查询 以免无结果 重复查询
TotalApplication.getInstanceFilterFieldMap().put(arcGISFeatureLayer.getUrl(),Constants.NO_FILTER_FIELD);
Renderer renderer = arcGISFeatureLayer.getRenderer();
if (renderer!=null) {
if (renderer instanceof UniqueValueRenderer) {
UniqueValueRenderer uniqueValueRenderer= (UniqueValueRenderer) renderer;
//获取过滤字段 RDDM
String filterField = uniqueValueRenderer.getField1();
if (filterField!=null&&!filterField.isEmpty()) {
TotalApplication.getInstanceFilterFieldMap().put(arcGISFeatureLayer.getUrl(),filterField);
}
}
}
//通知过滤
}
}
});
}
3.图例过滤
离线过滤
离线用的FeatureLayer过滤 FeatureLayer的LayerDefinition为 String (Sql Where Clause),
无需控制图层,且可以和Visible混合使用
//图例过滤 例:YDDM = 'mc'
featureLayer.setDefinitionExpression(filterField+Constants.WHERE_EQUAL+Constants.WHERE_QUOTATION_MARKS+finalLegendLabel+Constants.WHERE_QUOTATION_MARKS);
在线过滤
在线用的ArcGISDynamicMapServiceLayer过滤
ArcGISDynamicMapServiceLayer的LayerDefinition为Map< int(layerId) , String(Sql Where Clause) >,
得到所需数据进行过滤
//图例过滤
if (filterField!=null&&!Constants.NO_FILTER_FIELD.equalsIgnoreCase(filterField)&&!filterField.isEmpty()) {
if (layer instanceof ArcGISDynamicMapServiceLayer) {
//拼组Sql Where clause 并设置LayerDefinitions 进行过滤
Map<Integer, String> layerDefinitions = ((ArcGISDynamicMapServiceLayer) layer).getLayerDefinitions();
if (layerDefinitions==null) {
layerDefinitions=new HashMap<Integer, String>();
}
//map中: layerId -> where clause YDDM = 'G1'
layerDefinitions.put(Integer.parseInt(layerId),filterField+Constants.WHERE_EQUAL+Constants.WHERE_QUOTATION_MARKS+legendName+Constants.WHERE_QUOTATION_MARKS);
((ArcGISDynamicMapServiceLayer) layer).setLayerDefinitions(layerDefinitions);
((ArcGISDynamicMapServiceLayer) layer).refresh();
}
}
4.结束过滤(全部显示)
离线结束过滤
Map<String, Layer> layerMap = TotalApplication.getInstanceAllLayerMap();
if (layerMap.containsKey(name)) {
Layer layer = layerMap.get(name);
if (layer instanceof FeatureLayer) {
//设置LayerDefinition
((FeatureLayer) layer).setDefinitionExpression(Constants.SQL_TURE);
//数据改变
legendAdapter.selectLabel= Constants.NO_SELECT;
TotalApplication.getLayerSelectLabelMap().put(name,Constants.NO_SELECT);
legendAdapter.notifyDataSetChanged();
}
}
//获取当前layer对应的Service Layer 的URL与Id
List<ThemeInfo> theme = oneMapActivity.mDataSource.getTheme();
for (ThemeInfo themeInfo : theme) {
if (name.equalsIgnoreCase(themeInfo.getName())) {
serviceUID=themeInfo.getServiceUid();
layerID=themeInfo.getLayerId();
}
}
List<MapServicesInfo> mapServices = oneMapActivity.mDataSource.getMapServices();
for (MapServicesInfo mapService : mapServices) {
if (serviceUID!=null&&serviceUID.equalsIgnoreCase(mapService.getName())) {
url=mapService.getUrl();
}
}
//数据改变
legendAdapter.selectLabel= Constants.NO_SELECT;
TotalApplication.getLayerSelectLabelMap().put(name,Constants.NO_SELECT);
legendAdapter.notifyDataSetChanged();
//TODO 通知图例过滤
全部显示
if (layer instanceof ArcGISDynamicMapServiceLayer) {
Map<Integer, String> layerDefinitions = ((ArcGISDynamicMapServiceLayer) layer).getLayerDefinitions();
if (layerDefinitions==null){
layerDefinitions=new HashMap<Integer, String>();
}
layerDefinitions.put(Integer.parseInt(layerId),Constants.SQL_TURE);
((ArcGISDynamicMapServiceLayer) layer).setLayerDefinitions(layerDefinitions);
((ArcGISDynamicMapServiceLayer) layer).refresh();
}
结语
图例过滤功能的开发,既减少了用户手动查找相应地块和汇总的时间,提高了地图的可阅读性。让用户通过移动设备简单的操作地图中同一类型的地块汇总,并通过绘制图层让用户在地图上更直观的看清板块对象。