Android实现本地图片选择及预览缩放效果

在做项目时经常会遇到选择本地图片的需求,以前都是懒得写直接调用系统方法来选择图片,但是这样并不能实现多选效果,最近又遇到了,所以还是写一个demo好了,以后也方便使用。还是首先来看看效果:

显示的图片使用RecyclerView实现的,利用Glide来加载;下面弹出的图片文件夹效果是采用PopupWindow实现,这里比采用PopupWindow更方便,弹出显示的左边图片是这个文件夹里的第一张图片;选中的图片可以进行预览,使用网上一个大神写的来实现的;至于图片的获取是用ContentProvider。

看看主界面的布局文件,上面一栏是一个返回按钮和一个跳转预览界面的按钮,根据是否有选中的图片来设置它的点击和显示状态;中间就是一个用于显示图片的RecyclerView,左下角是显示文件夹的名字可点击切换,右下角就是确定按钮。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context="com.cdxsc.imageselect_y.ImageSelecteActivity"> 

 <RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="45dp"
 android:background="@android:color/white"> 

 <ImageButton
  android:id="@+id/ib_back"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerVertical="true"
  android:layout_marginLeft="10dp"
  android:background="@mipmap/action_bar_back_normal" /> 

 <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerVertical="true"
  android:layout_marginLeft="10dp"
  android:layout_toRightOf="@id/ib_back"
  android:text="选择图片"
  android:textColor="#000"
  android:textSize="16sp" /> 

 <TextView
  android:id="@+id/tv_preview"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignParentRight="true"
  android:layout_centerVertical="true"
  android:layout_marginRight="10dp"
  android:enabled="false"
  android:text="预览"
  android:textColor="#BEBFBF"
  android:textSize="16sp" />
 </RelativeLayout> 

 <View
 android:layout_width="match_parent"
 android:layout_height="0.5dp"
 android:background="#eeeeee" /> 

 <android.support.v7.widget.RecyclerView
 android:id="@+id/rv"
 android:layout_width="match_parent"
 android:layout_height="0dp"
 android:layout_weight="1"></android.support.v7.widget.RecyclerView> 

 <RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="50dp"> 

 <TextView
  android:id="@+id/tv_allPic"
  android:layout_width="wrap_content"
  android:layout_height="match_parent"
  android:layout_centerVertical="true"
  android:layout_marginLeft="10dp"
  android:clickable="true"
  android:gravity="center_vertical"
  android:text="所有图片"
  android:textColor="@android:color/black"
  android:textSize="16sp" /> 

 <Button
  android:id="@+id/bt_confirm"
  android:layout_width="wrap_content"
  android:layout_height="35dp"
  android:layout_alignParentRight="true"
  android:layout_centerVertical="true"
  android:layout_marginRight="10dp"
  android:background="@drawable/shape_disable"
  android:enabled="false"
  android:text="确定"
  android:textColor="#676767"
  android:textSize="16sp" />
 </RelativeLayout>
</LinearLayout>

好了,现在看主界面的代码

public class ImageSelecteActivity extends AppCompatActivity { 

 private static final String TAG = "lzy";
 @BindView(R.id.ib_back)
 ImageButton mButtonBack;
 @BindView(R.id.tv_preview)
 TextView mTextViewPreview;
 @BindView(R.id.rv)
 RecyclerView mRecyclerView;
 @BindView(R.id.tv_allPic)
 TextView mTextViewAllPic;
 @BindView(R.id.bt_confirm)
 Button mButtonConfirm;
 private GalleryPopupWindow mPopupWindow;
 //存储每个目录下的图片路径,key是文件名
 private Map<String, List<String>> mGroupMap = new HashMap<>();
 private List<ImageBean> list = new ArrayList<>();
 //当前文件夹显示的图片路径
 private List<String> listPath = new ArrayList<>();
 //所选择的图片路径集合
 private ArrayList<String> listSelectedPath = new ArrayList<>(); 

