zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Android ANR 知多少
    电源管理
    功耗分析
    手机功耗测试
    Battery Historian
    Android 电量优化
    Android手机功耗
    功耗 Log 抓取要求规范
    Android 手机无法进入系统解决方案
    定屏死机问题操作指南
  • 原文地址:https://www.cnblogs.com/Claire6649/p/5998183.html
Copyright © 2011-2022 走看看