本地图片选择器(picasso框架)
2016-05-17 14:12
471 查看
要点:
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.图片按修改时间排序(新修改的图片会在前面)
效果
代码
activitypackage 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"/>
参考:/article/10877492.html
还有网上的一些例子。
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>
相关文章推荐
- Ubuntu 14.04下caffe的安装
- JavaScript数组方法
- Centos出现-bash: unzip: command not found的解决办法
- Android程序中如何启动浏览器
- 1D Measuring(基础篇)
- 企业信息管理系统到底包括哪些工作呢?
- (数据看成字符串)大端——高尾端,小端——低尾端链接
- android面试精华题目总结
- Swift 几个简单控件及上传系统相册照片
- CPU的寻址方式(Linux内核情景分析)
- 本地jar 导入maven
- exports 和 module.exports 的区别
- JavaScript DOM 中的内置对象
- JavaScript DOM 中的内置对象
- JavaScript DOM 中的内置对象
- JavaScript DOM 中的内置对象
- JavaScript DOM 中的内置对象
- JavaScript DOM 中的内置对象
- JavaScript DOM 中的内置对象
- JavaScript DOM 中的内置对象