 private Handler mHandler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
  //扫描完成后
  getGalleryList();
  listPath.clear();
  listPath.addAll(mGroupMap.get("所有图片"));
  adapter.update(listPath);
  if (mPopupWindow != null)
  mPopupWindow.notifyDataChanged();
 }
 };
 private ImageSelectAdapter adapter; 

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_image_selecte);
 ButterKnife.bind(this);
 init();
 } 

 private void init() {
 getImages();
 mRecyclerView.setLayoutManager(new GridLayoutManager(ImageSelecteActivity.this, 3));
 adapter = new ImageSelectAdapter(this, listPath);
 mRecyclerView.setAdapter(adapter);
 adapter.setOnCheckedChangedListener(onCheckedChangedListener);
 } 

 @OnClick({R.id.ib_back, R.id.tv_preview, R.id.tv_allPic, R.id.bt_confirm})
 public void onClick(View view) {
 switch (view.getId()) {
  case R.id.ib_back:
  finish();
  break;
  case R.id.tv_preview://跳转预览界面
  Intent intent = new Intent(ImageSelecteActivity.this, ImagePreviewActivity.class);
  //把选中的图片集合传入预览界面
  intent.putStringArrayListExtra("pic", listSelectedPath);
  startActivity(intent);
  break;
  case R.id.tv_allPic://选择图片文件夹
  if (mPopupWindow == null) {
   //把文件夹列表的集合传入显示
   mPopupWindow = new GalleryPopupWindow(this, list);
   mPopupWindow.setOnItemClickListener(new GalleryPopupWindow.OnItemClickListener() {
   @Override
   public void onItemClick(String fileName) {
    //切换了文件夹,清除之前的选择的信息
    setButtonDisable();
    listPath.clear();
    listSelectedPath.clear();
    //把当前选择的文件夹内图片的路径放入listPath,更新界面
    listPath.addAll(mGroupMap.get(fileName));
    adapter.update(listPath);
    mTextViewAllPic.setText(fileName);
   }
   });
  }
  mPopupWindow.showAtLocation(mRecyclerView, Gravity.BOTTOM, 0, dp2px(50, ImageSelecteActivity.this));
  break;
  case R.id.bt_confirm://确定
  for (int i = 0; i < listSelectedPath.size(); i++) {
   //这里可通过Glide把它转为Bitmap
   Glide.with(this).load("file://" + listSelectedPath.get(i)).asBitmap().into(new SimpleTarget<Bitmap>() {
   @Override
   public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
    Log.i(TAG, "onResourceReady: " + resource);
   }
   });
  }
  break;
 }
 } 

 /**
 * dp转px
 */
 public static int dp2px(int dp, Context context) {
 return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
  context.getResources().getDisplayMetrics());
 } 

 //选择图片变化的监听
 private ImageSelectAdapter.OnCheckedChangedListener onCheckedChangedListener = new ImageSelectAdapter.OnCheckedChangedListener() {
 @Override
 public void onChanged(boolean isChecked, String path, CheckBox cb, int position) {
  if (isChecked) {//选中
  if (listSelectedPath.size() == 9) {
   Toast.makeText(ImageSelecteActivity.this, "最多选择9张图片", Toast.LENGTH_SHORT).show();
   //把点击变为checked的图片变为没有checked
   cb.setChecked(false);
   adapter.setCheckedBoxFalse(position);
   return;
  }
  //选中的图片路径加入集合
  listSelectedPath.add(path); 

  } else {//取消选中
  //从集合中移除
  if (listSelectedPath.contains(path))
   listSelectedPath.remove(path);
  }
  //如果没有选中的按钮不可点击
  if (listSelectedPath.size() == 0) {
  setButtonDisable();
  } else {
  setButtonEnable();
  }
 }
 }; 

 //选中图片时的按钮状态
 private void setButtonEnable() {
 mButtonConfirm.setBackgroundResource(R.drawable.selector_bt);
 mButtonConfirm.setTextColor(Color.parseColor("#ffffff"));
 mButtonConfirm.setEnabled(true);
 mTextViewPreview.setEnabled(true);
 mTextViewPreview.setTextColor(getResources().getColor(R.color.colorAccent));
 mButtonConfirm.setText("确定" + listSelectedPath.size() + "/9");
 } 

 //没有选择时按钮状态
 private void setButtonDisable() {
 mButtonConfirm.setBackgroundResource(R.drawable.shape_disable);
 mButtonConfirm.setTextColor(Color.parseColor("#676767"));
 mButtonConfirm.setEnabled(false);
 mTextViewPreview.setEnabled(false);
 mTextViewPreview.setTextColor(Color.parseColor("#BEBFBF"));
 mButtonConfirm.setText("确定");
 } 

 /**
 * 利用ContentProvider扫描手机中的图片,此方法在运行在子线程中
 */
 private void getImages() {
 new Thread(new Runnable() { 

  @Override
  public void run() {
  Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
  ContentResolver mContentResolver = ImageSelecteActivity.this.getContentResolver();
  //只查询jpeg和png的图片
//  Cursor mCursor = mContentResolver.query(mImageUri, null,
//   MediaStore.Images.Media.MIME_TYPE + "=? or "
//    + MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?",
//   new String[]{"image/jpeg", "image/png", "image/jpg"}, MediaStore.Images.Media.DATE_MODIFIED);
  Cursor mCursor = mContentResolver.query(mImageUri, null, null, null,
   MediaStore.Images.Media.DATE_MODIFIED);
  if (mCursor == null) {
   return;
  }
  //存放所有图片的路径
  List<String> listAllPic = new ArrayList<String>();
  while (mCursor.moveToNext()) {
   //获取图片的路径
   String path = mCursor.getString(mCursor
    .getColumnIndex(MediaStore.Images.Media.DATA)); 

   //获取该图片的父路径名
   String parentName = new File(path).getParentFile().getName();
   listAllPic.add(path); 

   //根据父路径名将图片放入到mGruopMap中
   if (!mGroupMap.containsKey(parentName)) {
   List<String> chileList = new ArrayList<String>();
   chileList.add(path);
   mGroupMap.put(parentName, chileList);
   } else {
   mGroupMap.get(parentName).add(path);
   }
  }
  //添加所有图片
  mGroupMap.put("所有图片", listAllPic);
  //通知Handler扫描图片完成
  mHandler.sendEmptyMessage(0);
  mCursor.close();
  }
 }).start(); 

 } 

 //获取相册文件夹列表
 private void getGalleryList() {
 Iterator<Map.Entry<String, List<String>>> iterator = mGroupMap.entrySet().iterator();
 while (iterator.hasNext()) {
  Map.Entry<String, List<String>> next = iterator.next();
  ImageBean imageBean = new ImageBean();
  imageBean.setFileName(next.getKey());
  imageBean.setFirstPicPath(next.getValue().get(0));
  imageBean.setCount(next.getValue().size());
  if (next.getKey().equals("所有图片"))
  list.add(0, imageBean);
  else
  list.add(imageBean);
 }
 }
}

