接着《ArcGIS for Android 例子Offline Editor (BETA)(二)》,要实现在下载完GBD之后,点击编辑按钮,弹出模版来给我们选择的这个弹出框。这个弹出框是使用PopupWindow来实现的。
1、 定义一个类TemplatePicker,继承PopupWindow,类中的变量如下:
private Context context;
private MapView mapView;
private FeatureTemplate selectTemplate;//选择的FeatureTemplate
private FeatureLayer selectFeatureLayer;//被选择编辑的FeatureLayer
private Symbol selectSymbol;//被选择的符号
其中selectTemplate,selectFeatureLayer,selectSymbol分别用来当点击要某一类型要素时,保存要编辑要素的FeatureTemplate,要编辑的Layer,要编辑要素的Symbol。接下来用context,和mapView实现类的构造函数和selectTemplate,selectFeatureLayer,selectSymbol这三个的get方法,并设置PopupWindow一些参数:
public TemplatePicker(Context context, MapView mapView) {
this.context = context;
this.mapView = mapView;
//设置包含的View
setContentView(setView());
Display display= ((Activity)context).getWindowManager().getDefaultDisplay();
//设置宽度
setWidth(display.getWidth());
//设置高度
setHeight(300);
setFocusable(true);
setBackgroundDrawable(new BitmapDrawable());
}
public FeatureTemplate getSelectTemplate() {
return selectTemplate;
}
public FeatureLayer getSelectFeatureLayer() {
return selectFeatureLayer;
}
public Symbol getSelectSymbol() {
return selectSymbol;
}
2、 既然有存储要编辑的图层,要编辑要素的symbol,就还要有个方法清除这些存储:
//清楚选择
public void clearSelection(){
selectFeatureLayer=null;
selectTemplate=null;
}
3 、在构造函数中有个setView()方法未实现,这个方法主要返回一个View给PopupWindow来显示,这个View的布局有点复杂,见下图:
布局的最外围是一个ScrollView和LinerLayout,能够进行上下滚动,往里,每个FeatureLayer都有个RelativeLayout,用来包含图层名和图层中图例。在RelativeLayout最上方是一个TextView用来显示图层名,下方是一个HorizontalScrollView包裹这个一个横向的LinerLayout,用来显示整个图层的图例,在LinerLayout中包含多个竖向的LinerLayout,用于包含每种类型要素的图例,图例的图案使用ImageButton来显示,图例名使用TextView。接下来就按照布局来敲代码:
/**
* 构建PopupWindow的ContentView
*/
private View setView(){
//最外层的ScrollView
ScrollView scrollTemplateGroup =new ScrollView(context);
scrollTemplateGroup.setVerticalScrollBarEnabled(true);
scrollTemplateGroup.setScrollBarStyle(ScrollView.SCROLLBARS_INSIDE_INSET);
//最外层的LinearLayout
LinearLayout templateGroup=new LinearLayout(context);
templateGroup.setOrientation(LinearLayout.VERTICAL);
templateGroup.setPadding(10, 10, 10, 10);
templateGroup.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
templateGroup.setBackgroundResource(R.drawable.popupbg);
Layer[] layers=mapView.getLayers();
int layercount=0;
//遍历FeatureLayer
for(Layer layer :layers){
if(layer instanceof FeatureLayer){
layercount++;
//每个FeatureLayer所占用的RelativeLayout
RelativeLayout templateLayout=new RelativeLayout(context);
templateLayout.setPadding(10, 10, 10, 10);
templateLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
//用来显示图层名
TextView layerName=new TextView(context);
layerName.setPadding(5, 5, 5, 5);
layerName.setText(layer.getName());
layerName.setTextColor(Color.MAGENTA);
layerName.setId(1);
//用来显示每个图层图例的HorizontalScrollView
HorizontalScrollView scrollTemplateAndType=new HorizontalScrollView(context);
scrollTemplateAndType.setPadding(5, 5, 5, 5);
//设置scrollTemplateAndType的相对位置,是其在layerName的下方
RelativeLayout.LayoutParams relParams=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
relParams.addRule(RelativeLayout.BELOW, layerName.getId());
//用来显示每个图层图例的LinearLayout
LinearLayout layerTemplate=new LinearLayout(context);
layerTemplate.setBackgroundColor(Color.WHITE);
layerTemplate.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
//取得TypeIdField
String typeFileid= ((GdbFeatureTable)(((FeatureLayer)layer).getFeatureTable())).getTypeIdField();
if(typeFileid.equalsIgnoreCase("")){//TypeIdField没有值
//获取图层中的FeatureTemplate
List<FeatureTemplate> templates= ((GdbFeatureTable)(((FeatureLayer)layer).getFeatureTable())).getFeatureTemplates();
//从templates构造出图例
for(FeatureTemplate template :templates){
try {
//根据FeatureTemplate生成GdbFeature
GdbFeature feature= ((GdbFeatureTable)(((FeatureLayer)layer).getFeatureTable())).createFeatureWithTemplate(template, null);
//我感觉用下面这个也能获取到Symbol,但是结果在显示线符号的会不正确,点/面符号能正常显示,求解释!!!
//Symbol symbol= feature.getSymbol();
Renderer renderer = ((FeatureLayer) layer).getRenderer();
//获取符号
Symbol symbol = renderer.getSymbol(feature);
//得到代表图例的图片
Bitmap bitmap=createBitmapFromSymbol(symbol,layer);
//设置图例的布局和点击事件
populateTemplateView(layerTemplate,bitmap,template,symbol,(FeatureLayer)layer);
} catch (Exception e) {
e.printStackTrace();
}
}
}else{//TypeIdField有值
List<FeatureType> featureTypes= ((GdbFeatureTable)(((FeatureLayer)layer).getFeatureTable())).getFeatureTypes();
for(FeatureType featureType :featureTypes){
FeatureTemplate[] templates= featureType.getTemplates();
for(FeatureTemplate template :templates){
try {
//根据FeatureTemplate生成GdbFeature
GdbFeature feature= ((GdbFeatureTable)(((FeatureLayer)layer).getFeatureTable())).createFeatureWithTemplate(template, null);
Renderer renderer = ((FeatureLayer) layer).getRenderer();
//获取符号
Symbol symbol = renderer.getSymbol(feature);
//得到代表图例的图片
Bitmap bitmap=createBitmapFromSymbol(symbol,layer);
//设置图例的布局和点击事件
populateTemplateView(layerTemplate,bitmap,template,symbol,(FeatureLayer)layer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
scrollTemplateAndType.addView(layerTemplate);
templateLayout.addView(layerName);
templateLayout.addView(scrollTemplateAndType, relParams);
//加到templateGroup
templateGroup.addView(templateLayout);
}
}
Log.i("layout", layercount+"");
//加到scrollTemplateGroup中
scrollTemplateGroup.addView(templateGroup);
return scrollTemplateGroup;
}
//设置图例的布局和点击事件
private void populateTemplateView( LinearLayout layout,Bitmap bitmap,
final FeatureTemplate template, final Symbol symbol, final FeatureLayer layer) {
//单个图例和图例名称所占用的LinearLayout
LinearLayout templateAndType=new LinearLayout(context);
templateAndType.setOrientation(LinearLayout.VERTICAL);
templateAndType.setPadding(5, 5, 5, 5);
templateAndType.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
//图例的图片以ImageButton形式显示
ImageButton imageBtn=new ImageButton(context);
imageBtn.setImageBitmap(bitmap);
imageBtn.setBackgroundColor(Color.WHITE);
//设置imageBtn的点击事件
imageBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
selectFeatureLayer=layer;
selectSymbol=symbol;
selectTemplate=template;
//隐藏PopupWindow
dismiss();
}
});
//显示图例名
TextView lengName=new TextView(context);
lengName.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
lengName.setPadding(5, 5, 5, 5);
lengName.setText(template.getName());
templateAndType.addView(imageBtn);
templateAndType.addView(lengName);
layout.addView(templateAndType);
}
//根据Symbol和Layer来创建相对应的图例
private Bitmap createBitmapFromSymbol(Symbol symbol,Layer layer) {
Bitmap bitmap=null;
Type type= ((FeatureLayer)layer).getGeometryType();
//跟不同的Type来创建不同的图例
if(type.equals(Type.POINT)){//点图层
Point point=new Point(20, 20);
bitmap=SymbolHelper.getLegendImage(symbol, point, 50, 50, Color.WHITE);
}else if(type.equals(Type.POLYLINE)){//线图层
Polyline polyLine=new Polyline();
polyLine.startPath(0,0);
polyLine.lineTo(40,40);
bitmap=SymbolHelper.getLegendImage(symbol, polyLine, 50, 50, Color.WHITE);
}else if(type.equals(Type.POLYGON)){//面图层
Polygon polygon=new Polygon();
polygon.startPath(0, 0);
polygon.lineTo(40, 0);
polygon.lineTo(40, 40);
polygon.lineTo(0, 40);
polygon.lineTo(0, 0);
bitmap=SymbolHelper.getLegendImage(symbol, polygon, 50, 50, Color.WHITE);
}
return bitmap;
}
在取每类要素的Symbol,我第一感觉是使用GdbFeature的getSymbol()来取,但是结果线的Symbol不能正常显示,只能改用例子中先取得FeatureLayer的Renderer,在从Renderer中取得Symbol,我也不知道为神马不能直接从GdbFeature中来取得Symbol,求解释。
4、 接下来,回到OfflineEditorActivity中,新建个变量,并实现其set和get方法
TemplatePicker tp;
public TemplatePicker getTp() {
return tp;
}
public void setTp(TemplatePicker tp) {
this.tp = tp;
}
在编辑按钮中加入如下代码,测试下TemplatePicker的popupWindow能不能正常显示:
/**
* 编辑
*/
public void editButton(View v) {
if(getTp()==null){
tp=new TemplatePicker(this, mMapView);
tp.showAtLocation(btn_edit, Gravity.BOTTOM, 0, 0);
}
}
部署到模拟器上,点下载GDB,等GDB下载完之后,切换到编辑选项卡,点编辑按钮,出来如下图: