Android 图片选择器

图片选择器,遍历系统所有图片并显示,点击查看大图,长按选中,并将结果返回

 

 

字体颜色res/color建立text_selecor.xml

1 <selector xmlns:android="http://schemas.android.com/apk/res/android">
2     <item android:color="@android:color/white" android:state_enabled="true"/>
3     <item android:color="@android:color/darker_gray" android:state_enabled="false"/>
4 </selector>
text_selector.xml

图片选择按钮

1 <selector xmlns:android="http://schemas.android.com/apk/res/android">
2     <item android:state_checked="true" android:drawable="@mipmap/sel_check"/>
3     <item android:state_checked="false" android:drawable="@mipmap/sel_nor"/>
4 </selector>
item_selector

遍历之后将所有图片显示

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:background="@android:color/background_dark"
 4     android:layout_height="match_parent">
 5     <ImageView
 6         android:id="@+id/iv_img"
 7         android:layout_width="match_parent"
 8         android:layout_height="match_parent"
 9         android:scaleType="centerCrop"
10         android:layout_margin="10dp"
11         android:src="@mipmap/camera"/>
12     <CheckBox
13         android:id="@+id/cb_btn"
14         android:layout_margin="15dp"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content"
17         android:layout_alignParentRight="true"
18         android:button="@drawable/item_selector"/>
19 
20 </RelativeLayout>
item_image.xml
 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:id="@+id/activity_main"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     android:orientation="vertical"
 7     tools:context="com.example.lesson10_picselectordemo.MainActivity">
 8 
 9     <RelativeLayout
10         android:layout_width="match_parent"
11         android:layout_height="wrap_content"
12         android:background="@android:color/holo_blue_dark"
13         android:padding="10dp">
14 
15         <TextView
16             android:layout_width="wrap_content"
17             android:layout_height="wrap_content"
18             android:layout_centerHorizontal="true"
19             android:text="图片选择"
20             android:textColor="@android:color/white"
21             android:textSize="18sp" />
22 
23         <TextView
24             android:id="@+id/tv_finish"
25             android:layout_width="wrap_content"
26             android:layout_height="wrap_content"
27             android:layout_alignParentRight="true"
28             android:enabled="false"
29             android:text="完成"
30             android:textColor="@color/text_selector" />
31 
32     </RelativeLayout>
33 
34     <GridView
35         android:id="@+id/gv_image"
36         android:layout_width="match_parent"
37         android:layout_height="wrap_content"
38         android:numColumns="4"/>
39 </LinearLayout>
activity_main.xml

适配器,当适配数据类型不确定时,可以使用泛型.继承BaseAdapter都要重写那几个方法,这里将他们抽出来

 1 /**
 2  * 适配数据类型不确定,可以使用泛型
 3  * 也可以是使用extends限定泛型,比如接口IGetName有个getName()方法,只要T继承IGetName实现方法,就可以使用该方法
 4  * Created by Administrator on 2016/10/24 0024.
 5  */
 6 
 7 public abstract class ListItemAdapter<T> extends BaseAdapter {
 8 
 9     //适配器需要上下文,数据
10     //使用ptotected修饰符,使子类也可以用
11     protected Context mContext;
12     protected List<T> mList;
13 
14     public ListItemAdapter(Context mContext,List<T> mList){
15         this.mContext = mContext;
16         this.mList = mList;
17     }
18 
19     @Override
20     public int getCount() {
21         return mList.size();
22     }
23 
24     @Override
25     public T getItem(int position) {
26         return mList.get(position);
27     }
28 
29     @Override
30     public long getItemId(int position) {
31         return position;
32     }
33 }
ListItemAdapter.java