·mGroupMap:这个是以文件夹名为key,文件夹内的图片路径集合为value,也就是按照文件夹来分别存储了所有图片的路径。
·listPath:保存的是当前显示在界面上的文件夹内的图片路径集合
·listSelectedPath:保存用户选中的图片路径
·list:保存的是ImageBean的集合,ImageBean保存了文件夹名、里面首张图片的路径以及里面所包含图片的数量,当切换文件夹时用于显示
·getImages():这个方法就是用来扫描手机里图片并保存的,这是在子线程中执行的,显示这可能是一个耗时的任务。通过ContentProvider获取到一个包含所有图片的Cursor,然后遍历这个Cursor把所需的数据就保存在mGroupMap里面,最后利用Handler通知界面更新。
·getGalleryList():这个方法就是mGroupMap里面的数据来给list赋值,也就是产生一个现实文件夹列表所需的数据集合。
·GalleryPopupWindow也就是我们用于显示文件列表的,在67--84行就是一些GalleryPopupWindow的设置,调用showAtLocation方法把PopupWindow显示在距离底部50dp的位置,并设置了点击的回调,当切换了一个文件夹后要做的相关操作就在这里进行。GalleryPopupWindow再待会再具体看看

接下来再看看中间RecyclerView的Adapter

public class ImageSelectAdapter extends RecyclerView.Adapter<ImageSelectAdapter.NViewHolder> { 

 private Context context;
 private List<String> list = new ArrayList<>();
 private OnCheckedChangedListener onCheckedChangedListener;
 private List<Boolean> listChecked = new ArrayList<>(); 

 public ImageSelectAdapter(Context context, List<String> list) {
 this.context = context;
 this.list.addAll(list);
 setListCheched(list);
 } 

 public void update(List<String> list) {
 this.list.clear();
 this.list.addAll(list);
 setListCheched(list);
 notifyDataSetChanged(); 

 } 

