要点:
1.使用picasso框架,只需导入jar包
Picasso.with(mContext).load(R.drawable.picture_unselected).into((ImageView)mHolder.ibt);
2.在子线程里扫描系统图片
3.获得文件修改时间:file.lastModified()//long类型
4.Set无序且不重复!获取set的值
mDirPaths = new HashSet<String>();
Iterator<String> i = mDirPaths.iterator();
while(i.hasNext()) {
i.next();// 值
}
5.list1 = list2 (难点)
问题描述:
// adapter = new ImageAdapter(this,paths);
// mGridView.setAdapter(adapter);
// paths和selectPaths都是list
paths.clear(); //1.
paths = selectPaths; //2.
for (String p : paths) { //3.
Log.v("TAG", p);
}
adapter.notifyDataSetChanged(); // 4.
// 步骤3.根据打印结果,可以打印出值
// 步骤4.但是adapet通知的时候,显示出来的数据为空(即paths不存在值)
// 显然有点矛盾
// 我的理解是,adapter适配的是适配堆内存,path一开始指向的就是这个堆
// 内存。然后步骤1.paths.clear()将堆内存清空,之后步骤2.让paths
// 指向别的堆内存。在步骤4.适配器通知的时候,依然是指向之前的堆内存
// (被清空),所以造成了看起来paths没有数据,然而循环打印paths却能
// 打印出值,这一矛盾的现象。
// 这里的解决方案是
// 2.测试代码~(正确事例)
// paths.clear();
// for (String p : selectPaths) {
// paths.add(p);
// }
// adapter.notifyDataSetChanged();
6.Viewholder的声明,设置点击监听的时候,如果Viewholder声明为全局变量,那么mHolder.ibt设置背景的时候会设置到别的item上去了。
这里在每次getView()时声明一个Viewholder可以解决。
7.接着6的案例,选中一个item时,滑动屏幕时,别的item也会被选中,这里的解决方案是getView()的时候图片全部设置为没被选中(初始状态),然后再点击监听里设置,如果选择则将图片路径作为tag存储在list里面,然后根据当前item的路径是否在list里面,有的话则设置图片为选择状态。
说明:
1.读取读取所有的本地图片
2.使用picasso加载图片
3.图片按修改时间排序(新修改的图片会在前面)
效果
代码
activity
package com.example.testpacasso;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.GridView;
public class MainActivity extends Activity {
private GridView mGridView;
private ImageAdapter adapter;
// 图片路径, 有序
private List<String> paths;
// 扫描到的图片路径, 无序且不重复
private Set<String> mDirPaths ;
private Handler mHandler;
private Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
adapter.notifyDataSetChanged();
}
};
initViews();
initDatas();
initEvent();
}
private void initEvent() {
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 获取选择图片的路径
List<String> selectPaths = adapter.getSelectPaths();
// 拿到图片路径之后根据自己的需求做处理
// 。。。。。
// 1.测试代码(显示空白,看起来paths没有值)
// 并且在adapter.notifyDataSetChanged();往下的代码都不会执行!但又没有异常抛出.
// paths.clear();
// paths = selectPaths;
// for (String p : paths) {
// Log.v("TAG", p);
// }
// adapter.notifyDataSetChanged();
// 2.测试代码~(正确事例)
// paths.clear();
// for (String p : selectPaths) {
// paths.add(p);
// }
// for (String p : paths) {
// Log.v("TAG", p);
// }
// adapter.notifyDataSetChanged();
}
});
}
private void initViews() {
mGridView = (GridView) findViewById(R.id.gv);
mButton = (Button) findViewById(R.id.bt);
}
private void initDatas() {
// 获得图片的路径
paths = new ArrayList<String>();
adapter = new ImageAdapter(this,paths);
mGridView.setAdapter(adapter);
// 扫描图片
getImagePath();
}
private void getImagePath() {
// 开启线程查找图片
new Thread(new Runnable() {
@Override
public void run() {
// 1.所有图片的Uri
Uri mImgUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
// 2.
ContentResolver cr = MainActivity.this.getContentResolver();
// 3.
Cursor cursor = cr.query(mImgUri, null,
MediaStore.Images.Media.MIME_TYPE + "= ? or "
+ MediaStore.Images.Media.MIME_TYPE + "= ?",
new String[] { "image/jpeg", "image/png" },
MediaStore.Images.Media.DATE_MODIFIED);
// 4.
mDirPaths = new HashSet<String>();
while(cursor.moveToNext()) {
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
mDirPaths.add(path);
}
// 遍历set
Iterator<String> i = mDirPaths.iterator();
// 存储模型数据
List<ImageModel> mList = new ArrayList<ImageModel>();
ImageModel imageModel = null;
File file = null;
String path ;
while (i.hasNext()) {
imageModel = new ImageModel();
path = i.next();
imageModel.setPath(path);
file = new File(path);
imageModel.setMotifyTime(file.lastModified());
mList.add(imageModel);
}
// 按修改时间排序
// 创建时间数组
int length = mList.size();
long [] motify = new long[length];
for (int j = 0;j < length; j++) {
motify[j] = mList.get(j).getMotifyTime();
}
// 快排排序
quickSort(motify,0,length-1);
// 根据排序,重新排序path(升序排列)
paths.clear();
for (int k = 0; k < length; k++) {
for (int p = 0; p < mList.size(); p++) {
if (mList.get(p).getMotifyTime() == motify[k]) {
paths.add(mList.get(p).getPath()); //移除,避免修改时间相同的实体
mList.remove(p);
break;
}
}
}
// paths倒序排序
Collections.reverse(paths);
// handle
mHandler.sendEmptyMessage(0);
}
}).start();
}
// 快排1
private static void quickSort(long[] array,int beg,int end){
if(beg >= end || array == null)
return;
int p = partition(array, beg, end);
quickSort(array, beg, p-1);
quickSort(array, p+1, end);
}
// 快排2
private static int partition(long[] array,int beg,int end){
long last = array[end];
int i = beg -1;
for (int j = beg; j <= end-1; j++) {
if(array[j] <= last){
i++;
if(i != j){
array[i] = array[i]^array[j];
array[j] = array[i]^array[j];
array[i] = array[i]^array[j];
}
}
}
if((i+1) != end){
array[i+1] = array[i+1]^array[end];
array[end] = array[i+1]^array[end];
array[i+1] = array[i+1]^array[end];
}
return i+1;
}
}
adapter
package com.example.testpacasso;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.squareup.picasso.Picasso;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class ImageAdapter extends BaseAdapter{
private Context mContext;
private List<String> paths;
private View view;
// private ViewHolder mHolder; // 如果设置为全局变量,在点击监听部分会有与预期不符合的效果!
// 选中图片列表
private List<String> selectPaths;
public ImageAdapter(Context mContext, List<String> paths) {
this.mContext = mContext;
this.paths = paths;
selectPaths = new ArrayList<String>();
}
@Override
public int getCount() {
return paths.size();
}
@Override
public Object getItem(int position) {
return paths.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final int pos = position;
final ViewHolder mHolder;
if (convertView == null) {
view = LayoutInflater.from(mContext).inflate(R.layout.item, null); // 设置parent崩溃
mHolder = new ViewHolder();
mHolder.img = (ImageView) view.findViewById(R.id.iv);
mHolder.ibt = (ImageButton) view.findViewById(R.id.ib);
view.setTag(mHolder);
} else {
view = convertView;
mHolder = (ViewHolder) view.getTag();
}
// 加载图片
Picasso.with(mContext).load(new File(paths.get(position))).placeholder(R.drawable.ic_launcher).resize(500, 500)
.centerCrop().into(mHolder.img);
// 重置状态
Picasso.with(mContext).load(R.drawable.picture_unselected).into((ImageView)mHolder.ibt);
// 如果被选择,则改为选中状态
if (selectPaths.contains(paths.get(pos))) {
Picasso.with(mContext).load(R.drawable.pictures_selected).into((ImageView) mHolder.ibt);
}
// 点击图片打钩图片
mHolder.ibt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!selectPaths.contains(paths.get(pos))) {
Picasso.with(mContext).load(R.drawable.pictures_selected).placeholder(R.drawable.picture_unselected).into((ImageView)mHolder.ibt);
selectPaths.add(paths.get(pos));
} else {
Picasso.with(mContext).load(R.drawable.picture_unselected).into((ImageView)mHolder.ibt);
selectPaths.remove(paths.get(pos));
}
}
});
return view;
}
class ViewHolder {
ImageView img;
ImageButton ibt;
}
// 得到选中的图片
public List<String> getSelectPaths() {
return selectPaths;
}
}
main_xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:id="@+id/ll"
android:background="#2294D4">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="8"
android:text="图片选择器"
android:gravity="center|left"
android:paddingLeft="10dp"
android:textColor="#fff"
android:textSize="20dp"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:textColor="#fff"
android:text="确定"
android:id="@+id/bt"/>
</LinearLayout>
<GridView
android:layout_below="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"
android:id="@+id/gv"/>
</RelativeLayout>
item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_margin="1dp"
android:scaleType="centerCrop"
/>
<ImageButton
android:id="@+id/ib"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="3dp"
android:layout_marginTop="3dp"
android:background="@null"
android:src="@drawable/picture_unselected" />
</RelativeLayout>
ImageModel
package com.example.testpacasso;
public class ImageModel{
// 路径
private String path;
// 修改时间
private long motifyTime;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public long getMotifyTime() {
return motifyTime;
}
public void setMotifyTime(long motifyTime) {
this.motifyTime = motifyTime;
}
}
权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
2016/06/01 更新
修改adapter类,添加点击事件,点击图片跳转至图片放大页面,可以左右滑动
ImageAdapter
package com.example.testpacasso;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.squareup.picasso.Picasso;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
public class ImageAdapter extends BaseAdapter{
private Context mContext;
private List<String> paths;
private View view;
// private ViewHolder mHolder; // 如果设置为全局变量,在点击监听部分会有与预期不符合的效果!
// 选中图片列表
private List<String> selectPaths;
public ImageAdapter(Context mContext, List<String> paths) {
this.mContext = mContext;
this.paths = paths;
selectPaths = new ArrayList<String>();
}
@Override
public int getCount() {
return paths.size();
}
@Override
public Object getItem(int position) {
return paths.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final int pos = position;
final ViewHolder mHolder;
if (convertView == null) {
view = LayoutInflater.from(mContext).inflate(R.layout.item, null); // 设置parent崩溃
mHolder = new ViewHolder();
mHolder.img = (ImageView) view.findViewById(R.id.iv);
mHolder.ibt = (ImageButton) view.findViewById(R.id.ib);
view.setTag(mHolder);
} else {
view = convertView;
mHolder = (ViewHolder) view.getTag();
}
// 加载图片
Picasso.with(mContext).load(new File(paths.get(position))).placeholder(R.drawable.ic_launcher).resize(500, 500)
.centerCrop().into(mHolder.img);
// 重置状态
Picasso.with(mContext).load(R.drawable.picture_unselected).into((ImageView)mHolder.ibt);
// 如果被选择,则改为选中状态
if (selectPaths.contains(paths.get(pos))) {
Picasso.with(mContext).load(R.drawable.pictures_selected).into((ImageView) mHolder.ibt);
}
// 点击图片打钩图片
mHolder.ibt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!selectPaths.contains(paths.get(pos))) {
Picasso.with(mContext).load(R.drawable.pictures_selected).placeholder(R.drawable.picture_unselected).into((ImageView)mHolder.ibt);
selectPaths.add(paths.get(pos));
} else {
Picasso.with(mContext).load(R.drawable.picture_unselected).into((ImageView)mHolder.ibt);
selectPaths.remove(paths.get(pos));
}
}
});
// 點擊放大
mHolder.img.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(mContext, ImageActivity.class);
Bundle bundle = new Bundle();
ArrayList<String> arrayList = (ArrayList<String>) paths;
bundle.putStringArrayList(ImageActivity.EXTRA_URLS, arrayList);
bundle.putInt(ImageActivity.EXTRA_POSITION,pos);
intent.putExtra(ImageActivity.EXTRA_BUNDLE, bundle);
mContext.startActivity(intent);
}
});
return view;
}
class ViewHolder {
ImageView img;
ImageButton ibt;
}
// 得到选中的图片
public List<String> getSelectPaths() {
return selectPaths;
}
}
ImageActivity
package com.example.testpacasso;
import java.io.File;
import java.util.ArrayList;
import com.squareup.picasso.Picasso;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
/**
*
* @author yj<br>
* 要使用这个类,必须传入一个包含图片路径的集合和要显示图片的位置position<br>
* 该类可以左右滑动显示图片<br>
*/
public class ImageActivity extends Activity {
private ViewPager mViewPager;
/**
* 当前图片的位置,作为显示的入口
*/
private int position;
private PagerAdapter mAdapter;
/**
* 存放要显示图片的路径集合
*/
private ArrayList<String> paths;
/**
* 存放ViewPager Item的下标,用户removeView时的判断依据
*/
private ArrayList<Integer> arrayList;
/**
* ViewPager是否在向左滑动
*/
private boolean isLeft;
/**
* 临时存放的变量,用于判断ViewPager是向左滑动还是向右滑动
*/
private int temp;
/**
* 屏幕的长
*/
private int screenWidth;
/**
* 屏幕的寬
*/
private int screenHeight;
public static String EXTRA_BUNDLE ="bundle";
public static String EXTRA_URLS ="urls";
public static String EXTRA_POSITION ="position";
@SuppressWarnings("unchecked")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image);
init();
initEvent();
}
private void init() {
screenWidth = getWindowManager().getDefaultDisplay().getWidth();
screenHeight = getWindowManager().getDefaultDisplay().getHeight();
arrayList = new ArrayList<Integer>();
// 获取数据,包括图片路径集合和当前图片路径所在的下标
Bundle bundle = getIntent().getBundleExtra(EXTRA_BUNDLE);
if (bundle != null) {
paths = (ArrayList<String>) bundle.get(EXTRA_URLS);
position = bundle.getInt(EXTRA_POSITION);
}
mViewPager = (ViewPager) findViewById(R.id.id_viewpager);
mAdapter = new PagerAdapter() {
@Override
public void destroyItem(ViewGroup container, int position,
Object object) {
if (isLeft) {
// 左滑
container.removeViewAt(findSmallIndex());
arrayList.remove(findSmallIndex());
} else {
// 右滑
container.removeViewAt(findBigIndex());
arrayList.remove(findBigIndex());
}
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = LayoutInflater.from(ImageActivity.this).inflate(R.layout.image, null);
ImageView imageView = (ImageView) view.findViewById(R.id.iv_image);
String url = paths.get(position);
// 1.使用picasso 效果很好
Picasso.with(ImageActivity.this).load(new File(url)).centerInside().resize(screenWidth, screenHeight).into(imageView);
// // 2.使用异步加载, 效果一般, 不够picasso好
// MyTask myTask = new MyTask(imageView);
// myTask.execute(url, calculateInSampleSize(url)+"");
container.addView(view);
arrayList.add(position);
return view;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public int getCount() {
return paths.size();
}
};
mViewPager.setAdapter(mAdapter);
// 显示当前的图片
// 此刻ViewPager只会加载position前后的内容,即只有3个View
mViewPager.setCurrentItem(position);
}
private void initEvent() {
// 判断是手指像左滑动还是像右滑动
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// 经过测试发现
// arg2在向左滑动时,arg2会不断增大,最后变为0,
// arg2在向右滑动时,arg2会不断减小,最后变为0,
if (arg2 != 0) {
temp = arg2;
} else {
if (temp > 300) {
isLeft = true;
} else {
isLeft = false;
}
}
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
/**
* 找到列表最小item所在的小标
* @return
*/
protected int findSmallIndex() {
int index = 0;
for (int i = 1; i < arrayList.size(); i++) {
if (arrayList.get(index) > arrayList.get(i)) {
index = i;
}
}
return index;
}
/**
* 找到列表里最大item所在的下标
* @return
*/
protected int findBigIndex() {
int index = 0;
for (int i = 1; i < arrayList.size(); i++) {
if (arrayList.get(index) < arrayList.get(i)) {
index = i;
}
}
return index;
}
/**
* 没有使用到, 作为记录
*/
// /**
// * 计算合适的inSampleSize
// *
// * @param url
// * @param width
// * @param height
// * @return
// */
// private int calculateInSampleSize(String url) {
// Options options = new Options();
// options.inJustDecodeBounds = true;
// int inSampleSize = 1;
// BitmapFactory.decodeFile(url, options);
// int bitmapWidth = options.outWidth;
// int bitmapheight = options.outHeight;
//
// while (bitmapWidth / inSampleSize > screenWidth
// && bitmapheight / inSampleSize > screenHeight) {
// inSampleSize = inSampleSize * 2;
// }
// return inSampleSize;
// }
/**
* 没有使用到, 作为记录
*/
// /**
// * 异步,防止卡顿
// * @author yj
// *
// */
// class MyTask extends AsyncTask<String, Void, Bitmap> {
// private ImageView view;
// public MyTask(ImageView view) {
// this.view = view;
// }
//
// @Override
// protected Bitmap doInBackground(String... params) {
// Options options = new Options();
// options.inSampleSize = Integer.parseInt(params[1]);
// Bitmap bitmap = BitmapFactory.decodeFile(params[0], options);
// return bitmap;
// }
//
// @Override
// protected void onPostExecute(Bitmap result) {
// super.onPostExecute(result);
// view.setImageBitmap(result);
// }
//
// }
}
activity_image.xml
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#000" >
<android.support.v4.view.ViewPager
android:id="@+id/id_viewpager"
android:layout_height="match_parent"
android:layout_width="match_parent">
</android.support.v4.view.ViewPager>
</RelativeLayout>
image
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android" >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/iv_image"
/>
</RelativeLayout>