本地图片选择器(picasso框架)
来源:互联网 发布:原生js返回顶部火箭 编辑:程序博客网 时间:2024/05/20 20:02
要点:
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"/>
参考:http://blog.csdn.net/u010542146/article/details/50766471
还有网上的一些例子。
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>
0 0
- 本地图片选择器(picasso框架)
- picasso 显示本地图片
- Android图片加载框架Picasso(一)
- picasso图片缓存框架
- 图片加载框架-Picasso
- 图片加载框架Picasso
- Picasso 图片加载框架
- 图片加载框架-Picasso
- 图片加载框架Picasso解析
- Picasso 图片框架的学习
- 图片加载框架之Picasso
- Android图片加载框架Picasso
- 图片加载框架Picasso解析
- 图片加载框架之Picasso
- Android加载图片框架Picasso
- 图片处理框架之picasso
- picasso图片框架源码解析
- Android图片加载框架Picasso(Square公司)
- mysql触发器+mysql_udf_http
- 《JAVA继承与多态》利用继承实现MyStack,MyStack是用组合实现的。扩展ArrayLis
- Cocos2d-x跨平台手机游戏开发学习路线图
- ANR和FC
- 限制安全角色访问特定字段
- 本地图片选择器(picasso框架)
- The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
- java反射——运用反射生成jdk动态代理
- java GUI 图形界面编程
- SVM开发详解
- 第10、11周项目2 - 存储班长信息的学生类(2)
- URL编码与解码
- 动态库技术之二-静态库函数
- Spark算子reduceByKey深度解析