 /**
 * 设置listChecked的初始值
 *
 * @param list
 */
 private void setListCheched(List<String> list) {
 listChecked.clear();
 for (int i = 0; i < list.size(); i++) {
  listChecked.add(false);
 }
 } 

 //当点击超过了九张图片,再点击的设置为false
 public void setCheckedBoxFalse(int pos) {
 listChecked.set(pos, false);
 } 

 public interface OnCheckedChangedListener {
 /**
  * @param isChecked 是否选中
  * @param path 点击的图片路径
  * @param cb 点击的CheckBox
  * @param pos 点击的位置
  */
 void onChanged(boolean isChecked, String path, CheckBox cb, int pos);
 } 

 public void setOnCheckedChangedListener(OnCheckedChangedListener onCheckedChangedListener) {
 this.onCheckedChangedListener = onCheckedChangedListener;
 } 

 @Override
 public NViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 return new NViewHolder(LayoutInflater.from(context).inflate(R.layout.item_image_select, parent, false));
 } 

 @Override
 public void onBindViewHolder(final NViewHolder holder, final int position) {
 Glide.with(context).load("file://" + list.get(position)).into(holder.iv);
 holder.cb.setChecked(listChecked.get(position));
 holder.itemView.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  holder.cb.setChecked(!holder.cb.isChecked());
  if (holder.cb.isChecked()) {
   listChecked.set(position, true);
  } else {
   listChecked.set(position, false);
  }
  if (onCheckedChangedListener != null) {
   onCheckedChangedListener.onChanged(holder.cb.isChecked(), list.get(position), holder.cb, position);
  }
  }
 });
 } 

 @Override
 public int getItemCount() {
 return list.size();
 } 

 public class NViewHolder extends RecyclerView.ViewHolder {
 @BindView(R.id.iv_itemImageSelect)
 ImageView iv;
 @BindView(R.id.cb_itemImageSelect)
 CheckBox cb; 

 public NViewHolder(View itemView) {
  super(itemView);
  ButterKnife.bind(this, itemView);
 }
 } 

}

这里Item的布局文件就是一个ImageView加一个CheckBox,根据选中状态改变CheckBox的状态,这里就不贴出来了。
·listChecked:这个集合是用来存储每个位置是否Check的,如果在onBindViewHolder里面不设置CheckBox的状态的话,由于复用问题会出问题,所以想出了用一个集合来保存它们状态的方法,不知道大家有没有其他更好的方法。
·OnCheckedChangedListener:向外暴露的接口,把点击的位置等参数都传到Activity中去。
·update():这个方法用来更新界面的,没有采用直接调notifyDataSetChanged方法是因为,如果数据的数量变化了那么listChecked的数量也要发生变化才行这样才能对应,所以写了这个方法。

再接着看看GalleryPopupWindow

/**
 * Created by lzy on 2017/2/8.
 */
public class GalleryPopupWindow extends PopupWindow {
 private static final String TAG = "lzy"; 

 RecyclerView mRecyclerView; 

 private Activity activity;
 private GalleryPopupWindow.OnItemClickListener onItemClickListener;
 private List<ImageBean> list;
 private GalleryAdapter adapter; 

 public GalleryPopupWindow(Activity context, List<ImageBean> list) {
 super(context);
 this.activity = context;
 this.list = list;
 LayoutInflater inflater = (LayoutInflater) context
  .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 View contentView = inflater.inflate(R.layout.popu_gallery, null);
 initView(contentView); 

 int h = context.getWindowManager().getDefaultDisplay().getHeight();
 int w = context.getWindowManager().getDefaultDisplay().getWidth();
 this.setContentView(contentView);
 this.setWidth(w);
 this.setHeight(ImageSelecteActivity.dp2px(350, context));
 this.setFocusable(false);
 this.setOutsideTouchable(true);
 this.update(); 

 setBackgroundDrawable(new ColorDrawable(000000000));
 } 

 public void notifyDataChanged() {
 adapter.notifyDataSetChanged();
 } 

 private void initView(View contentView) {
 mRecyclerView = (RecyclerView) contentView.findViewById(R.id.rv_gallery);
 mRecyclerView.setLayoutManager(new LinearLayoutManager(activity));
 adapter = new GalleryAdapter(list, activity);
 adapter.setOnItemClickListener(new GalleryAdapter.OnItemClickListener() {
  @Override
  public void onItemClick(String fileName) {
  if (onItemClickListener != null) {
   onItemClickListener.onItemClick(fileName);
   dismiss();
  }
  }
 });
 mRecyclerView.setAdapter(adapter); 

 } 