然后ImageAdapter只要继承ListItemAdapter重写getView即可

  1 public class ImageAdapter extends ListItemAdapter<File> {
  2 
  3     private boolean select = false;
  4 
  5     public void open(int position){
  6         select = true;
  7         booleanArray.put(position,true);
  8         if(onImageCheckedListener != null){
  9             onImageCheckedListener.onImageChecked(true);
 10         }
 11         this.notifyDataSetChanged();
 12     }
 13 
 14     public void close(){
 15         select = false;
 16         booleanArray.clear();
 17         this.notifyDataSetChanged();
 18     }
 19 
 20     public ImageAdapter(Context mContext, List<File> mList) {
 21         super(mContext, mList);
 22     }
 23 
 24     @Override
 25     public int getCount() {
 26         //多出来的第一张为照相机,点击进入照相机
 27         return super.getCount()+1;
 28     }
 29 
 30 
 31     /**
 32      * 这里布局重用,使用checkbox会导致很多问题,
 33      * 勾选了一个,下拉之后发现下面也被勾选了一个
 34      * 这时,我们可以使用HashMap<Integer,Boolean>,是否被勾选
 35      *
 36      * 这里推荐使用另外一个类SparseBooleanArray
 37      *
 38      * @param position
 39      * @param convertView
 40      * @param parent
 41      * @return
 42      */
 43     SparseBooleanArray booleanArray = new SparseBooleanArray();
 44 
 45     public SparseBooleanArray getBooleanArray() {
 46         return booleanArray;
 47     }
 48 
 49     @Override
 50     public View getView(final int position, View convertView, ViewGroup parent) {
 51         ViewHolder viewHolder;
 52         if(convertView == null){
 53             convertView = View.inflate(mContext,R.layout.item_image,null);
 54             viewHolder = new ViewHolder(convertView);
 55             convertView.setTag(viewHolder);
 56         }
 57 
 58         viewHolder = (ViewHolder) convertView.getTag();
 59 
 60         if(position == 0){
 61             //照相机
 62             viewHolder.iv_img.setImageResource(R.mipmap.camera);
 63             viewHolder.cb_btn.setVisibility(View.GONE);
 64         }else{
 65 
 66             //设置图片
 67             viewHolder.iv_img.setImageURI(Uri.fromFile(mList.get(position - 1)));
 68 
 69             if(select) {
 70                 viewHolder.cb_btn.setVisibility(View.VISIBLE);
 71                 //是否需要勾选呢?
 72                 Boolean b = booleanArray.get(position);
 73                 if (b == null || b == false) {
 74                     viewHolder.cb_btn.setChecked(false);
 75                 } else {
 76                     viewHolder.cb_btn.setChecked(true);
 77                 }
 78 
 79 
 80                 //checkbox不能设置onCheckChange监听,因为上面setChecked导致下面isCheck也会跟着变化
 81             /*viewHolder.cb_btn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
 82                 @Override
 83                 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
 84                     booleanArray.put(position,isChecked);
 85                 }
 86             });*/
 87                 viewHolder.cb_btn.setOnClickListener(new View.OnClickListener() {
 88                     @Override
 89                     public void onClick(View v) {
 90                         //position有可能不存在,为空,这里必须给Boolean
 91                         Boolean b = booleanArray.get(position);
 92                         if (b == null || b == false) {
 93                             b = true;
 94                         } else {
 95                             b = false;
 96                         }
 97                         booleanArray.put(position, b);
 98 
 99                         //判断所有boolean ,如果没有一个true,则关闭
100                         for (int i = 0; i <booleanArray.size() ; i++) {
101                             //i一定存在,所以可以给boolean
102                             boolean isChecked = booleanArray.get(booleanArray.keyAt(i));
103                             if(isChecked){
104                                 //说明有被勾选的值
105                                 if(onImageCheckedListener != null){
106                                     onImageCheckedListener.onImageChecked(true);
107                                 }
108                                 return;
109                             }
110                         }
111                         //没有被勾选的值,
112                         if(onImageCheckedListener != null)
113                             onImageCheckedListener.onImageChecked(false);
114                         //关闭
115                         close();
116                     }
117                 });
118             }else {
119                 viewHolder.cb_btn.setVisibility(View.GONE);
120             }
121         }
122         return convertView;
123     }
124 
125     //回调方法
126     //写在需要执行方法的地方
127     //实现,在需要返回的地方
128     public interface  OnImageCheckedListener{
129         void onImageChecked(boolean b);
130     }
131 
132     private OnImageCheckedListener onImageCheckedListener;
133 
134     //alt + insert
135     public void setOnImageCheckedListener(OnImageCheckedListener onImageCheckedListener) {
136         this.onImageCheckedListener = onImageCheckedListener;
137     }
138 
139 
140     class ViewHolder{
141         ImageView iv_img;
142         CheckBox cb_btn;
143 
144         public ViewHolder(View convertView){
145 
146             iv_img = (ImageView) convertView.findViewById(R.id.iv_img);
147             int width = mContext.getResources().getDisplayMetrics().widthPixels / 4 -2;
148             RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width,width);
149             iv_img.setLayoutParams(params);
150             cb_btn = (CheckBox) convertView.findViewById(R.id.cb_btn);
151         }
152     }
153 }
ImageAdapter.java

