2015-06-12 14:14:57 shaozucheng 阅读数 8569
  • Android Studio 开发详解

    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。

    10819 人正在学习 去看看 郭宏志

这段时间开发的时候用到了高德地图,对高德地图开发有心得体会,现在分享给大家,对我开发过百度地图的我来说,总体来说高德地图Demo,没有百度讲解的详细

个人更偏向于使用百度地图,但是没办发,项目需要使用高德地图,我开发的是定位,更具经纬度添加标记,标记点击事件,以及路线规划废话不多说,上代代码


那么首先导入高德给的jar,包,我开发的是2d地图,


这个包结构图,高德题图api也提供了步骤,就不多说了


下面添加权限,设置key

<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />




package com.yakj.gaodedemo;

import android.app.Activity;
import android.graphics.Color;
import android.location.Location;
import android.os.Bundle;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.LocationManagerProxy;
import com.amap.api.location.LocationProviderProxy;
import com.amap.api.maps2d.AMap;
import com.amap.api.maps2d.AMap.OnMapClickListener;
import com.amap.api.maps2d.AMap.OnMarkerClickListener;
import com.amap.api.maps2d.CameraUpdateFactory;
import com.amap.api.maps2d.LocationSource;
import com.amap.api.maps2d.MapView;
import com.amap.api.maps2d.model.BitmapDescriptor;
import com.amap.api.maps2d.model.BitmapDescriptorFactory;
import com.amap.api.maps2d.model.LatLng;
import com.amap.api.maps2d.model.Marker;
import com.amap.api.maps2d.model.MarkerOptions;
import com.amap.api.maps2d.model.MyLocationStyle;
import com.yakj.view.StationInfoPopupWindow;

public class MainActivity extends Activity implements LocationSource, AMapLocationListener, OnMarkerClickListener, OnMapClickListener {
	/**
	 * 基础地图
	 */
	private MapView mapView;

	private AMap aMap;

	/**
	 * 定位
	 */
	private LocationManagerProxy mAMapLocationManager;

	/**
	 * 定位监听
	 */
	private OnLocationChangedListener mListener;

	/**
	 * 添加的覆盖物标志
	 */
	private Marker currentMarker;

	/**
	 * 点击标记物弹出popWindow信息
	 */
	private StationInfoPopupWindow popWindow;

