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

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

 <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>

text_selector.xml

图片选择按钮

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

item_selector

遍历之后将所有图片显示

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@android:color/background_dark"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:layout_margin="10dp"
android:src="@mipmap/camera"/>
<CheckBox
android:id="@+id/cb_btn"
android:layout_margin="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:button="@drawable/item_selector"/> </RelativeLayout>

item_image.xml

 <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.lesson10_picselectordemo.MainActivity"> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_dark"
android:padding="10dp"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="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:enabled="false"
android:text="完成"
android:textColor="@color/text_selector" /> </RelativeLayout> <GridView
android:id="@+id/gv_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="4"/>
</LinearLayout>

activity_main.xml

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

 /**
* 适配数据类型不确定,可以使用泛型
* 也可以是使用extends限定泛型,比如接口IGetName有个getName()方法,只要T继承IGetName实现方法,就可以使用该方法
* Created by Administrator on 2016/10/24 0024.
*/ public abstract class ListItemAdapter<T> extends BaseAdapter { //适配器需要上下文,数据
//使用ptotected修饰符,使子类也可以用
protected Context mContext;
protected List<T> mList; public ListItemAdapter(Context mContext,List<T> mList){
this.mContext = mContext;
this.mList = mList;
} @Override
public int getCount() {
return mList.size();
} @Override
public T getItem(int position) {
return mList.get(position);
} @Override
public long getItemId(int position) {
return position;
}
}

ListItemAdapter.java

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

 public class ImageAdapter extends ListItemAdapter<File> {

     private boolean select = false;

     public void open(int position){
select = true;
booleanArray.put(position,true);
if(onImageCheckedListener != null){
onImageCheckedListener.onImageChecked(true);
}
this.notifyDataSetChanged();
} public void close(){
select = false;
booleanArray.clear();
this.notifyDataSetChanged();
} public ImageAdapter(Context mContext, List<File> mList) {
super(mContext, mList);
} @Override
public int getCount() {
//多出来的第一张为照相机,点击进入照相机
return super.getCount()+1;
} /**
* 这里布局重用,使用checkbox会导致很多问题,
* 勾选了一个,下拉之后发现下面也被勾选了一个
* 这时,我们可以使用HashMap<Integer,Boolean>,是否被勾选
*
* 这里推荐使用另外一个类SparseBooleanArray
*
* @param position
* @param convertView
* @param parent
* @return
*/
SparseBooleanArray booleanArray = new SparseBooleanArray(); public SparseBooleanArray getBooleanArray() {
return booleanArray;
} @Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null){
convertView = View.inflate(mContext,R.layout.item_image,null);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} viewHolder = (ViewHolder) convertView.getTag(); if(position == 0){
//照相机
viewHolder.iv_img.setImageResource(R.mipmap.camera);
viewHolder.cb_btn.setVisibility(View.GONE);
}else{ //设置图片
viewHolder.iv_img.setImageURI(Uri.fromFile(mList.get(position - 1))); if(select) {
viewHolder.cb_btn.setVisibility(View.VISIBLE);
//是否需要勾选呢?
Boolean b = booleanArray.get(position);
if (b == null || b == false) {
viewHolder.cb_btn.setChecked(false);
} else {
viewHolder.cb_btn.setChecked(true);
} //checkbox不能设置onCheckChange监听,因为上面setChecked导致下面isCheck也会跟着变化
/*viewHolder.cb_btn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
booleanArray.put(position,isChecked);
}
});*/
viewHolder.cb_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//position有可能不存在,为空,这里必须给Boolean
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++) {
//i一定存在,所以可以给boolean
boolean isChecked = booleanArray.get(booleanArray.keyAt(i));
if(isChecked){
//说明有被勾选的值
if(onImageCheckedListener != null){
onImageCheckedListener.onImageChecked(true);
}
return;
}
}
//没有被勾选的值,
if(onImageCheckedListener != null)
onImageCheckedListener.onImageChecked(false);
//关闭
close();
}
});
}else {
viewHolder.cb_btn.setVisibility(View.GONE);
}
}
return convertView;
} //回调方法
//写在需要执行方法的地方
//实现,在需要返回的地方
public interface OnImageCheckedListener{
void onImageChecked(boolean b);
} private OnImageCheckedListener onImageCheckedListener; //alt + insert
public void setOnImageCheckedListener(OnImageCheckedListener onImageCheckedListener) {
this.onImageCheckedListener = onImageCheckedListener;
} class ViewHolder{
ImageView iv_img;
CheckBox cb_btn; public ViewHolder(View convertView){ iv_img = (ImageView) convertView.findViewById(R.id.iv_img);
int width = mContext.getResources().getDisplayMetrics().widthPixels / 4 -2;
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width,width);
iv_img.setLayoutParams(params);
cb_btn = (CheckBox) convertView.findViewById(R.id.cb_btn);
}
}
}

ImageAdapter.java

