Android 图片选择详解及实例代码

Android 图片选择

可以达到的效果:

1.第一个图片的位置放照相机,点击打开照相机

2.其余的是显示全部存储的图片,点击一次是查看大图,长按则是每张图片出现一个checkBox,可以进行选择

下面是实例效果图

MainActivity 类

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener, ImageAdapter.OnImageCheckListener, View.OnClickListener { private static final int CAMERA_CODE = 12; List<File> fileList = new ArrayList<>(); ImageAdapter adapter; GridView gvImage; TextView tvFinish; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //弹出对话框,加载数据 loadData(); } private void initView() { gvImage = (GridView) findViewById(R.id.gv_image); tvFinish = (TextView) findViewById(R.id.tv_finish); adapter = new ImageAdapter(this, fileList); adapter.setOnImageCheckListener(this); gvImage.setAdapter(adapter); gvImage.setOnItemClickListener(this); gvImage.setOnItemLongClickListener(this); tvFinish.setOnClickListener(this); } private ProgressDialog showProgressDialog() { //弹出对话框 ProgressDialog dialog = new ProgressDialog(this); dialog.setTitle("提示"); dialog.setMessage("正在加载图片,请稍等。。。"); dialog.show(); return dialog; } private void loadData() { final ProgressDialog dialog = showProgressDialog(); //开启线程 new Thread() { @Override public void run() { super.run(); //递归 //从sd卡中获取所有图片 getFile(Environment.getExternalStorageDirectory()); runOnUiThread(new Runnable() { @Override public void run() { dialog.dismiss(); adapter.notifyDataSetChanged(); } }); } }.start(); } public void getFile(File dir) { //1. 获取子目录 File[] files = dir.listFiles(); if (files == null) return; //集合或者数组去点for for (File file : files) { if (file.isDirectory()) getFile(file); else { //加载图片 if (file.getName().endsWith(".png") || file.getName().endsWith(".jpg")) { fileList.add(file); } } } } File cameraFile; //点击 @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (position == 0) { //getAbsolutePath返回的路径是没有"/" cameraFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM/" + System.currentTimeMillis() + ".png"); //打开照相机 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //照相机需要带数据 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile)); startActivityForResult(intent, CAMERA_CODE); } else { //打开大图 File file = fileList.get(position - 1); //带数据跳转到现实大图 Intent intent = new Intent(this, ShowBigImage.class); intent.putExtra("file", file); startActivity(intent); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.e("TAG", resultCode + "---------------------"); if (requestCode == CAMERA_CODE && resultCode == RESULT_OK) { Log.e("TAG", (cameraFile.exists()) + ""); fileList.add(0, cameraFile); adapter.notifyDataSetChanged(); } } //长按 @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { if (position == 0) return false; else { adapter.open(position); } return true; } @Override public void onImageCheck(boolean b) { //b代表 适配器中 有没有勾选的值 tvFinish.setEnabled(b); } @Override public void onClick(View v) { //需要知道有哪些数据被选中 //不能使用泛型,ArrayList才实现了序列化,List没有实现 ArrayList<File> resultList = new ArrayList<>(); //通过适配器中的 为true的 选中的项来加载file SparseBooleanArray booleanArray = adapter.getBooleanArray(); for (int i = 0; i < booleanArray.size(); i++) { boolean isCheck = booleanArray.get(booleanArray.keyAt(i)); if (isCheck) { int position = booleanArray.keyAt(i); resultList.add(fileList.get(position - 1)); } } Intent intent = new Intent(); intent.putExtra("list", resultList); //返回数据 setResult(RESULT_OK, intent); finish(); } }

ImageAdapter 类

public class ImageAdapter extends ListItemAdapter<File> { private boolean select = false; public void open(int posisiont) { select = true; booleanArray.put(posisiont, true); if (onImageCheckListener != null) onImageCheckListener.onImageCheck(true); this.notifyDataSetChanged(); } public void close() { select = false; booleanArray.clear(); notifyDataSetChanged(); } //position //HashMap<Integer, Boolean> map = new HashMap<>(); private SparseBooleanArray booleanArray = new SparseBooleanArray(); public SparseBooleanArray getBooleanArray() { return booleanArray; } public ImageAdapter(Context context, List<File> list) { super(context, list); } @Override public int getCount() { //多出来的就是照相机 return super.getCount() + 1; } // @Override // public View getView(int position, View convertView, ViewGroup parent) { // if (convertView == null) { // ImageView iv = new ImageView(mContext); // iv.setScaleType(ImageView.ScaleType.CENTER_CROP); // iv.setBackgroundColor(Color.argb(0xFF, 0x07, 0x05, 0x18)); // int width = mContext.getResources().getDisplayMetrics().widthPixels / 3 - 2; // GridView.LayoutParams params = new GridView.LayoutParams(width, width); // iv.setPadding(2, 2, 2, 2); // iv.setLayoutParams(params); // convertView = iv; // } // ImageView iv = (ImageView) convertView; // if (position == 0) { // //照相机 // iv.setImageResource(R.mipmap.camera); // } else { // iv.setImageURI(Uri.fromFile(getItem(position - 1))); // } // return convertView; // } @Override public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = View.inflate(mContext, R.layout.item_image, null); holder = new ViewHolder(convertView); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } if (position == 0) { holder.image.setImageResource(R.mipmap.camera); holder.checkBox.setVisibility(View.GONE); } else { holder.image.setImageURI(Uri.fromFile(getItem(position - 1))); if (select) { holder.checkBox.setVisibility(View.VISIBLE); //当前的需不需要勾选呢 //null Boolean b = booleanArray.get(position); if (b == null || b == false) { holder.checkBox.setChecked(false); } else { holder.checkBox.setChecked(true); } //item点击和布局冲突 holder.checkBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Boolean b = booleanArray.get(position); if (b == null || b == false) b = true; else b = false; booleanArray.put(position, b); //判断所有的boolean,如果已经没有一个true 关闭 for (int i = 0; i < booleanArray.size(); i++) { //4-true 0==false //两个值 key -- > 3 4 // 0 1 2 3 4 5 boolean isChecked = booleanArray.get(booleanArray.keyAt(i)); Log.e("TAG", "----" + isChecked); Log.e("TAG", booleanArray.toString()); if (isChecked) { //有被勾选的值 if (onImageCheckListener != null) onImageCheckListener.onImageCheck(true); return; } } if (onImageCheckListener != null) onImageCheckListener.onImageCheck(false); //没有被勾选的值了 //关闭 close(); } }); } else { holder.checkBox.setVisibility(View.GONE); } //不能使用onCheck // holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // @Override // public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // booleanArray.put(position, isChecked); // } // }); } return convertView; } //回调方法。 //写在需要执行方法的地方 //他实现 在需要返回的地方 public interface OnImageCheckListener { public void onImageCheck(boolean b); } private OnImageCheckListener onImageCheckListener; //alt+insert public void setOnImageCheckListener(OnImageCheckListener onImageCheckListener) { this.onImageCheckListener = onImageCheckListener; } class ViewHolder { ImageView image; CheckBox checkBox; public ViewHolder(View convertView) { image = (ImageView) convertView.findViewById(R.id.iv_image); int width = mContext.getResources().getDisplayMetrics().widthPixels / 3 - 2; RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, width); image.setLayoutParams(params); checkBox = (CheckBox) convertView.findViewById(R.id.cb_check); } } }

ListItemAdapter类

//也可以用 extends 来限制一个泛型的父类 //在类的后面定义一个泛型 public abstract class ListItemAdapter<T> extends BaseAdapter { protected Context mContext; protected List<T> mList; //必须要有上下文,数据 //List<File> List<String> public ListItemAdapter(Context context, List<T> list) { mContext = context; mList = list; } //适配器去加载一个List public void setList(List<T> list) { this.mList = list; notifyDataSetChanged(); } @Override public int getCount() { return mList == null ? 0 : mList.size(); } @Override public T getItem(int position) { return mList.get(position); } @Override public long getItemId(int position) { return position; } }

ShowBigImage 类

public class ShowBigImage extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ImageView iv = new ImageView(this); File file = (File) getIntent().getSerializableExtra("file"); iv.setImageURI(Uri.fromFile(file)); setContentView(iv); } }