	/**
	 * 展示popWindow布局
	 */
	private RelativeLayout mpop;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mapView = (MapView) findViewById(R.id.map);
		mapView.onCreate(savedInstanceState);// 必须要写
		mpop = (RelativeLayout) findViewById(R.id.rent_map_pop);
		init();
	}

	/**
	 * 初始化AMap对象
	 */
	private void init() {
		if (aMap == null) {
			aMap = mapView.getMap();
			setUpMap();
		}
	}

	/**
	 * 设置地图样式
	 */
	private void setUpMap() {
		// 自定义系统定位蓝点
		MyLocationStyle myLocationStyle = new MyLocationStyle();
		// 自定义定位蓝点图标
		myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.location_marker));
		// 自定义精度范围的圆形边框颜色
		myLocationStyle.strokeColor(Color.BLUE);
		myLocationStyle.radiusFillColor(Color.TRANSPARENT);
		// 自定义精度范围的圆形边框宽度
		myLocationStyle.strokeWidth(2);
		// 将自定义的 myLocationStyle 对象添加到地图上
		aMap.setMyLocationStyle(myLocationStyle);
		
		aMap.setLocationSource(this);// 设置定位监听
		aMap.getUiSettings().setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示
		aMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
		// 设置定位的类型为定位模式:定位(AMap.LOCATION_TYPE_LOCATE)、跟随(AMap.LOCATION_TYPE_MAP_FOLLOW)
		// 地图根据面向方向旋转(AMap.LOCATION_TYPE_MAP_ROTATE)三种模式
		// aMap.setMyLocationType(AMap.MAP_TYPE_SATELLITE);

		// 设置地图可视缩放大小
		aMap.moveCamera(CameraUpdateFactory.zoomTo(14));
		aMap.getUiSettings().setCompassEnabled(true);// 设置指南针
		aMap.getUiSettings().setScaleControlsEnabled(true);// 设置比例尺

		LatLng latLng = new LatLng(31.383755, 118.438321);
		MarkerOptions otMarkerOptions = new MarkerOptions();
		otMarkerOptions.position(latLng);
		otMarkerOptions.visible(true);//设置可见
		otMarkerOptions.title("芜湖市").snippet("芜湖市:31.383755, 118.438321");//里面的内容自定义
		otMarkerOptions.draggable(true);
		//下面这个是标记上面这个经纬度在地图的位置是
		// otMarkerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_mark));
		
		//下面这个是自定义的标记图标使用方法
		otMarkerOptions.icon(ImageNormal(0));

		aMap.addMarker(otMarkerOptions);
		aMap.setOnMarkerClickListener(this);
		aMap.setOnMapClickListener(this);
	}

	/**
	 * 自定义标记物的图片(未选中状态)
	 * @param i
	 * @return
	 */
	private BitmapDescriptor ImageNormal(int i) {
		//这个布局是自定义的,这面的内容同样自动,在poi_view 这个xml文件里有一个有一张图片,有一个TextView
		//被我删除了,这个TextView,有需要的网友可以自己设置,这个TextView里面可以写数字,或者ABCD...更具需求
		//各位自由发挥
		View view = null;
		view = getLayoutInflater().inflate(R.layout.poi_view, null);
		RelativeLayout ly = (RelativeLayout) view.findViewById(R.id.view_mark);

		// TextView tv = (TextView) view.findViewById(R.id.poi_mark_img);
		// tv.setText(i + "");
		// tv.setPadding(0, 0, 0, 25);
		// tv.setBackgroundResource(R.drawable.poi_mark_normal);
		BitmapDescriptor bitmap = BitmapDescriptorFactory.fromView(view);
		return bitmap;
	}

	/**
	 * 自定义标记物图片(选中状态)
	 * @param i
	 * @return
	 */
	private BitmapDescriptor ImagePress(int i) {
		//使用方法同上
		View view = null;
		view = getLayoutInflater().inflate(R.layout.poi_view, null);
		// TextView tv = (TextView) view.findViewById(R.id.poi_mark_img);
		// tv.setText(i + "");
		// tv.setPadding(0, 0, 0, 25);
		// tv.setBackgroundResource(R.drawable.poi_mark_press);
		BitmapDescriptor bitmap = BitmapDescriptorFactory.fromView(view);
		return bitmap;
	}

	/**
	 * 方法必须重写
	 */
	@Override
	protected void onResume() {
		super.onResume();
		mapView.onResume();
	}

	/**
	 * 方法必须重写
	 */
	@Override
	protected void onPause() {
		super.onPause();
		mapView.onPause();
		deactivate();
	}

	/**
	 * 方法必须重写
	 */
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		mapView.onSaveInstanceState(outState);
	}

	/**
	 * 方法必须重写
	 */
	@Override
	protected void onDestroy() {
		super.onDestroy();
		mapView.onDestroy();
		if (popWindow != null) {//隐藏popwindow
			popWindow.dismiss();
		}
	}

	/**
	 * 激活定位
	 */
	@Override
	public void activate(OnLocationChangedListener listener) {
		mListener = listener;
		if (mAMapLocationManager == null) {
			mAMapLocationManager = LocationManagerProxy.getInstance(this);
			// 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,
			// 注意设置合适的定位时间的间隔,并且在合适时间调用removeUpdates()方法来取消定位请求
			// 在定位结束后,在合适的生命周期调用destroy()方法
			// 其中如果间隔时间为-1,则定位只定一次
			mAMapLocationManager.requestLocationData(LocationProviderProxy.AMapNetwork, 60 * 1000, 10, this);
		}
	}

	/**
	 * 停止定位
	 */
	@Override
	public void deactivate() {
		mListener = null;
		if (mAMapLocationManager != null) {
			mAMapLocationManager.removeUpdates(this);
			mAMapLocationManager.destroy();
		}
		mAMapLocationManager = null;
	}

	@Override
	public void onLocationChanged(Location location) {

	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {

	}

	@Override
	public void onProviderEnabled(String provider) {

	}

	@Override
	public void onProviderDisabled(String provider) {

	}

	/**
	 * 定位成功后回调函数
	 */
	@Override
	public void onLocationChanged(AMapLocation amapLocation) {
		if (mListener != null && amapLocation != null) {
			if (amapLocation.getAMapException().getErrorCode() == 0) {
				mListener.onLocationChanged(amapLocation);// 显示系统小蓝点
			}
		}
	}

	@Override
	public boolean onMarkerClick(Marker marker) {
		currentMarker = marker;
		Toast.makeText(this, "你点击了的是" + marker.getTitle(), 10000).show();
		
		if(popWindow !=null){//先把原来的给隐藏起来
			popWindow.dismiss();
		}
		
		popWindow = new StationInfoPopupWindow(this);
		popWindow.showAsDropDown(mpop);
		
		return false;
	}

	/**
	 * 点击地图其他地方时,隐藏InfoWindow,和popWindow弹出框
	 */
	@Override
	public void onMapClick(LatLng latLng) {
		if (currentMarker != null) {
			currentMarker.hideInfoWindow();//隐藏InfoWindow框
			popWindow.dismiss();
		}
	}

}