点击查看大图

 public class ShowBigImage extends AppCompatActivity{

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

ShowBigImage.java

 public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener, ImageAdapter.OnImageCheckedListener, View.OnClickListener {
private static final int CAMERA_CODE = 1;
//SD卡所有图片
List<File> filesList = new ArrayList<>(); ProgressDialog dialog; GridView gv_image;
TextView tv_finish;
ImageAdapter adapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //加载数据
loadData();
//初始化视图
initView(); } private void initView() {
gv_image = (GridView) findViewById(R.id.gv_image);
tv_finish = (TextView) findViewById(R.id.tv_finish);
adapter = new ImageAdapter(this,filesList);
tv_finish.setOnClickListener(this);
adapter.setOnImageCheckedListener(this);
gv_image.setAdapter(adapter);
//点击图片查看大图
gv_image.setOnItemClickListener(this);
//长按选择图片
gv_image.setOnItemLongClickListener(this);
} public ProgressDialog showDialog(){
//显示Dialog
dialog = new ProgressDialog(this);
dialog.setTitle("加载数据");
dialog.setMessage("正在加载数据,请稍等...");
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.show(); return dialog;
} public void loadData(){
dialog = showDialog(); //数据加载不能阻塞UI
//在子线程中加载
new Thread(){
@Override
public void run() {
super.run();
//开始递归遍历SD卡根目录
/*public static File getExternalStorageDirectory() {
throwIfUserRequired();
return sCurrentUser.getExternalDirs()[0];//获取第0张SD卡如果想要其他SD卡,只要重写这个方法即可
}*/
File SDDir = Environment.getExternalStorageDirectory();
getFiles(SDDir); //数据加载完毕,要关闭Dialog
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.dismiss();
//刷新适配器
adapter.notifyDataSetChanged();
}
});
}
}.start();
} public void getFiles(File dir){
File[] files = dir.listFiles(); if(files == null){
return;
} //开始遍历
for (File file : files) {
if(file.isDirectory()){
getFiles(file);
}else{
if(file.getName().endsWith("jpg") || file.getName().endsWith("png")){
filesList.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 = filesList.get(position - 1);
//带数据点开大图
Intent intent = new Intent(this,ShowBigImage.class);
intent.putExtra("img",file);
startActivity(intent);
} } @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == requestCode && resultCode == RESULT_OK){
//照相机的图片永远放在第一个
filesList.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 onImageChecked(boolean b) {
//b代表适配器中有没有被勾选的值
tv_finish.setEnabled(b);
} @Override
public void onClick(View v) {
//选择的图片
//不能使用泛型,ArrayList才实现了序列化,List没有实现
ArrayList<File> resultList = new ArrayList<>();
//点击完成,带参返回
//需要知道哪些数据被选中
//通过是是适配器中的boolArray的为true的选中项来加载file
SparseBooleanArray booleanArray = adapter.getBooleanArray();
for (int i = 0; i <booleanArray.size() ; i++) {
boolean isSelected = booleanArray.get(booleanArray.keyAt(i));
if(isSelected){
int position = booleanArray.keyAt(i);
//剔除掉第一张照相机图片
resultList.add(filesList.get(position-1));
}
}
Intent intent = new Intent();
intent.putExtra("list",resultList);
//返回数据
setResult(RESULT_OK,intent);
finish();
}
}

MainActivity.java

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

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

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.lesson10_picselectordemo"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="SelectPicture"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ShowBigImage"/>
</application> </manifest>

AndroidManifest.xml

测试类

点击Buttong,打开图片选择器

 <RelativeLayout 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"
tools:context="com.example.lesson10_picselectordemotest.MainActivity"> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="toPicSelectorDemo"
android:layout_centerInParent="true"
android:text="图片选择器启动另一个Module" />
</RelativeLayout>

activity_main.xml

 public class MainActivity extends AppCompatActivity {

     @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} public void toPicSelectorDemo(View v){ startActivityForResult(new Intent("SelectPicture"),1);
} @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
ArrayList<File> file = (ArrayList<File>) data.getSerializableExtra("list");
Toast.makeText(this,file.toString(),Toast.LENGTH_SHORT).show();
}
}
}

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. SGU 115.Calendar

    连水3道,还能更水么... #include <stdio.h> using namespace std; ] = {, , , , , , , , , , , , }; int n, m ...

  2. modifytime是一个神奇的column name----这边文章是错的totally,因为我的实验不彻底。timestamp属性很神奇,头一个timestamp,会自动的成DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

    在mysql里边modifytime是一个神奇的column name,试一下. 请执行sql语句 CREATE TABLE `test_time` ( `modifytime` timestamp ...

  3. saiku

    1.saiku下载http://community.meteorite.bi/可以下载各个版本的源代码 2.下载到   saiku-latest.zip 3.解压运行比较简单     解压出来的目录: ...

  4. vertical-align:top属性

    vertical-align这个是设置元素的垂直排列的. 用来定义行内元素的基线相对于该元素所在行的基线的垂直对齐. 它的值比较多:baseline | sub | super | top | tex ...

  5. Code::Blocks 的配色方案

    codeblocks的配置文件是default.conf, 在Windows系统下,该文件在C:\Documents and Settings\Administrator\Application Da ...

  6. 【C语言】严格区分大小写

    C语言严格区分大小写 一.相关基础知识 二.具体内容 C语言严格区分大小写: 如: int为关键字,INT则为用户标识符,即可定义int INT;   int INt;   int Int;  cha ...

  7. CSS HACK的方法

    所有浏览器 通用 height: 100px; IE6 专用 _height: 100px; IE7 专用 *+height: 100px; IE6.IE7 共用 *height: 100px; IE ...

  8. wlan的QOS配置

    WLAN QoS配置 1.1  WLAN QoS简介 802.11网络提供了基于竞争的无线接入服务,但是不同的应用需求对于网络的要求是不同的,而原始的网络不能为不同的应用提供不同质量的接入服务,所以已 ...

  9. BZOJ 1027 合金

    Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的 ...

  10. codeforces C. k-Tree

    思路:dp[i][j]表示和为i,最大值为j的方案数. #include <cstdio> #include <cstring> #include <algorithm& ...