标签:android照片选择器 照片预览 拍摄照片 获取照片路径 选择多张照片
转载请注明出处:http://blog.csdn.net/a740169405/article/details/41622025
说明:
①本来打算自己写图片异步加载代码,后来因为赶时间,就改成直接引用开源框架universal-image-loader,一个 android上知名度很高的图片加载框架。
②预览图片的时候,使用到了一个开源框架,忘了叫什么啦,只记得包名叫polites.android,这里直接引入了源 码,对不住作者了 - _ - 。
③为了兼容低版本,library以及测试项目的开发平台均为android2.3.3。
④点击查看照片时,为了防止手机上照片太对,使用bundle在activity之间传递会导致崩溃,所以使用进入预览 界面之后重新从本地读取图片信息。
⑤项目中使用了一个PhotoModel实体类,用来存放照片的路径信息,以及照片被选中的状态。
简单入门:
大家只需要引入library工程,并在清单文件中注册两个activity以及加入读取SD卡权限即可,使用例子以及源码放在文章最后
功能介绍:
大致实现了图片选择、预览、切换相册、拍照。并将选中的照片信息返回。
预览效果:
照片选择
预览
相册选择
关键实现:
〇:首先要说明的是如何使用我的源码,引入library,并在你自己的清单文件中加入读取SD卡权限,以及注册两个activity。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<activity
android:name="com.photoselector.ui.PhotoSelectorActivity"
android:label="图片选择" >
</activity>
<activity
android:name="com.photoselector.ui.PhotoPreviewActivity"
android:label="图片预览" >
</activity>①首先,一进入照片选择界面,需要将最近照片显示出来,使用ContentResolver查询最近照片,这里我采用了异步加载的方式获取数据,并调用主界面的回调函数对适配器adapter进行更新。
说明:过滤掉小于10kb的照片
/** 获取最近照片列表 */
public List<PhotoModel> getCurrent() {
Cursor cursor = resolver.query(Media.EXTERNAL_CONTENT_URI, new String[] { ImageColumns.DATA,
ImageColumns.DATE_ADDED, ImageColumns.SIZE }, null, null, ImageColumns.DATE_ADDED);
if (cursor == null || !cursor.moveToNext())
return new ArrayList<PhotoModel>();
List<PhotoModel> photos = new ArrayList<PhotoModel>();
cursor.moveToLast();
do {
if (cursor.getLong(cursor.getColumnIndex(ImageColumns.SIZE)) > 1024 * 10) {
PhotoModel photoModel = new PhotoModel();
photoModel.setOriginalPath(cursor.getString(cursor.getColumnIndex(ImageColumns.DATA)));
photos.add(photoModel);
}
} while (cursor.moveToPrevious());
return photos;
}public void getReccent(final OnLocalReccentListener listener) {
final Handler handler = new Handler() {
@SuppressWarnings("unchecked")
@Override
public void handleMessage(Message msg) {
listener.onPhotoLoaded((List<PhotoModel>) msg.obj);
}
};
new Thread(new Runnable() {
@Override
public void run() {
List<PhotoModel> photos = albumController.getCurrent();
Message msg = new Message();
msg.obj = photos;
handler.sendMessage(msg);
}
}).start();
}private OnLocalReccentListener reccentListener = new OnLocalReccentListener() {
@Override
public void onPhotoLoaded(List<PhotoModel> photos) {
if (tvAlbum.getText().equals(RECCENT_PHOTO))
photos.add(0, new PhotoModel());
photoAdapter.update(photos);
gvPhotos.smoothScrollToPosition(0); // 滚动到顶端
reset();
}
};②在图片选择界面,新建一个ArrayList集合变量selected用来存放当前选中的照片信息。
接着将获取到的照片显示在GridView上,这里我对GridView的每一个Item进行了封装,大致就是一个ImageView上面浮着一个CheckBox。在每一个CheckBox状态改变时,调用回调函数往集合中插入当前选中照片的信息。
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (!isCheckAll) {
listener.onCheckedChanged(photo, buttonView, isChecked); // 调用主界面回调函数
}
// 让图片变暗或者变亮
if (isChecked) {
setDrawingable();
ivPhoto.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
} else {
ivPhoto.clearColorFilter();
}
photo.setChecked(isChecked);
}
private ArrayList<PhotoModel> selected;
@Override
/** 照片选中状态改变之后 */
public void onCheckedChanged(PhotoModel photoModel, CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
selected.add(photoModel);
tvPreview.setEnabled(true);
} else {
selected.remove(photoModel);
}
tvPreview.setText("预览(" + selected.size() + ")"); //修改预览数量
if (selected.isEmpty()) {
tvPreview.setEnabled(false);
tvPreview.setText("预览");
}
}因为对GridView的每一个Item进行了封装,同一时刻加载太多个会导致内存崩溃,这里我采用在一定时间内随机选择一个时间进行加载,这也是为什么有时候后面的Item会先加载完成(不排除小图片先加载完成的可能)
DisplayImageOptions defaultDisplayImageOptions = new DisplayImageOptions.Builder() // .considerExifParams(true) // 调整图片方向 .resetViewBeforeLoading(true) // 载入之前重置ImageView .showImageOnLoading(R.drawable.ic_picture_loading) // 载入时图片设置为黑色 .showImageOnFail(R.drawable.ic_picture_loadfailed) // 加载失败时显示的图片 .delayBeforeLoading(0) // 载入之前的延迟时间 .build(); // ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()) .defaultDisplayImageOptions(defaultDisplayImageOptions).memoryCacheExtraOptions(480, 800) .threadPoolSize(5).build(); ImageLoader.getInstance().init(config);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
ImageLoader.getInstance().displayImage("file://" + photo.getOriginalPath(), ivPhoto);
}
}, new Random().nextInt(10));说明:CommonUtils是我封装的一个常用工具类。
/** 预览照片 */
private void priview() {
Bundle bundle = new Bundle();
bundle.putSerializable("photos", selected);
CommonUtils.launchActivity(this, PhotoPreviewActivity.class, bundle);
}@Override
/** 点击查看照片 */
public void onItemClick(int position) {
Bundle bundle = new Bundle();
if (tvAlbum.getText().toString().equals(RECCENT_PHOTO))
bundle.putInt("position", position - 1);
else
bundle.putInt("position", position);
bundle.putString("album", tvAlbum.getText().toString());
CommonUtils.launchActivity(this, PhotoPreviewActivity.class, bundle);
}@SuppressWarnings("unchecked")
protected void init(Bundle extras) {
if (extras == null)
return;
if (extras.containsKey("photos")) { // 预览图片
photos = (List<PhotoModel>) extras.getSerializable("photos");
current = extras.getInt("position", 0);
updatePercent();
bindData();
} else if (extras.containsKey("album")) { // 点击图片查看
String albumName = extras.getString("album"); // 相册
this.current = extras.getInt("position");
if (!CommonUtils.isNull(albumName) && albumName.equals(PhotoSelectorActivity.RECCENT_PHOTO)) {
photoSelectorDomain.getReccent(this);
} else {
photoSelectorDomain.getAlbum(albumName, this);
}
}
}说明:这里的AnimationUtil是我封装的一个用来显示动画的工具类,具体代码可以看源代码。
/** 弹出相册列表 */
private void popAlbum() {
layoutAlbum.setVisibility(View.VISIBLE);
new AnimationUtil(getApplicationContext(), R.anim.translate_up_current).setLinearInterpolator().startAnimation(
layoutAlbum);
}
/** 隐藏相册列表 */
private void hideAlbum() {
new AnimationUtil(getApplicationContext(), R.anim.translate_down).setLinearInterpolator().startAnimation(
layoutAlbum);
layoutAlbum.setVisibility(View.GONE);
}private OnLocalAlbumListener albumListener = new OnLocalAlbumListener() {
@Override
public void onAlbumLoaded(List<AlbumModel> albums) {
albumAdapter.update(albums);
}
};/** 获取所有相册列表 */
public List<AlbumModel> getAlbums() {
List<AlbumModel> albums = new ArrayList<AlbumModel>();
Map<String, AlbumModel> map = new HashMap<String, AlbumModel>();
Cursor cursor = resolver.query(Media.EXTERNAL_CONTENT_URI, new String[] { ImageColumns.DATA,
ImageColumns.BUCKET_DISPLAY_NAME, ImageColumns.SIZE }, null, null, null);
if (cursor == null || !cursor.moveToNext())
return new ArrayList<AlbumModel>();
cursor.moveToLast();
AlbumModel current = new AlbumModel("最近照片", 0, cursor.getString(cursor.getColumnIndex(ImageColumns.DATA)), true); // "最近照片"相册
albums.add(current);
do {
if (cursor.getInt(cursor.getColumnIndex(ImageColumns.SIZE)) < 1024 * 10)
continue;
current.increaseCount();
String name = cursor.getString(cursor.getColumnIndex(ImageColumns.BUCKET_DISPLAY_NAME));
if (map.keySet().contains(name))
map.get(name).increaseCount();
else {
AlbumModel album = new AlbumModel(name, 1, cursor.getString(cursor.getColumnIndex(ImageColumns.DATA)));
map.put(name, album);
albums.add(album);
}
} while (cursor.moveToPrevious());
return albums;
}/** 获取对应相册下的照片 */
public List<PhotoModel> getAlbum(String name) {
Cursor cursor = resolver.query(Media.EXTERNAL_CONTENT_URI, new String[] { ImageColumns.BUCKET_DISPLAY_NAME,
ImageColumns.DATA, ImageColumns.DATE_ADDED, ImageColumns.SIZE }, "bucket_display_name = ?",
new String[] { name }, ImageColumns.DATE_ADDED);
if (cursor == null || !cursor.moveToNext())
return new ArrayList<PhotoModel>();
List<PhotoModel> photos = new ArrayList<PhotoModel>();
cursor.moveToLast();
do {
if (cursor.getLong(cursor.getColumnIndex(ImageColumns.SIZE)) > 1024 * 10) {
PhotoModel photoModel = new PhotoModel();
photoModel.setOriginalPath(cursor.getString(cursor.getColumnIndex(ImageColumns.DATA)));
photos.add(photoModel);
}
} while (cursor.moveToPrevious());
return photos;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
PhotoItem item = null;
TextView tvCamera = null;
if (position == 0 && CommonUtils.isNull(models.get(position).getOriginalPath())) { // 当时第一个时,显示按钮
if (convertView == null || !(convertView instanceof TextView)) {
tvCamera = (TextView) LayoutInflater.from(context).inflate(R.layout.view_camera, null);
tvCamera.setHeight(itemWidth);
tvCamera.setWidth(itemWidth);
convertView = tvCamera;
}
convertView.setOnClickListener(cameraListener);
} else { // 显示图片
if (convertView == null || !(convertView instanceof PhotoItem)) {
item = new PhotoItem(context, listener);
item.setLayoutParams(itemLayoutParams);
convertView = item;
} else {
item = (PhotoItem) convertView;
}
item.setImageDrawable(models.get(position));
item.setSelected(models.get(position).isChecked());
item.setOnClickListener(mCallback, position);
}
return convertView;
}/** 拍照 */
private void catchPicture() {
CommonUtils.launchActivityForResult(this, new Intent(MediaStore.ACTION_IMAGE_CAPTURE), REQUEST_CAMERA);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CAMERA && resultCode == RESULT_OK) {
PhotoModel photoModel = new PhotoModel(CommonUtils.query(getApplicationContext(), data.getData()));
selected.clear();
selected.add(photoModel);
ok();
}
}
/** 完成 */
private void ok() {
if (selected.isEmpty()) {
setResult(RESULT_CANCELED);
} else {
Intent data = new Intent();
Bundle bundle = new Bundle();
bundle.putSerializable("photos", selected);
data.putExtras(bundle);
setResult(RESULT_OK, data);
}
finish();
}说明:这里的tvPath是我写的Demo项目里,一个用来显示照片路径的TextView。
@Override
public void onClick(View v) {
//CommonUtils是library中的一个工具类
CommonUtils.launchActivityForResult(this, PhotoSelectorActivity.class, 0);
tvPath.setText("");
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0 && resultCode == RESULT_OK) {
if (data != null && data.getExtras() != null) {
@SuppressWarnings("unchecked")
List<PhotoModel> photos = (List<PhotoModel>) data.getExtras().getSerializable("photos");
if (photos == null || photos.isEmpty())
return;
StringBuffer sb = new StringBuffer();
for (PhotoModel photo : photos) {
sb.append(photo.getOriginalPath() + "\r\n");
}
tvPath.setText(sb.toString());
}
}
}转载请注明出处:http://blog.csdn.net/a740169405/article/details/41622025
标签:android照片选择器 照片预览 拍摄照片 获取照片路径 选择多张照片
原文地址:http://blog.csdn.net/a740169405/article/details/41622025