图上看到的那个就是我自定义的图片,这个有些时候都是需要自定的,高德给的原生的不应符合我们的需求

当点击那个图上那个标记时就出现如下界面。



然后就是路劲规划了,点击到这里去按钮就跳转到路径规划的界面

下面吧popWidow代码贴出来

package com.yakj.view;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.BitmapDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;

import com.yakj.gaodedemo.R;
import com.yakj.gaodedemo.RouteActivity;

public class StationInfoPopupWindow implements View.OnClickListener {
	private Context context;
	private PopupWindow popupWindow;
    //到这里去按钮
	private Button goBtn;

	public StationInfoPopupWindow(final Context context) {
		this.context = context;

		View view = LayoutInflater.from(context).inflate(R.layout.view_map_popup_window, null);

		popupWindow = new PopupWindow(view, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		// 这个是为了点击“返回Back”也能使其消失,并且并不会影响你的背景(很神奇的)
		popupWindow.setBackgroundDrawable(new BitmapDrawable(context.getResources()));
		goBtn = (Button) view.findViewById(R.id.go_to_hotel_btn);
		goBtn.setOnClickListener(this);
	}

	// 下拉式 弹出 pop菜单 parent 右下角
	public void showAsDropDown(View parent) {
		// 保证尺寸是根据屏幕像素密度来的
		popupWindow.showAtLocation(parent, Gravity.BOTTOM, 0, 0);
		// 使其聚集
		popupWindow.setFocusable(false);
		// 设置允许在外点击消失
		popupWindow.setOutsideTouchable(false);
		// 设置动画
		popupWindow.setAnimationStyle(R.style.PopupWindowAnimStyle);
		// 刷新状态
		popupWindow.update();
	}

	public void setDismissListener(OnDismissListener onDismissListener) {
		popupWindow.setOnDismissListener(onDismissListener);
	}

	// 隐藏菜单
	public void dismiss() {
		popupWindow.dismiss();
	}

	// 是否显示
	public boolean isShowing() {
		return popupWindow.isShowing();
	}

	@Override
	public void onClick(View v) {
		if (v == goBtn) {
                        //这里跳转到路径规划界面
			Intent intent = new Intent(context, RouteActivity.class);
			context.startActivity(intent);

		}
	}

}

这里有些效果的图片贴不出来,我在博客最后会把我的Demo源码给大家,希望对给位有所帮助


下面来说下路径规划


package com.yakj.gaodedemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.Toast;

import com.amap.api.maps2d.AMap;
import com.amap.api.maps2d.CameraUpdateFactory;
import com.amap.api.maps2d.MapView;
import com.amap.api.maps2d.overlay.BusRouteOverlay;
import com.amap.api.maps2d.overlay.DrivingRouteOverlay;
import com.amap.api.maps2d.overlay.WalkRouteOverlay;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.route.BusPath;
import com.amap.api.services.route.BusRouteResult;
import com.amap.api.services.route.DrivePath;
import com.amap.api.services.route.DriveRouteResult;
import com.amap.api.services.route.RouteSearch;
import com.amap.api.services.route.RouteSearch.BusRouteQuery;
import com.amap.api.services.route.RouteSearch.DriveRouteQuery;
import com.amap.api.services.route.RouteSearch.OnRouteSearchListener;
import com.amap.api.services.route.RouteSearch.WalkRouteQuery;
import com.amap.api.services.route.WalkPath;
import com.amap.api.services.route.WalkRouteResult;

/**
 * 路径规划
 * 
 * @author Administrator
 *
 */
public class RouteActivity extends Activity implements OnClickListener, OnRouteSearchListener {

