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

字体颜色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. laravel5通过auth.attempt事件加入登陆验证码

    <?php namespace WangDong\Http\Controllers\Auth; use Illuminate\Http\Exception\HttpResponseExcepti ...

  2. request.getContextPath获取绝对路径

    request.getContextPath获取绝对路径 博客分类: 经验+注意 其他 request.getContextPath 项目需求:所有jsp页必须通过Action转发,不能直接在地址栏链 ...

  3. Transpose File

    Given a text file file.txt, transpose its content. You may assume that each row has the same number ...

  4. shell调用shell

    在默认条件下,执行shell文件会出现permission denied报错,一般是没有可执行权限.用chmod修改权限 chomd 777 score.sh   //把所有权限给aa文件 777代表 ...

  5. 简单实现tab标签页切换

    常见面试题: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  6. 页面点击关闭弹出提示js代码

    代码效果为: <script> window.onbeforeunload = function() { return "您好!\n我是abc\n —————————————— ...

  7. js切换换class

    1, js代码 function ntabs(thisObj,Num)            {if(thisObj.className == "active")return;   ...

  8. 矩形嵌套问题-ACM集训

    参考 http://blog.csdn.net/xujinsmile/article/details/7861412 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形 ...

  9. Java中权限修饰符public、private、protected和default的区别

    1.public 可以修饰类.成员变量和成员函数,没有任何限制,同一个包中,或者不同包中的类都可以自由访问 2.private 可以修饰成员变量和成员函数,只能在本类中使用 3.default (不写 ...

  10. orcad中的PSpice仿真加入厂商模型

      <1>首先要知道原理图的符号是没有模型的,不是你肆意妄为就可以拉来仿真的. <2>其次要知道很多器件软件中是没有模型的. <3>有很多获取模型的方法:<使 ...