 //暴露点击的接口
 public interface OnItemClickListener {
 /**
  * @param keyValue
  */
 void onItemClick(String keyValue);
 } 

 public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
 this.onItemClickListener = onItemClickListener;
 }
}

这个PopupWindow的布局文件就是一个RecyclerView,所以这里面也没什么,也就是设置RecyclerView,然后向外暴露一个点击的接口,用于Activity接收是点击了哪个文件夹,所以接口参数也就是文件夹名,再看看这个PopupWindow的Adapter

/**
 * Created by lzy on 2017/2/8.
 */
public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.NViewHolder> { 

 private Context context;
 private List<ImageBean> list;
 private OnItemClickListener onItemClickListener;
 //用于记录是选中的哪一个文件夹
 private int selectedPos; 

 public GalleryAdapter(List<ImageBean> list, Context context) {
 this.list = list;
 this.context = context;
 } 

 public interface OnItemClickListener {
 void onItemClick(String fileName);
 } 

 public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
 this.onItemClickListener = onItemClickListener;
 } 

 @Override
 public NViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 return new NViewHolder(LayoutInflater.from(context).inflate(R.layout.item_gallery, parent, false));
 } 

 @Override
 public void onBindViewHolder(NViewHolder holder, final int position) {
 holder.itemView.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  selectedPos = position;
  notifyDataSetChanged();
  if (onItemClickListener != null) {
   onItemClickListener.onItemClick(list.get(position).getFileName());
  }
  }
 });
 if (position == selectedPos) {
  holder.ivCheck.setVisibility(View.VISIBLE);
 } else {
  holder.ivCheck.setVisibility(View.GONE);
 }
 holder.tvCount.setText(list.get(position).getCount() + "张");
 holder.tvName.setText(list.get(position).getFileName());
 Glide.with(context).load("file://" + list.get(position).getFirstPicPath()).into(holder.iv);
 } 

 @Override
 public int getItemCount() {
 return list.size();
 } 

 public class NViewHolder extends RecyclerView.ViewHolder {
 @BindView(R.id.iv_itemGallery)
 ImageView iv;
 @BindView(R.id.tv_itemGallery_name)
 TextView tvName;
 @BindView(R.id.tv_itemGallery_count)
 TextView tvCount;
 @BindView(R.id.iv_itemGallery_check)
 ImageView ivCheck; 

 public NViewHolder(View itemView) {
  super(itemView);
  ButterKnife.bind(this, itemView);
 }
 } 

}

这里有个接口是把点击的文件名传递给PopupWindow,然后再给Activity,selectedPos是用来记录选择的是哪一个文件夹,显示对应的CheckBox。

这里就差不多完成了,感兴趣的可以下载Demo来看看。再说一下,这里显示图片都是采用的Glide,使用也很方便,我们获取的图片路径都是文件路径,如果要转化为Bitmap也可以直接调用Glide的方法就可以轻松实现,如下所示:

Glide.with(this).load("file://" + listSelectedPath.get(i)).asBitmap().into(new SimpleTarget<Bitmap>() {
   @Override
   public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
    Log.i(TAG, "onResourceReady: " + resource);
   }
   });

其中找寻控件都没有使用findViewById,而是采用的ButterKnife,节约了大量的时间,顺便说说导入的方法
在app下面的build.gradle中加入以下:
apply plugin: 'com.neenbedankt.android-apt'

apt 'com.jakewharton:butterknife-compiler:8.1.0' 
    compile 'com.github.bumptech.glide:glide:3.5.2'

项目下面的build.gradle

//添加apt插件
 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

添加插件
File->Setting->Plugins  搜索zelezny,如下所示

当需要使用的时候,直接在光标移动到布局文件,点击Alt+Insert,选择Generate ButterKnife Injections

就出现如下界面,可以自动生成了