	private AMap aMap;
	private MapView mapView;

	/**
	 * 公交按钮,驾车按钮,步行按钮
	 */
	private ImageButton transitBtn, drivingBtn, walkBtn;

	private int busMode = RouteSearch.BusDefault;// 公交默认模式
	private int drivingMode = RouteSearch.DrivingDefault;// 驾车默认模式
	private int walkMode = RouteSearch.WalkDefault;// 步行默认模式
	private RouteSearch routeSearch;

	private BusRouteResult busRouteResult;// 公交模式查询结果
	private DriveRouteResult driveRouteResult;// 驾车模式查询结果
	private WalkRouteResult walkRouteResult;// 步行模式查询结果

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_route);
		mapView = (MapView) findViewById(R.id.route_map);
		mapView.onCreate(savedInstanceState);// 此方法必须重写
		transitBtn = (ImageButton) findViewById(R.id.imagebtn_roadsearch_tab_transit);
		drivingBtn = (ImageButton) findViewById(R.id.imagebtn_roadsearch_tab_driving);
		walkBtn = (ImageButton) findViewById(R.id.imagebtn_roadsearch_tab_walk);

		routeSearch = new RouteSearch(this);
		routeSearch.setRouteSearchListener(this);
		init();
	}

	/**
	 * 初始化AMap对象
	 */
	private void init() {
		if (aMap == null) {
			aMap = mapView.getMap();
		}

		transitBtn.setOnClickListener(this);
		drivingBtn.setOnClickListener(this);
		walkBtn.setOnClickListener(this);

		// 设置地图可视缩放大小
		aMap.moveCamera(CameraUpdateFactory.zoomTo(12));
	}

	/**
	 * 方法必须重写
	 */
	@Override
	protected void onResume() {
		super.onResume();
		mapView.onResume();
	}

	/**
	 * 方法必须重写
	 */
	@Override
	protected void onPause() {
		super.onPause();
		mapView.onPause();
	}

	/**
	 * 方法必须重写
	 */
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		mapView.onSaveInstanceState(outState);
	}

	/**
	 * 方法必须重写
	 */
	@Override
	protected void onDestroy() {
		super.onDestroy();
		mapView.onDestroy();
	}

	@Override
	public void onClick(View v) {

		// 这里是写死的两个位置
		LatLonPoint startPoint = new LatLonPoint(31.383755, 118.438321);
		LatLonPoint endPoint = new LatLonPoint(31.339746, 118.381727);

		final RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(startPoint, endPoint);
		if (v == transitBtn) {// 公交
			BusRouteQuery query = new BusRouteQuery(fromAndTo, busMode, "芜湖市", 1);// 第一个参数表示路径规划的起点和终点,第二个参数表示公交查询模式,第三个参数表示公交查询城市区号,第四个参数表示是否计算夜班车,0表示不计算
			routeSearch.calculateBusRouteAsyn(query);// 异步路径规划公交模式查询
		} else if (v == drivingBtn) {// 驾车
			DriveRouteQuery query = new DriveRouteQuery(fromAndTo, drivingMode, null, null, "");// 第一个参数表示路径规划的起点和终点,第二个参数表示驾车模式,第三个参数表示途经点,第四个参数表示避让区域,第五个参数表示避让道路
			routeSearch.calculateDriveRouteAsyn(query);// 异步路径规划驾车模式查询
		} else if (v == walkBtn) {// 步行
			WalkRouteQuery query = new WalkRouteQuery(fromAndTo, walkMode);
			routeSearch.calculateWalkRouteAsyn(query);// 异步路径规划步行模式查询
		}
	}

	@Override
	public void onBusRouteSearched(BusRouteResult result, int rCode) {
		if (rCode == 0) {
			if (result != null && result.getPaths() != null && result.getPaths().size() > 0) {
				busRouteResult = result;
				BusPath busPath = busRouteResult.getPaths().get(0);
				aMap.clear();// 清理地图上的所有覆盖物
				BusRouteOverlay routeOverlay = new BusRouteOverlay(this, aMap, busPath, busRouteResult.getStartPos(), busRouteResult.getTargetPos());
				routeOverlay.removeFromMap();
				routeOverlay.addToMap();
				routeOverlay.zoomToSpan();
			} else {
				showToast("对不起,没有搜索到相关数据!");
			}
		} else if (rCode == 27) {
			showToast("搜索失败,请检查网络连接!");
		} else if (rCode == 32) {
			showToast("key验证无效!");
		} else {
			showToast("未知错误,请稍后重试!错误码为" + rCode);
		}
	}

	@Override
	public void onDriveRouteSearched(DriveRouteResult result, int rCode) {
		if (rCode == 0) {
			if (result != null && result.getPaths() != null && result.getPaths().size() > 0) {
				driveRouteResult = result;
				DrivePath drivePath = driveRouteResult.getPaths().get(0);
				aMap.clear();// 清理地图上的所有覆盖物
				DrivingRouteOverlay drivingRouteOverlay = new DrivingRouteOverlay(this, aMap, drivePath, driveRouteResult.getStartPos(), driveRouteResult.getTargetPos());
				drivingRouteOverlay.removeFromMap();
				drivingRouteOverlay.addToMap();
				drivingRouteOverlay.zoomToSpan();
			} else {
				showToast("对不起,没有搜索到相关数据!");
			}
		} else if (rCode == 27) {
			showToast("搜索失败,请检查网络连接!");
		} else if (rCode == 32) {
			showToast("key验证无效!");
		} else {
			showToast("未知错误,请稍后重试!错误码为" + rCode);
		}
	}

	@Override
	public void onWalkRouteSearched(WalkRouteResult result, int rCode) {
		if (rCode == 0) {
			if (result != null && result.getPaths() != null && result.getPaths().size() > 0) {
				walkRouteResult = result;
				WalkPath walkPath = walkRouteResult.getPaths().get(0);
				aMap.clear();// 清理地图上的所有覆盖物
				WalkRouteOverlay walkRouteOverlay = new WalkRouteOverlay(this, aMap, walkPath, walkRouteResult.getStartPos(), walkRouteResult.getTargetPos());
				walkRouteOverlay.removeFromMap();
				walkRouteOverlay.addToMap();
				walkRouteOverlay.zoomToSpan();
			} else {
				showToast("对不起,没有搜索到相关数据!");
			}
		} else if (rCode == 27) {
			showToast("搜索失败,请检查网络连接!");
		} else if (rCode == 32) {
			showToast("key验证无效!");
		} else {
			showToast("未知错误,请稍后重试!错误码为" + rCode);
		}
	}

	/**
	 * toast封装
	 * 
	 * @param str
	 */
	private void showToast(String str) {
		Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
		;
	}

}




