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

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

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 图片选择器的更多相关文章

  1. Android图片选择器--仿QQ

    当做一款APP,需要选择本地图片时,首先考虑的无疑是系统相册,但是Android手机五花八门,再者手机像素的提升,大图无法返回等异常因数,导致适配机型比较困难,微信.QQ都相继的在自己的APP里集成了 ...

  2. 016 Android 图片选择器(在选中和未选中的过程中,切换展示图片)

    1.目标效果 在选中和未选中的过程中,切换展示图片 2.实现方法 (1)在app--->res--->drawable 右击drawable文件夹右键,new ---->drawab ...

  3. Android图片选择器

    1.概述 应公司项目需求,要做一个图片选择器,网上搜索了一些源码,我在别人的基础上进行了修改,另外页面也进行了重整,我的是先加载图片文件夹列表,然后再进入选择图片.            参考博客地址 ...

  4. Android之仿微信图片选择器

    先上效果图.第一张图显示的是“相机”文件夹中的所有图片:通过点击多张图片可以到第二张图所示的效果(被选择的图片会变暗,同时选择按钮变亮):点击最下面的那一栏可以到第三张图所示的效果(显示手机中所有包含 ...

  5. [转]Android 超高仿微信图片选择器 图片该这么加载

    快速加载本地图片缩略图的方法: 原文地址:Android 超高仿微信图片选择器 图片该这么加载 其示例代码下载: 仿微信图片选择器 ImageLoader

  6. Android 高级UI设计笔记06:仿微信图片选择器(转载)

    仿微信图片选择器: 一.项目整体分析: 1. Android加载图片的3个目标: (1)尽可能的去避免内存溢出. a. 根据图片的显示大小去压缩图片 b. 使用缓存对我们图片进行管理(LruCache ...

  7. Android 超高仿微信图片选择器 图片该这么加载

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39943731,本文出自:[张鸿洋的博客] 1.概述 关于手机图片加载器,在当今像 ...

  8. Android 超高仿微信图片选择器 图片该这么载入

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39943731,本文出自:[张鸿洋的博客] 1.概述 关于手机图片载入器,在当今像 ...

  9. Android开发之高仿微信图片选择器

    记得刚开始做Andriod项目那会,经常会碰到一些上传图片的功能需求,特别是社交类的app,比如用户头像,说说配图,商品配图等功能都需要让我们到系统相册去选取图片,但官方却没有提供可以选取多张图片的相 ...

随机推荐

  1. CentOS 6.5 IP 设置

    DEVICE=eth0TYPE=EthernetUUID=7d6d54e0-054d-472b-8cc1-080f16ef36c1ONBOOT=yesNM_CONTROLLED=yesBOOTPROT ...

  2. JS自执行函数的几种写法

    一:整体写在一个括号中 代码如下: (function Show(){alert("hello");}()) 二:function函数整体外加括号 代码如下: (function ...

  3. dedecms设置文章分页后,标题会带有序号的解决方法

    至于删除分页后标题后面的序号,找到include/arc.archives.class.php 打开,找到 if($i>1) $this->Fields['title'] = $this- ...

  4. wordpress 更改 "Home"为"首页"

    要怎麼更改wordpress的 menu上 那一直顯示著"首頁"的頁籤呢這問題我實在是找好久終於給我找到 在 wp-includes 的 post-template.php 這檔案 ...

  5. javascript 设为首页 | 加入收藏夹 JS代码

    我们介绍一个可兼容所有浏览器的加入收藏代码代码,大概原理是这样的我们根据获取用户navigator.userAgent.toLowerCase()信息来判断浏览器,根据浏览器是否支持加入收藏js命令, ...

  6. 分享29个超赞的响应式Web设计

    原文自:http://www.csdn.net/article/2013-01-16/2813678-responsive-design-websites 最近几年,响应式Web设计不断印入人们眼帘, ...

  7. jQuery简单的轮播特效

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. 关于pcre正则表达式库libpcre

    gcc 4.8中已经包含了std regex的头文件 可是没有实现,所以链接是失败的 gcc 4.9完整的支持了c++ 11的regex. 在4.9以前,可以寻求boost的regex. 不过,我更熟 ...

  9. install ubuntu

    http://wenku.baidu.com/link?url=Cq6nB1ArObV1liMUT13ZB9o16NQ0-FpELt37R6NuPvz7zoKlz14Mu_k-8CwqQodWpRC8 ...

  10. WAMP集成环境

    WAMP Windows下的Apache+Mysql/MariaDB+Perl/PHP/Python,一组常用来搭建动态网站或者服务器的开源软件,本身都是各自独立的程序,但是因为常被放在一起使用,拥有 ...