編輯:關於Android編程
這個頁面用到了添加圖層,添加覆蓋物,覆蓋物的事件處理,地圖的旋轉、縮放,高德定位,地圖分層顯隱,關鍵詞搜索等功能。
本篇博客僅為了記錄相關功能實現的代碼塊,所以未進行排版梳理,對Arcgis有需求的,建議看官方文檔 或中文文檔 。
public class MidFragment extends BaseFragment {
private static final String TITLE = "中間";
private MapView mMapView;//地圖
private Button mLocateBT, mResetBT;//定位、重置按鈕
private RadioGroup mTypeRG;
private double latitude = 30.343112;//當前點緯度
private double longitude = 120.11522;//當前點經度
private ImageView mSouthIV;//指南針
private SensorManager mSensorManager;//方向傳感器
private GraphicsLayer mMyLayer;//當前位置的圖層
private int mMyUID;//當前位置的圖標ID
private PictureMarkerSymbol mLocationSymbol;//當前位置的圖標
private Callout mCallout;//地圖彈窗
private ArcGISDynamicMapServiceLayer mServiceLayer;
private String url = "http://192.168.1.235:6080/arcgis/rest/services/SanKeFolder/SanKe_0426/MapServer";
// private String url = "http://huangyi2016.iask.in:23527/arcgis/rest/services/SanKeFolder/SanKe_0426/MapServer";
// private String url = "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer";
private Point mClickPoint;//地圖點擊點
private IdentifyParameters params = null;//搜索條件
private boolean isNavigation = false;//是否是導航模式
private boolean isRomation = false;//是否正在旋轉
private float mMapDegree;//地圖旋轉角度
private float mSensorDegree;//傳感器角度
private int WKID_IN = 4326;//輸入坐標系
private int WKID_OUT = 4490;//輸出坐標系
private String stringBuffer = "經緯度:\n";
private TextView gpsTextView;
private EntScenicSpot mScenicSpot;//景點
private LinearLayout mBottomLL;//底部景點信息布局
private TextView mBottomNameTV, mBottomDetailTV;//景點名稱,景點詳情
private ImageView mBottomIV;//景點圖片
private boolean isBottomShow;//是否顯示底部景點信息
public static MidFragment getInstance() {
return new MidFragment();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (null == mView) {
mView = inflater.inflate(R.layout.fragment_mid, null);
}
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
protected void initView() {
mSensorManager = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE); // 獲得傳感器管理器
mCommonHeaderBar.initHeaderStyle(CommonHeaderBar.HeaderStyle.MIDTV);
mCommonHeaderBar.setMidText(TITLE);
mMapView = (MapView) findViewById(R.id.view_map);
mResetBT = (Button) findViewById(R.id.bt_reset);
mLocateBT = (Button) findViewById(R.id.bt_locate);
mSouthIV = (ImageView) findViewById(R.id.iv_south);
mTypeRG = (RadioGroup) findViewById(R.id.rg_type);
gpsTextView = (TextView) findViewById(R.id.tv_gps);
mBottomLL = (LinearLayout) findViewById(R.id.ll_bottom);
mBottomNameTV = (TextView) findViewById(R.id.tv_name);
mBottomDetailTV = (TextView) findViewById(R.id.tv_detail);
mBottomIV = (ImageView) findViewById(R.id.iv_info);
mCallout = mMapView.getCallout();//通過MapView獲取Callout實例對象
mCallout.setStyle(R.xml.mime_callout_style);//為Callout設置樣式文件
mLocationSymbol = new PictureMarkerSymbol(getActivity().getResources().getDrawable(R.drawable.ic_map_arrow));//設置當前點的圖標樣式
}
@Override
protected void initData() {
ArcGISRuntime.setClientId("9yNxBahuPiGPbsdi");//去水印
//獲取到經緯度就設置,沒有就設置默認的
latitude = SharePreferenceUtil.getInstance().getString("LATITUDE") == null ? 30 : Double.valueOf(SharePreferenceUtil.getInstance().getString("LATITUDE"));
longitude = SharePreferenceUtil.getInstance().getString("LONGTIUDE") == null ? 120 : Double.valueOf(SharePreferenceUtil.getInstance().getString("LONGTIUDE"));
Log.v("--->獲取", longitude + "/" + latitude);
Toast.makeText(getActivity(), longitude + "/" + latitude, Toast.LENGTH_LONG).show();
mServiceLayer = new ArcGISDynamicMapServiceLayer(url);//在線地圖
mMapView.addLayer(mServiceLayer);//添加圖層
mMapView.setAllowRotationByPinch(true); //是否允許使用Pinch方式旋轉地圖
mMapView.setMapBackground(getResources().getColor(R.color.white), getResources().getColor(R.color.white), 0, 0);//設置背景
//設置當前位置為中心點
Point wgsPoint = new Point(longitude, latitude);
Point mapPoint = (Point) GeometryEngine.project(wgsPoint, SpatialReference.create(WKID_IN), SpatialReference.create(WKID_OUT));
mMapView.centerAt(mapPoint, true);
Graphic graphic = new Graphic(mapPoint, mLocationSymbol);
mMyLayer = new GraphicsLayer();
mMyUID = mMyLayer.addGraphic(graphic);
mMapView.addLayer(mMyLayer);//添加覆蓋物圖層
// 限定當前顯示區域
// Unit mapUnit = SpatialReference.create(3857).getUnit();//mMapView.getSpatialReference().getUnit();
// double zoomWidth = Unit.convertUnits(10, Unit.create(LinearUnit.Code.MILE_US), mapUnit);
// Envelope zoomExtent = new Envelope(mapPoint, zoomWidth, zoomWidth);
// mMapView.setExtent(zoomExtent);
}
@Override
protected void initListener() {
mMapView.setOnStatusChangedListener(new OnStatusChangedListener() {//地圖的狀態監聽
@Override
public void onStatusChanged(Object o, STATUS status) {
if (status.equals(STATUS.INITIALIZED)) { //初始化完成才顯示,防止黑屏
mMapView.postDelayed(new Runnable() {
@Override
public void run() {
mMapView.setVisibility(View.VISIBLE);
}
}, 100);
}
}
});
mResetBT.setOnClickListener(new View.OnClickListener() {//重置
@Override
public void onClick(View v) {
isNavigation = false;//關閉導航模式
mMapView.setRotationAngle(0); //初始化時地圖角度,參數為正時按逆時針方向旋轉
Point wgsPoint = new Point(longitude, latitude);
Point mapPoint = (Point) GeometryEngine.project(wgsPoint, SpatialReference.create(WKID_IN), SpatialReference.create(WKID_OUT));
mMapView.centerAt(mapPoint, true);
mSouthIV.setRotation(0);
// gpsTextView.setVisibility(View.INVISIBLE);
}
});
mLocateBT.setOnClickListener(new View.OnClickListener() {//定位
@Override
public void onClick(View v) {
isNavigation = true;//啟動導航模式
//當前位置圖標的更新
Point wgsPoint = new Point(longitude, latitude);
Point mapPoint = (Point) GeometryEngine.project(wgsPoint, SpatialReference.create(WKID_IN), SpatialReference.create(WKID_OUT));
mLocationSymbol.setAngle(0);
mMapView.centerAt(mapPoint, true);
Graphic graphic = new Graphic(mapPoint, mLocationSymbol);
mMyLayer.updateGraphic(mMyUID, graphic);
// gpsTextView.setVisibility(View.VISIBLE);
// gpsTextView.setText(stringBuffer);
}
});
mMapView.setOnPinchListener(new OnPinchListener() {//地圖旋轉監聽
@Override
public void prePointersMove(float v, float v1, float v2, float v3, double v4) {
}
@Override
public void postPointersMove(float v, float v1, float v2, float v3, double v4) {
mSouthIV.post(new Runnable() {
@Override
public void run() {
mMapDegree = (float) mMapView.getRotationAngle();
mSouthIV.setRotation(-mMapDegree);
}
});
}
@Override
public void prePointersDown(float v, float v1, float v2, float v3, double v4) {
}
@Override
public void postPointersDown(float v, float v1, float v2, float v3, double v4) {
isRomation = true;
}
@Override
public void prePointersUp(float v, float v1, float v2, float v3, double v4) {
}
@Override
public void postPointersUp(float v, float v1, float v2, float v3, double v4) {
isRomation = false;
}
});
//高德定位監聽
ToolGDLocate.initNewInstance(getActivity());
ToolGDLocate.startLocate(new ToolGDLocate.GDListener() {
@Override
public void onLocationChanged(AMapLocation amapLocation) {
if (Math.abs(amapLocation.getLatitude() - latitude) > 0.00005 || Math.abs(amapLocation.getLongitude() - longitude) > 0.00005) {
stringBuffer += (longitude + " - " + latitude + "\n");
}
longitude = amapLocation.getLongitude();
latitude = amapLocation.getLatitude();
Point wgsPoint = new Point(longitude, latitude);
Point mapPoint = (Point) GeometryEngine.project(wgsPoint, SpatialReference.create(WKID_IN), SpatialReference.create(WKID_OUT));
Graphic graphic = new Graphic(mapPoint, mLocationSymbol);
mMyLayer.updateGraphic(mMyUID, graphic);
Log.v("--->更新", longitude + "/" + latitude);
}
});
mMapView.setOnSingleTapListener(//覆蓋物監聽
new OnSingleTapListener() {
@Override
public void onSingleTap(float v, float v1) {
if (!mMapView.isLoaded())
return;
mCallout.hide();
View mView = LayoutInflater.from(getActivity()).inflate(R.layout.view_callout_locate, null);//彈出窗口布局文件對象
int[] graphicIDs = mMyLayer.getGraphicIDs(v, v1, 25);
if (graphicIDs != null && graphicIDs.length > 0) {
Graphic gr = mMyLayer.getGraphic(graphicIDs[0]);
Point location = (Point) gr.getGeometry();
mCallout.setOffset(0, -15);//設置偏移量
mCallout.show(location, mView);//設置彈出窗顯示的內容
}
mClickPoint = mMapView.toMapPoint(v, v1);
//關鍵詞查詢設置
String targetLayer = url.concat("/0");
// String[] queryArray = {targetLayer, "Name = '廁所'"};
String[] queryArray = {targetLayer, "Message like '%廁所%'"};
AsyncQueryTask ayncQuery = new AsyncQueryTask();
ayncQuery.execute(queryArray);
//觸碰點查詢設置
params = new IdentifyParameters();
params.setTolerance(20);
params.setDPI(98);
// params.setLayers(new int[]{4});
params.setLayerMode(IdentifyParameters.ALL_LAYERS);
params.setGeometry(mClickPoint);
params.setSpatialReference(mMapView.getSpatialReference());
params.setMapHeight(mMapView.getHeight());
params.setMapWidth(mMapView.getWidth());
params.setReturnGeometry(true);
// add the area of extent to identify parameters
Envelope env = new Envelope();
mMapView.getExtent().queryEnvelope(env);
params.setMapExtent(env);
// execute the identify task off UI thread
MyIdentifyTask mTask = new MyIdentifyTask(mClickPoint);
mTask.execute(params);
}
}
);
mTypeRG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.rb_map_all:
mServiceLayer.setVisible(true);
break;
case R.id.rb_map_point:
mServiceLayer.setVisible(false);
break;
case R.id.rb_map_wc:
ArcGISLayerInfo[] infos = mServiceLayer.getLayers();
infos[0].setVisible(true);
mServiceLayer.refresh();
break;
case R.id.rb_map_store:
ArcGISLayerInfo[] infoss = mServiceLayer.getLayers();
infoss[0].setVisible(false);
mServiceLayer.refresh();
break;
case R.id.rb_map_door:
break;
}
}
});
mBottomLL.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getActivity(), "跳轉更多", Toast.LENGTH_SHORT).show();
}
});
}
//關鍵字查詢
private class AsyncQueryTask extends AsyncTask {
@Override
protected FeatureResult doInBackground(String... queryArray) {
if (queryArray == null || queryArray.length <= 1)
return null;
String url = queryArray[0];
QueryParameters qParameters = new QueryParameters();
String whereClause = queryArray[1];
SpatialReference sr = SpatialReference.create(102100);
// qParameters.setGeometry(mMapView.getExtent());
// qParameters.setGeometry(mClickPoint);
qParameters.setOutSpatialReference(sr);
qParameters.setReturnGeometry(true);
qParameters.setWhere(whereClause);
QueryTask qTask = new QueryTask(url);
try {
return qTask.execute(qParameters);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(FeatureResult results) {
if (results != null) {
// Toast.makeText(getActivity(), "您找到了一個廁所", Toast.LENGTH_SHORT).show();
for (Object element : results) {
if (element instanceof Feature) {
Feature feature = (Feature) element;
Graphic graphic = new Graphic(feature.getGeometry(), feature.getSymbol(), feature.getAttributes());
// graphicsLayer.addGraphic(graphic);
//結果添加事件
mCallout.hide();
View mView = LayoutInflater.from(getActivity()).inflate(R.layout.view_callout_locate, null);//彈出窗口布局文件對象
Point location = (Point) graphic.getGeometry();
mCallout.setOffset(0, -15);//設置偏移量
mCallout.show(location, mView);//設置彈出窗顯示的內容
}
}
}
}
}
//觸碰點查詢
private class MyIdentifyTask extends AsyncTask {
IdentifyTask task = new IdentifyTask(url);
IdentifyResult[] M_Result;
Point mAnchor;
MyIdentifyTask(Point anchorPoint) {
mAnchor = anchorPoint;
}
protected IdentifyResult[] doInBackground(IdentifyParameters... params) {
if (params != null && params.length > 0) {
IdentifyParameters mParams = params[0];
try {
M_Result = task.execute(mParams);
} catch (Exception e) {
e.printStackTrace();
}
}
return M_Result;
}
@Override
protected void onPostExecute(IdentifyResult[] results) {
if (results != null && results.length > 0) {
Log.v("-->", results[0].getDisplayFieldName());
mCallout.hide();
if (results[0].getAttributes().get("Name") != null && results[0].getAttributes().get("Name").equals("洗手間")) {
View mView = LayoutInflater.from(getActivity()).inflate(R.layout.view_callout_locate, null);//彈出窗口布局文件對象
Geometry geometry = results[0].getGeometry();
mCallout.setOffset(0, -15);//設置偏移量
mCallout.show((Point) geometry, mView);//設置彈出窗顯示的內容
} else if (results[0].getAttributes().get("SHAPE") != null && results[0].getAttributes().get("SHAPE").equals("點")) {
if (results[0].getAttributes().get("Message") != null)
getScenicSpot(results[0].getAttributes().get("Message").toString());
} else if (results[0].getAttributes().get("SHAPE") == null && isBottomShow) {
showBottom(false);
} else if (results[0].getAttributes().get("SHAPE") != null && !results[0].getAttributes().get("SHAPE").equals("點") && isBottomShow) {
showBottom(false);
}
} else if (isBottomShow) {
showBottom(false);
}
// ArrayList resultList = new ArrayList();
//
// IdentifyResult result_1;
//
// for (int index = 0; index < results.length; index++) {
//
// result_1 = results[index];
// String displayFieldName = result_1.getDisplayFieldName();
// Map attr = result_1.getAttributes();
// for (String key : attr.keySet()) {
// if (key.equalsIgnoreCase(displayFieldName)) {
// resultList.add(result_1);
// }
// }
// }
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main, menu);
}
@Override
public void onResume() {
super.onResume();
mMapView.unpause();
mSensorManager.registerListener(sensorEventListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_UI);
}
@Override
public void onPause() {
super.onPause();
mMapView.pause();
}
@Override
public void onStop() {
super.onStop();
mSensorManager.unregisterListener(sensorEventListener);
}
/**
* Tip:
* ArcGISTiledMapServiceLayer類,這個類可以用來加載基礎圖層,但是默認是訪問URL獲取的,只要重寫它的getTile()方法,
* 在獲取瓦片的時候先判斷本地是否存在,如果本地不存在則使用super.getTile()方法獲得URL中的相應瓦片,然後保存到本地。
*/
private SensorEventListener sensorEventListener = new SensorEventListener() {//方向傳感器監聽
@Override
public void onSensorChanged(final SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
// 獲取當前傳感器獲取到的角度
if (isNavigation && isRomation) {//記錄手動旋轉時傳感器的角度
mSensorDegree = event.values[0];
} else if (isNavigation && !isRomation) {//旋轉時調整地圖角度
float degree = mMapDegree + event.values[0] - mSensorDegree;
// Point centerPoint = (Point) GeometryEngine.project(new Point(longitude, latitude), SpatialReference.create(WKID_IN), SpatialReference.create(WKID_OUT));
// mMapView.centerAt(centerPoint, true);//設置中心點
mMapView.setRotationAngle(degree);
mSouthIV.setRotation((float) -mMapView.getRotationAngle());
} else if (!isNavigation) {
float degree = event.values[0];
//當前位置圖標的更新
Point wgsPoint = new Point(longitude, latitude);
Point mapPoint = (Point) GeometryEngine.project(wgsPoint, SpatialReference.create(WKID_IN), SpatialReference.create(WKID_OUT));
mLocationSymbol.setAngle(degree);
Graphic graphic = new Graphic(mapPoint, mLocationSymbol);
mMyLayer.updateGraphic(mMyUID, graphic);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
//底部信息布局的顯示/隱藏
private void showBottom(boolean toShow) {
if (toShow) {
//底部信息布局的顯示
mBottomLL.setVisibility(View.VISIBLE);
ObjectAnimator animation = ObjectAnimator.ofFloat(mBottomLL, "translationY", mBottomLL.getLayoutParams().height, 0);
animation.setInterpolator(new DecelerateInterpolator());
animation.setDuration(300);
animation.start();
isBottomShow = true;
} else {
//底部信息布局的隱藏
ObjectAnimator animation = ObjectAnimator.ofFloat(mBottomLL, "translationY", 0, mBottomLL.getLayoutParams().height);
animation.setInterpolator(new DecelerateInterpolator());
animation.setDuration(300);
animation.start();
isBottomShow = false;
}
}
/**
* 獲取景點
*/
private void getScenicSpot(final String id) {
putAsyncTask(new AsyncTask() {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected DataExchange doInBackground(Void... params) {
String strXML = HttpUtil.request(mXMLGenerator.getScenicSpotInfo(id));
DataExchange dataExg = mXMLResolver.getScenicSpotInfo(strXML);
return dataExg;
}
@Override
protected void onPostExecute(DataExchange result) {
super.onPostExecute(result);
dismissLoadingDialog();
if (result.isSuccess()) {
List spots = (List) result.getBackData();
if (spots != null) {
mScenicSpot = spots.get(0);
mBottomNameTV.setText(mScenicSpot.getName());
mBottomDetailTV.setText(mScenicSpot.getDesc());
Glide.with(getActivity()).load(mScenicSpot.getPicpath()).into(mBottomIV);
if (!isBottomShow)
showBottom(true);
}
} else {
if (!result.getErrorInfo().isEmpty())
showCustomToast(result.getErrorInfo());
else
showCustomToast(R.string.individuality_dialog);
}
}
});
}
}
多虧了<include />標簽,在Android裡,很容易就能做到共享和重用UI組件。在Android開發中,很容易就能創建出復雜的UI結構,結果呢,用了很
Android使用Handler進行實例化(new)時, 如: private Handler handler = new Handler(); 會報錯Ha
一、繼承listActivity、使用arrayAdapter使用ListView和arrayAdapter布局,是ListView布局中最為簡單的一種,首先我們會建立一
AssetManager是android的資源管理器,負責管理android系統所有的資源.資源可以分系統級別和應用級別.系統級別主要是f