源码地址:Android图片选择及预览缩放

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android选择图片或拍照图片上传到服务器

    最近要搞一个项目,需要上传相册和拍照的图片,不负所望,终于完成了!  不过需要说明一下,其实网上很多教程拍照的图片,都是缩略图不是很清晰,所以需要在调用照相机的时候,事先生成一个地址,用于标识拍照的图片URI 具体上传代码: 1.选择图片和上传界面,包括上传完成和异常的回调监听 package com.spring.sky.image.upload; import java.util.HashMap; import java.util.Map; import android.app.Activi

  • android中写一个内部类来选择文件夹中指定的图片类型实例说明

    复制代码 代码如下: /**本类是用来选择文件夹中是.jpg类型的图片*/ private class JpgFileFilter implements FilenameFilter{ @Override public boolean accept(File dir, String filename) { // TODO Auto-generated method stub return filename.endsWith(".jpg"); } }

  • Android仿微信照片选择器实现预览查看图片

    好了下面进入正题,我们先看一下实现效果吧: 下面来介绍一下代码: 本思路就是: 1.先到手机中扫描jpeg和png的图片 2.获取导图片的路径和图片的父路径名也就是文件夹名 3.将图片路径和文件夹名分别添加导数据源中 4.数据源有了就是显示了,文件夹显示是利用的popwindow,而图片显示则是GridView 看一下具体代码: 首先开启一个线程去扫描图片 /** * 利用ContentProvider扫描手机中的图片,此方法在运行在子线程中 完成图片的扫描,最终获得jpg最多的那个文件夹 */

  • Android仿微信选择图片和拍照功能

    本文实例为大家分享了 Android微信选择图片的具体代码,和微信拍照功能,供大家参考,具体内容如下 1.Android6.0系统,对于权限的使用都是需要申请,选择图片和拍照需要申请Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE这两个权限. if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageM

  • Android实现QQ图片说说照片选择效果

    本文实例为大家分享了Android实现QQ图片说说照片选择的具体代码,供大家参考,具体内容如下 效果展示 布局文件 布局是很简单的,一个GridView,直接上布局: layout/activity_add_photo.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/andr

  • 浅谈谈Android 图片选择器

    ImageSelector 简介 Android自定义相册,实现了拍照.图片选择(单选/多选).ImageLoader无绑定 任由开发者选择 https://github.com/YancyYe/ImageSelector Demo Download Apk 更新内容 UI重改 所有功能可配置 解决OOM情况 图片手动选择 支持汉语和英语 截图展示 使用说明 步骤一: 通过Gradle抓取 dependencies { compile 'com.yancy.imageselector:image

  • 分享实现Android图片选择的两种方式

    Android选择图片的两种方式: 第一种:单张选取 通过隐式启动activity,跳转到相册选择一张返回结果 关键代码如下: 发送请求: private static final int PICTURE = 10086; //requestcode Intent intent = new Intent(); if (Build.VERSION.SDK_INT < 19) {//因为Android SDK在4.4版本后图片action变化了 所以在这里先判断一下 intent.setAction

  • android完美实现 拍照 选择图片 剪裁等代码分享

    前言,版本兼容问题主要是由于4.4以前和4.4以后的Uri的格式不同所造成的错误 1.拍照 和选择图片   ①选择图片 intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); startActivityForResult(intent, GALLERY_REQUEST_CODE); ②拍照 intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE)

  • Android拍照或从图库选择图片并裁剪

    今天看<第一行代码>上面关于拍照和从相册选取图片那一部分,发现始终出不来效果,所以搜索其他资料学习一下相关知识,写一个简单的Demo. 一. 拍照选择图片 1.使用隐式Intent启动相机 //构建隐式Intent Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //调用系统相机 startActivityForResult(intent, 1); 2.处理相机拍照返回的结果 //用户点击了取消 if(data == n

  • Android实现拍照、选择图片并裁剪图片功能

    一. 实现拍照.选择图片并裁剪图片效果 按照之前博客的风格,首先看下实现效果. 二. uCrop项目应用 想起之前看到的Yalantis/uCrop效果比较绚,但是研究源码之后发现在定制界面方面还是有一点的限制,于是在它的基础上做了修改Android-Crop,把定制界面独立出来,让用户去自由设置.下图为使用Android-Crop实现的模仿微信选择图片并裁剪Demo. 三. 实现思路 比较简单的选择设备图片裁剪,并将裁剪后的图片保存到指定路径: 调用系统拍照,将拍照图片保存在SD卡,然后裁剪图

随机推荐