我这里路劲规划的界面没有定位,点击进去会是北京,然后你随便点击上面的一个路线规划按钮,就会有显示,如上图所示

下面我的把Demo路径,点击打开链接错这里啦大笑大笑

下载地址 :http://download.csdn.net/detail/shaozucheng/8799515








2017-02-22 21:26:48 lishengko 阅读数 3602
  • Android Studio 开发详解

    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。

    10819 人正在学习 去看看 郭宏志

Android开发中加载相册是很常用的功能,但相册图片过多正常加载会产生卡顿,即便使用线程异步加载图片卡顿问题依然得不到改善。
正常代码:

public class AlbumAdapter extends ?{
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        if(bitmap!=null){
            线程加载图片
        }
        else
            读取缓存
    }
}

卡顿原因是无论怎样优化读取IO都是费时的工作,adapter又会一次实例多个子项,导致加载的图片过多,内存占用率过高产生了卡顿。
优化代码:

public class AlbumActivity extends AppCompatActivity{
    private RecyclerView mRecyclerView;
    private List<PhotoItem> photoItemList;
    private List<PhotoItem> selectItemList;
    private int[] photoLayout;
    private AlbumAdapter mAdapter;
    private Handler handler;
    private Button submit;
    private GridLayoutManager gridLayoutManager;
    private static final String[] STORE_IMAGES = {
            MediaStore.Images.Media.DISPLAY_NAME, // 显示的名字
            MediaStore.Images.Media.LATITUDE, // 维度
            MediaStore.Images.Media.LONGITUDE, // 经度
            MediaStore.Images.Media._ID, // id
            MediaStore.Images.Media.BUCKET_ID, // dir id 目录
            MediaStore.Images.Media.BUCKET_DISPLAY_NAME, // dir name 目录名字
            MediaStore.Images.Media.DATA//路径
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_album);
        submit = (Button)findViewById(R.id.submit);
        mRecyclerView = (RecyclerView)findViewById(R.id.list);
        gridLayoutManager = new GridLayoutManager(this, 3);
        mRecyclerView.setLayoutManager(gridLayoutManager);
        mRecyclerView.setHasFixedSize(true);
        photoLayout = new int[2];
        photoLayout[0]=(ScreenHelper.getScreenWidth(this) - ScreenHelper.dp2px(this, 20)) / 3 - ScreenHelper.dp2px(this, 10);
        photoLayout[1] = ScreenHelper.dp2px(this, 110);
        gridLayoutManager.findFirstCompletelyVisibleItemPosition();
        initPhoto();
        notifySubmit();
        mAdapter = new AlbumAdapter(mRecyclerView,photoItemList,selectItemList);
        mAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(RecyclerView.ViewHolder viewHolder, int position) {
                notifySubmit();
            }
        });

        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                //停止滑动后缓存当前屏幕图片
                if(newState == 0){
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for(int i=gridLayoutManager.findFirstVisibleItemPosition();i<gridLayoutManager.findLastVisibleItemPosition();i++){
                                cacheBitmap(i);
                            }
                        }
                    }).start();
                }
            }
        });

        mRecyclerView.setAdapter(mAdapter);

        handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                mAdapter.notifyImage((int)msg.obj);
                return false;
            }
        });
    }

    private void initPhoto(){
        photoItemList = new ArrayList<>();
        selectItemList = (List<PhotoItem>)getIntent().getSerializableExtra(FinalHelper.IMAGE_PATH);
        if(selectItemList == null)
            selectItemList = new ArrayList<>();
        String path="";
        for(int i=0;i<selectItemList.size();i++){
            path += selectItemList.get(i).getPath()+",";
        }
        Cursor cursor = MediaStore.Images.Media.query(getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, STORE_IMAGES,"width >0","date_modified desc");
        cursor.moveToNext();
        for (int i = 0; i < cursor.getCount(); i++) {
            PhotoItem photoItem = new PhotoItem(cursor.getInt(3),path.indexOf(cursor.getString(6))!=-1?true:false,cursor.getString(0),cursor.getString(6));
            photoItemList.add(photoItem);
            cursor.moveToNext();
        }

        //从前往后存缓存缩略图  单线程轮播减少内存消耗确保屏幕不卡顿
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i=0;i<photoItemList.size();i++){
                    cacheBitmap(i);
                }
            }
        }).start();
    }

    //缓存bitmap
    public void cacheBitmap(int position){
        if(CacheManager.get(photoItemList.get(position).getPath())==null){
            Bitmap bitmap = ImageHelper.getSmallCropBitmap(photoItemList.get(position).getPath(), photoLayout[0], photoLayout[1]);
            CacheManager.put(photoItemList.get(position).getPath(),bitmap);
            Message message = new Message();
            message.obj=position;
            handler.sendMessage(message);
        }
    }

    public void notifySubmit(){
        if(selectItemList.size()>0){
            submit.setBackgroundResource(R.drawable.bg_album_submit_enable);
            submit.setText(getString(R.string.submit) + "(" + selectItemList.size() + ")");
            submit.setTextColor(ContextCompat.getColor(this, R.color.white));
            submit.setAlpha(1f);
            submit.setClickable(true);
        }
        else {
            submit.setBackgroundResource(R.drawable.bg_album_submit);
            submit.setTextColor(ContextCompat.getColor(this, R.color.darkgray));
            submit.setAlpha(.8f);
            submit.setText(getString(R.string.submit));
            submit.setClickable(false);
        }
    }

    public void onSubmit(View view){
        Intent intent = new Intent();
        intent.putExtra(FinalHelper.IMAGE_PATH, (Serializable) selectItemList);
        setResult(Activity.RESULT_OK, intent);
        finish();
    }

    public void onBack(View view){
        finish();
    }

    public void onCancel(View view){
        finish();
    }


}