main_xml

<?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:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.administrator.imageselector.MainActivity"> <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/colorPrimary"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="选取图片" android:textColor="@android:color/white" android:textSize="18sp" /> <TextView android:id="@+id/tv_finish" 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="@color/textenable" /> </RelativeLayout> <GridView android:id="@+id/gv_image" android:layout_width="match_parent" android:layout_height="match_parent" android:horizontalSpacing="2dp" android:numColumns="3" android:verticalSpacing="2dp" /> </LinearLayout>

item_image.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#03030a"> <ImageView android:id="@+id/iv_image" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="5dp" android:scaleType="centerCrop" android:src="@mipmap/camera" /> <CheckBox android:id="@+id/cb_check" android:button="@null" android:layout_width="20dp" android:layout_height="20dp" android:background="@drawable/cb_selector" android:layout_alignParentRight="true" android:layout_margin="10dp" /> </RelativeLayout>

res下color文件夹下的textenable.xml

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@android:color/white" android:state_enabled="true" /> <item android:color="@android:color/darker_gray" android:state_enabled="false" /> </selector>

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

时间: 2024-09-20 09:39:53

Android 图片选择详解及实例代码的相关文章

Android 文件选择器详解及实例代码_Android

     本文给大家讲解下Android文件选择器的使用.实际上就是获取用户在SD卡中选择的文件或文件夹的路径,这很像C#中的OpenFileDialog控件.        此实例的实现过程很简单,这样可以让大家快速的熟悉Android文件选择器,提高开发效率.        网上曾经见到过一个关于文件选择器的实例,很多人都看过,本实例是根据它修改而成的,但更容易理解,效率也更高,另外,本实例有自己的特点:        1.监听了用户按下Back键的事件,使其返回上一层目录.       