点击查看大图

 1 public class ShowBigImage extends AppCompatActivity{
 2 
 3     @Override
 4     protected void onCreate(@Nullable Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         ImageView img = new ImageView(this);
 7 
 8         File file = (File) getIntent().getSerializableExtra("img");
 9         img.setImageURI(Uri.fromFile(file));
10         setContentView(img);
11     }
12 }
ShowBigImage.java
  1 public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener, ImageAdapter.OnImageCheckedListener, View.OnClickListener {
  2     private static final int CAMERA_CODE = 1;
  3     //SD卡所有图片
  4     List<File> filesList = new ArrayList<>();
  5 
  6     ProgressDialog dialog;
  7 
  8     GridView gv_image;
  9     TextView tv_finish;
 10     ImageAdapter adapter;
 11 
 12     @Override
 13     protected void onCreate(Bundle savedInstanceState) {
 14         super.onCreate(savedInstanceState);
 15         setContentView(R.layout.activity_main);
 16 
 17         //加载数据
 18         loadData();
 19         //初始化视图
 20         initView();
 21 
 22     }
 23 
 24     private void initView() {
 25         gv_image = (GridView) findViewById(R.id.gv_image);
 26         tv_finish = (TextView) findViewById(R.id.tv_finish);
 27         adapter = new ImageAdapter(this,filesList);
 28         tv_finish.setOnClickListener(this);
 29         adapter.setOnImageCheckedListener(this);
 30         gv_image.setAdapter(adapter);
 31         //点击图片查看大图
 32         gv_image.setOnItemClickListener(this);
 33         //长按选择图片
 34         gv_image.setOnItemLongClickListener(this);
 35     }
 36 
 37     public ProgressDialog showDialog(){
 38         //显示Dialog
 39         dialog = new ProgressDialog(this);
 40         dialog.setTitle("加载数据");
 41         dialog.setMessage("正在加载数据,请稍等...");
 42         dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
 43         dialog.show();
 44 
 45         return dialog;
 46     }
 47 
 48     public void loadData(){
 49         dialog = showDialog();
 50 
 51         //数据加载不能阻塞UI
 52         //在子线程中加载
 53         new Thread(){
 54             @Override
 55             public void run() {
 56                 super.run();
 57                 //开始递归遍历SD卡根目录
 58                 /*public static File getExternalStorageDirectory() {
 59                     throwIfUserRequired();
 60                     return sCurrentUser.getExternalDirs()[0];//获取第0张SD卡如果想要其他SD卡,只要重写这个方法即可
 61                 }*/
 62                 File SDDir = Environment.getExternalStorageDirectory();
 63                 getFiles(SDDir);
 64 
 65                 //数据加载完毕,要关闭Dialog
 66                 runOnUiThread(new Runnable() {
 67                     @Override
 68                     public void run() {
 69                         dialog.dismiss();
 70                         //刷新适配器
 71                         adapter.notifyDataSetChanged();
 72                     }
 73                 });
 74             }
 75         }.start();
 76     }
 77 
 78     public void getFiles(File dir){
 79         File[] files = dir.listFiles();
 80 
 81         if(files == null){
 82             return;
 83         }
 84 
 85         //开始遍历
 86         for (File file : files) {
 87             if(file.isDirectory()){
 88                 getFiles(file);
 89             }else{
 90                 if(file.getName().endsWith("jpg") || file.getName().endsWith("png")){
 91                     filesList.add(file);
 92                 }
 93             }
 94         }
 95     }
 96 
 97     File cameraFile;
 98     @Override
 99     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
100         //点击查看大图
101         if(position == 0){
102             //getAbsolutePath默认没有带"/"
103             cameraFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/DCIM/"+System.currentTimeMillis()+".png");
104             //打开照相机
105             Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
106             //图片保存位置
107             intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile));
108             startActivityForResult(intent,CAMERA_CODE);
109 
110         }else{
111             //打开大图
112             File file = filesList.get(position - 1);
113             //带数据点开大图
114             Intent intent = new Intent(this,ShowBigImage.class);
115             intent.putExtra("img",file);
116             startActivity(intent);
117         }
118 
119     }
120 
121     @Override
122     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
123         super.onActivityResult(requestCode, resultCode, data);
124         if(requestCode == requestCode && resultCode == RESULT_OK){
125             //照相机的图片永远放在第一个
126             filesList.add(0,cameraFile);
127             adapter.notifyDataSetChanged();
128         }
129     }
130 
131     @Override
132     public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
133         //长按选择图片
134         //照相机不能长按
135         if(position == 0){
136             return false;
137         }else{
138             adapter.open(position);
139         }
140 
141         return true;
142     }
143 
144     @Override
145     public void onImageChecked(boolean b) {
146         //b代表适配器中有没有被勾选的值
147         tv_finish.setEnabled(b);
148     }
149 
150     @Override
151     public void onClick(View v) {
152         //选择的图片
153         //不能使用泛型,ArrayList才实现了序列化,List没有实现
154         ArrayList<File> resultList = new ArrayList<>();
155         //点击完成,带参返回
156         //需要知道哪些数据被选中
157         //通过是是适配器中的boolArray的为true的选中项来加载file
158         SparseBooleanArray booleanArray = adapter.getBooleanArray();
159         for (int i = 0; i <booleanArray.size() ; i++) {
160             boolean isSelected = booleanArray.get(booleanArray.keyAt(i));
161             if(isSelected){
162                 int position = booleanArray.keyAt(i);
163                 //剔除掉第一张照相机图片
164                 resultList.add(filesList.get(position-1));
165             }
166         }
167         Intent intent = new Intent();
168         intent.putExtra("list",resultList);
169         //返回数据
170         setResult(RESULT_OK,intent);
171         finish();
172     }
173 }
MainActivity.java