在读取相册的基本数据后,采用单线程轮播的方式顺序缓存图片缩率图,这样便解决了卡顿问题,在配合缓存类,再次加载相册就可以瞬间全部加载完毕,推荐使用开源的第三方库DiskLruCache实现图片的缩略图缓存。
QQ相册初次加载相册图片也是一张一张的,仿QQ相册实例:http://blog.csdn.net/lishengko/article/details/56495553

2017-01-22 16:59:01 carson_ho 阅读数 7842
  • Android Studio 开发详解

    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。

    10819 人正在学习 去看看 郭宏志

前言

  • Android基础中的Activity启动模式非常重要
  • 本文将介绍对Activity启动模式进行全面介绍

目录

目录


1. 定义

即Activity启动的方式


2. 启动模式的类别

Android启动提供了四种启动方式:

  • 标准模式(Standard
  • 栈顶复用模式(SingleTop
  • 栈内复用模式(SingleTask
  • 单例模式(SingleInstance

3. 知识储备

  • Activity的管理方式 = 任务栈
  • 任务栈 采用的结构 = “后进先出” 的栈结构
  • 每按一次Back键,就有一个Activity出栈

示意图


4. 具体介绍

  • 如下图

示意图

  • 通俗讲解
    图解

5. 四种启动模式的区别

示意图


6. 启动模式的设置

启动模式有2种设置方式:在AndroidMainifest设置、通过Intent设置标志位

6.1 在AndroidMainifest设置

AndroidMainifestActivity配置进行设置

<activity

android:launchMode="启动模式"
//属性
//standard:标准模式
//singleTop:栈顶复用模式
//singleTask:栈内复用模式
//singleInstance:单例模式
//如不设置,Activity的启动模式默认为**标准模式(standard)**
</activity>

6.2 通过Intent设置标志位

Intent inten = new Intent (ActivityA.this,ActivityB.class);
intent,addFlags(Intent,FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

标记位属性

标记位属性 含义
FLAG_ACTIVITY_SINGLE_TOP 指定启动模式为栈顶复用模式(SingleTop
FLAG_ACTIVITY_NEW_TASK 指定启动模式为栈内复用模式(SingleTask
FLAG_ACTIVITY_CLEAR_TOP 所有位于其上层的Activity都要移除,SingleTask模式默认具有此标记效果
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 具有该标记的Activity不会出现在历史Activity的列表中,即无法通过历史列表回到该Activity上

6.3 二者设置的区别

  • 优先级不同
    Intent设置方式的优先级 > Manifest设置方式,即 以前者为准
  • 限定范围不同
    Manifest设置方式无法设定 FLAG_ACTIVITY_CLEAR_TOPIntent设置方式 无法设置单例模式(SingleInstance

7. 总结

  • 本文对Android的Activity启动模式进行了全面介绍
  • 接下来会介绍继续介绍Android开发中的相关基础知识,感兴趣的同学可以继续关注carson_ho的微信公众号
    示意图
    示意图

请帮顶 / 评论点赞!因为你们的赞同/鼓励是我写作的最大动力!

2016-07-17 15:50:02 The_c_D 阅读数 1844
  • Android Studio 开发详解

    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。

    10819 人正在学习 去看看 郭宏志

高德地图API支持绘制覆盖物,覆盖物API类似于JS开源地图绘制库Leaflet,如果有相关经验可以轻松上手。

支持的覆盖物:

折线(Polyline)
多边形(Polygon)
圆(Circle)
图片覆盖层(GroundOverlay)
标记(Marker)
弧形(Arc)


如何创建覆盖物:

a.创建覆盖物选项对象(XXOptions eg:Polyline)

b.设置覆盖物选项 

c.创建覆盖物对象 (new XX(xxOptions) eg:new Polyline(new PolylineOptions()))

e.追加至地图 (amap.addXXX eg:amap.addPolyline(xxx) )


http://lbs.amap.com/api/android-sdk/guide/overlay/


//折线选项对象
PolylineOptions polyline=new PolylineOptions()
		.geodesic(false)
		.color(Color.rgb(0, 51, 255))
		.setDottedLine(true)
		.width(5L);

for(Test data:datas){
	//经纬度对象
	LatLng tmp=new LatLng(data.getLat(), data.getLon());
	//创建Mark 并使用自定义图片
	mMapView.getMap().addMarker(new MarkerOptions()
			.position(tmp)
			.title(data.getTitle())
			.snippet(this.buildMarkerSnippet(data))
			.draggable(false)
			.icon(BitmapDescriptorFactory
					.fromResource(R.drawable.location_marker))
			.anchor(0.5F,0.5F))
			.setRotateAngle(360 - Float.parseFloat(data.getCourse()));
	//将当前经纬度添加到直线中
	polyline.add(tmp);
}
//绘制直线
mMapView.getMap().addPolyline(polyline);


2013-11-09 12:08:15 lxtalx 阅读数 1344
  • Android Studio 开发详解

    Android Studio教程,该教材会详细介绍Android Studio如何使用,包括在Windows平台下载安装Android Studio、配置、代码重构、项目调试、jar包管理等。

    10819 人正在学习 去看看 郭宏志

前段时间学习使用googleMap,结果按照各种书上的代码敲进去,申请完KEY,结果发现地图还是用不了,纠结了一个月,然后之前的某一天,我突然发现,google把mapV1版本停用了,不能申请V!版本的KEY了,然后写个小程序又比较需要googleMap,然后就动手学习V2版本的地图了~~~~~~貌似这是我第一篇编程类的博客,我一定好好写~~~~

 

使用新版本的googleAPI,需要先加载google play service包,具体怎么做~~~要不给你们截个图吧!

 

【图1】

点这个,加载出以后

 

【图2】

选中google play services然后安装~~~~~~~~

当然,有的电脑会出现,下不下来,没速度的情况,比如我的就是这样,如果出现这种情况,那就开个代理,具体的我会另开一篇集中讲解这类问题

 

安装好以后,将google play service包导入到eclipse中,即这样操作

 File > Import > Android > Existing Android Code Into Workspace  点击下一步,找到

<安装androidSDK的目录>/extras/google/google_play_services/libproject/google-play-services_lib,点击完成

然后新建一个android项目,然后将google-play-services_lib作为包添加到项目里,就像这样

【图3】

【图4】

【图5】

就是图3,4,5这样操作,请看图5,记得一定要把is library的勾去掉,不去掉会出错,虽然我还不知道为什么会出错,求大神告知

 

对了,你还得看看你有没有导入supportV4包,没有导入的话请导入,具体就是下面这样,请看图

【图6】

如果没有导入,就点  Add External Jars  然后从这个路径找到你的supportV4<android-sdk-安装目录>/extras/android/support/v4/android-support-v4.jar

最后点 Order and Export 标签,把SupportV4打上勾

【图7】

点OK就完了,前期的配置全部完成了,这样的话咱们的google map V2的基本配置就完成了。对了,请注意看图7 中的android Dependencies,这个里面可能会报告supportV4,如果里面有,你又导入了一次supportV4的话,编译就会出错,所以导入之前先看清楚(我就因为这问题纠结了一早上~~)

你要是还不清楚,我也没办法了,我自我感觉写的相当清楚了~~~~~~~~

获取googleMapV2的KEY有好多教程了,我就不写了吧,也很简单啥的,我给你们找个链接~找到一个比较清楚的http://09572.iteye.com/blog/1768865 大家随意看吧,找个写的很清楚了

太多了,大家也不想看,我分开写吧~!

Activity 详解

阅读数 865

没有更多推荐了,返回首页