在不少應用中都Marker在地圖控件中間位置不變化:以下圖java
ps:有人說是屏幕這個其實形容不許確 實際上是MapView的中心點,只不過地圖通常都是鋪滿屏幕的,因此纔會有屏幕的說法android
請注意:(在這篇文章中 屏幕指MapView)git
在上一期中 咱們知道 Marker類有 設置Marker像素位置的方法以下markdown
那麼咱們如何取的地圖控件中心點的像素座標呢。網絡
這裏咱們須要瞭解兩個新的類框架
相機位置,這個類包含了全部的可視區域的位置參數。dom
這個類是咱們在地圖移動視角後,存儲一些參數以下:ide
在這個類中 target屬性是地圖控件中心點的座標,這個是屬性是咱們等會要使用oop
這個類負責將屏幕位置和地理座標(經緯度)進行轉換。屏幕位置是相對地圖的左上角的位置,因此並不必定是從整個屏幕開始計算的。學習
這個類重要的是他的方法。請看以下圖
看完上面咱們就應該知道 若是取地圖控件中心點的像素位置了。
咱們要經過CarmeraPositon的target屬性要拿到地圖中心點的座標
經過Projection的toScreenLocation方法來獲取地圖控件中心點的像素位置
代碼以下:
//拿到地圖中心點的座標。
LatLng latLng = aMap.getCameraPosition().target;
//把中心點的座標轉換成屏幕像素位置
Point screenPosition = aMap.getProjection().toScreenLocation(latLng);
//給marker設置像素位置。
marker.setPositionByPixels(screenPosition.x, screenPosition.y);
複製代碼
調用這段代碼須要注意的問題:
若是咱們直接在Activty中的onCreate或者Frgment的onViewCreate方法調用,因爲MapView這個時候的長度和寬度都仍是0,這個時候算出的screenPosition.x screenPosition.y
都爲0.計算的結果是不正確的,你會看不到Marker的,
因此咱們要在MapView的長度和寬度已經算出來的狀況下在調用這個方法,
高德SDK也提供了這個方法代碼以下:
getAMap().setOnMapLoadedListener(new AMap.OnMapLoadedListener() {
@Override
public void onMapLoaded() {
//在這裏調用這個方法,才能顯示出來
addCenterMarker();
}
});
複製代碼
好了 咱們來實現下面的這個效果
首先咱們分析下這個功能,
1. 移動地圖的時候 infoWindow隱藏,
2. 中止移動的時候 infoWindow顯示loading效果。
3. 根據座標的獲取地理名稱後 infoWindow顯示成功。 固然也有失敗的狀況。
根據座標點的獲取地理名稱 在高德上 叫逆地理編碼, 是一個耗時操做(至關於一個網絡請求)
ps: 你們看到那個三分鐘和附近車輛的座標位置, 其實應該是滴滴網絡請求接口返回的,可是我並無這個接口 就直接寫了 3分鐘,附近車輛座標是根據座標點隨機生成。
固然在實際狀況下這樣確定不行 正常狀況應該是:
當咱們中止移動地圖的時候,應該有兩個耗時操做,一個是獲取座標點地理名稱(逆地理編碼),一個是獲取預估時間附近車輛位置(http請求接口),且這兩個耗時操做都要成功 InfoWindow 才能顯示成功。
這個時候我就很是推薦使用RXJAVA來實現這個功能了。
可是是在這裏咱們主要是介紹高德SDK 儘可能不引入其餘框架,來增長你們的學習成本。
在代碼中我會作一個測試數據來模擬獲取預估時間附近車輛位置(http請求接口) 不使用rxjava
首先咱們瞭解下 一個方法
OnCameraChangeListener:
這個方法會在地圖移動的時候回調。
onCameraChange 會在移動地圖的時候不斷調用
onCameraChangeFinish 會在地圖中止移動的時候的調用
複製代碼
咱們應該
在onCameraChange 隱藏infoWindow
在onCameraChangeFinish 進行逆地理編碼和獲取接駕時間的耗時操做,infoWindow同時顯示loading效果,成功後infoWindow顯示成功 失敗後InfoWindow顯示失敗
咱們把代碼都寫在Fragment中很差 因此咱們封裝一下
建一個CenterMarkerView類
複製代碼
代碼以下:
/**
* @author jikun
* Created by jikun on 2018/3/14.
*/
public class CenterMarkerView {
private Marker centerMarker;
public void addCenterMarker(AMap aMap) {
MarkerOptions options = new MarkerOptions();
//對應Marker.setIcon方法 設置Marker的圖片
options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.icon_me_location));
options.anchor(0.5F, 1);
//拿到地圖中心點的座標。
LatLng latLng = aMap.getCameraPosition().target;
//把中心點的座標轉換成屏幕像素位置
Point screenPosition = aMap.getProjection().toScreenLocation(latLng);
//在地圖上添加Marker並獲取到Marker.
centerMarker = aMap.addMarker(options);
//給marker設置像素位置。
centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y);
centerMarker.setAnchor(0.5F, 1);
}
public void initInfoWindowsView(final Context context, AMap aMap) {
aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
@Override
public View getInfoWindow(Marker marker) {
View infoWindow = LayoutInflater.from(context).inflate(
R.layout.map_fast_car_info_window, null);
infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.VISIBLE);
infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.GONE);
infoWindow.findViewById(R.id.ll_left).setVisibility(View.VISIBLE);
infoWindow.findViewById(R.id.iv_loading).setVisibility(View.GONE);
return infoWindow;
}
@Override
public View getInfoContents(Marker marker) {
return null;
}
});
}
public void hideCenterMarkerInfoWindow() {
}
public void showLoadingInfoWindow() {
}
public void showSuccessInfoWindow() {
}
public void showErrorInfoWindow() {
}
public void destorty() {
if (null != centerMarker) {
centerMarker.destroy();
}
}
}
複製代碼
當咱們調用Marker.showInfoWindow 方法的時候 InfoWindowAdapter的getInfoWindow()和getInfoContents()會回調
根據這個 咱們先寫一個枚舉類 來區分當前InfoWindow是 加載中 仍是成功 或者失敗的UI效果
註解代碼以下:
//添加支持註解的依賴到你的項目中,須要在build.gradle文件中的依賴塊中添加:
//dependencies { compile 'com.android.support:support-annotations:24.2.0' }
@IntDef({InfoWindowUIType.LOADING, InfoWindowUIType.SUCCESS, InfoWindowUIType.FAILED})
@Retention(RetentionPolicy.SOURCE)
public @interface InfoWindowUIType {
public static final int LOADING = 0;
public static final int SUCCESS = 1;
public static final int FAILED = 2;
}
複製代碼
好了咱們來寫UI控制效果 代碼以下:
public void initInfoWindowsView(final Context context, AMap aMap) {
aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
@Override
public View getInfoWindow(Marker marker) {
View infoWindow = LayoutInflater.from(context).inflate(
R.layout.map_fast_car_info_window, null);
switch (type) {
case InfoWindowUIType.LOADING:
//Loading InfoWindow顯示效果
infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.VISIBLE);
infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.GONE);
infoWindow.findViewById(R.id.ll_left).setVisibility(View.GONE);
infoWindow.findViewById(R.id.iv_loading).setVisibility(View.VISIBLE);
ImageView imageView = infoWindow.findViewById(R.id.iv_loading);
AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();
if (!animationDrawable.isRunning()) {
animationDrawable.start();
}
break;
case InfoWindowUIType.SUCCESS:
infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.VISIBLE);
infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.GONE);
infoWindow.findViewById(R.id.ll_left).setVisibility(View.VISIBLE);
infoWindow.findViewById(R.id.iv_loading).setVisibility(View.GONE);
break;
case InfoWindowUIType.FAILED:
infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.GONE);
infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.VISIBLE);
break;
default:
break;
}
return infoWindow;
}
@Override
public View getInfoContents(Marker marker) {
return null;
}
});
}
複製代碼
咱們添加一個模擬請求的延遲類
代碼以下
/**
* @author jikun
* Created by jikun on 2018/3/14.
*/
public class DelayTest {
public OnCallBack callBack;
public Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (null != callBack) {
callBack.onSuccess();
}
}
};
public void getDelayPost(OnCallBack callBack) {
this.callBack = callBack;
long sec = (long) (Math.random() * 1300);
Log.e("測試代碼", "測試代碼時間=" + sec);
handler.sendEmptyMessageDelayed(0, sec);
}
public void stop() {
this.callBack = null;
}
public interface OnCallBack {
void onSuccess();
void onFailed();
}
public void destory() {
handler.removeCallbacksAndMessages(null);
}
}
複製代碼
而後在CenterMarkerMapFragment 的代碼以下:
/**
* @author jikun
* Created by jikun on 2018/3/13.
*/
public class CenterMarkerMapFragment extends BaseMapFragment {
private CenterMarkerView centerMarkerView;
private DelayTest delayTest;
public static CenterMarkerMapFragment newInstance() {
Bundle args = new Bundle();
CenterMarkerMapFragment fragment = new CenterMarkerMapFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_marker_map, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
TextureMapView textureMapView = view.findViewById(R.id.textureMapView);
delayTest = new DelayTest();
initMapView(textureMapView, savedInstanceState);
centerMarkerView = new CenterMarkerView();
centerMarkerView.initInfoWindowsView(getContext(), getAMap());
getAMap().setOnMapLoadedListener(new AMap.OnMapLoadedListener() {
@Override
public void onMapLoaded() {
centerMarkerView.addCenterMarker(getAMap());
moveCameraOnMap();
}
});
getAMap().setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition cameraPosition) {
delayTest.stop();
centerMarkerView.hideCenterMarkerInfoWindow();
}
@Override
public void onCameraChangeFinish(CameraPosition cameraPosition) {
centerMarkerView.showLoadingInfoWindow();
delayTest.getDelayPost(new DelayTest.OnCallBack() {
@Override
public void onSuccess() {
centerMarkerView.showSuccessInfoWindow();
}
@Override
public void onFailed() {
centerMarkerView.showErrorInfoWindow();
}
});
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
centerMarkerView.destorty();
delayTest.destory();
}
/**
* 移動地圖到Marker標記點位置的方法。
*/
private void moveCameraOnMap() {
LatLng latLng = new LatLng(30.657505, 104.065692);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(latLng);
getAMap().moveCamera(cameraUpdate);
}
複製代碼
最後咱們就實現以下效果
因爲篇幅問題,
逆地理編碼和 顯示周圍車輛我就放在下一篇中講解了。
代碼下載地址:gitee.com/justforgame…