Android GPS定位详解及实例代码_Android

      GPS定位是智能手机上一个比较有意思的功能,LBS等服务都有效的利用了GPS定位功能.本文就跟大家分享下Android开发中的GPS定位知识.        一.Android基础知识准备        1.Activity类        每一种移动开发环境都有自己的基类.如J2ME应用程序的基类是midlets,BREW的基类是applets,而Android程序的基类是Activity.这个activity为我们提供了对移动操作系统的基本功能和事件的访问.这个类包含了基本的构造

Android语音识别技术详解及实例代码_Android

   今天从网上找了个例子实现了语音识别,个人感觉挺好玩的,就把代码贴出来与大家分享下:          Android中主要通过RecognizerIntent来实现语音识别,其实代码比较简单,但是如果找不到设置,就会抛出异常ActivityNotFoundException,所以我们需要捕捉这个异常.而且语音识别在模拟器上是无法测试的,因为语音识别是访问google云端数据,所以如果手机的网络没有开启,就无法实现识别声音的!一定要开启手机的网络,如果手机不存在语音识别功能的话,也是无法启用

Android ListView position详解及实例代码_Android

我们在使用ListView的时候,一般都会为ListView添加一个响应事件android.widget.AdapterView.OnItemClickListener.对OnItemClickListener的position和id参数,我相信有些人在这上面走了些弯路.     在使用listview的时候,我们经常会在listview的监听事件中,例如OnItemClickListener(onItemClick)中,或listview的adapter中(getView.getItem.ge

android 通知Notification详解及实例代码

android Notification实例详解 1.使用Builder模式来创建 2.必须要设置一个smallIcon,还可以设置setTicker 3.可以设置 setContentTitle,setContentInfo,setContentText,setWhen 4.可以设置setDefaults(闪屏,声音,震动),通过Notification设置flags(能不能被清除) 5.发送需要获取一个NotificationManager(getSystemService来获取);noti

Android 百分比布局详解及实例代码

Android 百分比布局 1.引入:compile 'com.android.support:percent:24.0.0' 2.点开源码可以看到,主要有两个布局类PercentFrameLayout和PercentRelativeLayout,一个工具类PercentLayoutHelper. 3.点开布局类比如PercentRelativeLayout的源码,可以看到实现的很简单. public class PercentRelativeLayout extends RelativeLay

Android ListView position详解及实例代码

我们在使用ListView的时候,一般都会为ListView添加一个响应事件android.widget.AdapterView.OnItemClickListener.对OnItemClickListener的position和id参数,我相信有些人在这上面走了些弯路. 在使用listview的时候,我们经常会在listview的监听事件中,例如OnItemClickListener(onItemClick)中,或listview的adapter中(getView.getItem.getIte

Android 消息机制详解及实例代码

Android 消息机制 1.概述 Android应用启动时,会默认有一个主线程(UI线程),在这个线程中会关联一个消息队列(MessageQueue),所有的操作都会被封装成消息队列然后交给主线程处理.为了保证主线程不会退出,会将消息队列的操作放在一个死循环中,程序就相当于一直执行死循环,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数(handlerMessage),执行完成一个消息后则继续循环,若消息队列为空,线程则会阻塞等待.因此不会退出.如下图所示: Handl

Android语音识别技术详解及实例代码

今天从网上找了个例子实现了语音识别,个人感觉挺好玩的,就把代码贴出来与大家分享下: Android中主要通过RecognizerIntent来实现语音识别,其实代码比较简单,但是如果找不到设置,就会抛出异常ActivityNotFoundException,所以我们需要捕捉这个异常.而且语音识别在模拟器上是无法测试的,因为语音识别是访问google云端数据,所以如果手机的网络没有开启,就无法实现识别声音的!一定要开启手机的网络,如果手机不存在语音识别功能的话,也是无法启用识别! 下面是Recog