AndroidManifest.xml设置权限,注册活动

设置intent-filter <action> 并设置出口exported

 1 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 2     package="com.example.lesson10_picselectordemo">
 3 
 4     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 5 
 6     <application android:allowBackup="true" android:icon="@mipmap/ic_launcher"
 7         android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
 8         <activity android:name=".MainActivity"
 9             android:exported="true">
10             <intent-filter>
11                 <action android:name="SelectPicture"/>
12                 <action android:name="android.intent.action.MAIN" />
13                 <category android:name="android.intent.category.DEFAULT"/>
14                 <category android:name="android.intent.category.LAUNCHER" />
15             </intent-filter>
16         </activity>
17         <activity android:name=".ShowBigImage"/>
18     </application>
19 
20 </manifest>
AndroidManifest.xml

 

测试类

点击Buttong,打开图片选择器

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:id="@+id/activity_main"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     tools:context="com.example.lesson10_picselectordemotest.MainActivity">
 7 
 8     <Button
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:onClick="toPicSelectorDemo"
12         android:layout_centerInParent="true"
13         android:text="图片选择器启动另一个Module" />
14 </RelativeLayout>
activity_main.xml
 1 public class MainActivity extends AppCompatActivity {
 2 
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7     }
 8 
 9     public void toPicSelectorDemo(View v){
10 
11          startActivityForResult(new Intent("SelectPicture"),1);
12     }
13 
14     @Override
15     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
16         super.onActivityResult(requestCode, resultCode, data);
17         if(resultCode == RESULT_OK){
18             ArrayList<File> file = (ArrayList<File>) data.getSerializableExtra("list");
19             Toast.makeText(this,file.toString(),Toast.LENGTH_SHORT).show();
20         }
21     }
22 }
MainActivity.java

 

posted on 2016-10-25 20:50  语风6649  阅读(634)  评论(0编辑  收藏  举报

导航