仿微信图片选择器
Posted 小小葡萄干
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了仿微信图片选择器相关的知识,希望对你有一定的参考价值。
仿微信图片选择器
打开app后点击添加图片按钮:
获取选择的图片 并返回在gridview中:
实现该功能的重要组成部分有:利用gridview加载本地图片,gridView控件的使用,Intent之间数据的传递,和利用ContentProvider获取图片,和PopupWindow弹出页面的使用,利用Bitmap解决OOM问题。
下面开始贴出代码:
MainActivity文件的代码如下:
`import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import android.widget.SimpleAdapter.ViewBinder;
import android.widget.Toast;
public class MainActivity extends Activity {
private ImageButton imageButton_poprecommend_back;
private Button button_poprecommend_fabu;
private EditText editText_poprecommend;
private ImageButton imageButton_poprecommend_tianjia;
private GridView gridView_poprecommend;
private PopRecommend_ImageAdd_Adapter imageAdapter;
private ArrayList<String> shuju = new ArrayList<String>();
public static MainActivity activity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
activity = this;
FindId();
Dianji();
shuju = new ArrayList<String>();
Intent intent = this.getIntent();
shuju = intent.getStringArrayListExtra("shuju");
if (shuju != null) {
imageAdapter = new PopRecommend_ImageAdd_Adapter(this, shuju);
gridView_poprecommend.setAdapter(imageAdapter);
}
}
private void FindId() {
imageButton_poprecommend_back = (ImageButton) findViewById(R.id.imagview_poprecommend_back);
button_poprecommend_fabu = (Button) findViewById(R.id.button_poprecommend_fabu);
editText_poprecommend = (EditText) findViewById(R.id.edittext_poprecommend);
imageButton_poprecommend_tianjia = (ImageButton) findViewById(R.id.iamgebutton_poprecommend_tianjiatupian);
gridView_poprecommend = (GridView)this.findViewById(R.id.gridview_poprecommend);
}
private void Dianji() {
imageButton_poprecommend_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Activity_Image_Add.imageAdd!=null)
Activity_Image_Add.imageAdd.finish();
}
});
button_poprecommend_fabu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Activity_Image_Add.imageAdd!=null)
Activity_Image_Add.imageAdd.finish();
if (editText_poprecommend.getText().toString().equals("")) {
Toast.makeText(getApplication(), "发布内容不能为空", Toast.LENGTH_SHORT).show();
} else
Toast.makeText(getApplication(), "发布成功", Toast.LENGTH_SHORT).show();
}
});
imageButton_poprecommend_tianjia.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplication(), Activity_Image_Add.class);
startActivity(intent);
}
});
}
}
`
Activity_Image_Add activity的页面代码:
package com.xiyouliwp.fangweixin;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
/**
* 需求:IPet的图片选择器,
* Created by lwp940118 on 2016/5/29.
* 李文朋
*/
public class Activity_Image_Add extends Activity implements List_File_PopWind.OnImageDirSelected {
private ImageButton imageButton_ImageAdd_back;
private ImageButton imageButton_ImageAdd_finish;
private GridView gridView_ImageAdd;
int totalCount = 0;
/**
* 存储文件夹中的图片数量
*/
private int mPicSize = 0;
/**
* 图片数量最多的文件夹
*/
private File maxImageFile;
private RelativeLayout relativeLayout_popwind;
/**
* 所以图片
*/
private List<String> mImags;
/**
* list存放扫描到的文件夹的信息
*/
private List<ImageFolder> imageFolders = new ArrayList<ImageFolder>();
/**
* hashset 基于hashmap实现的,利用他可以防止一个文件夹 多次扫描
*/
private HashSet<String> mImagePath = new HashSet<String>();
//弹出对话框 进度条
private ProgressDialog mprogressDialog;
private TextView textview_ChooseDir;
private TextView textview_ImageCount;
//定义屏幕的高度
private int screenHeight = 0;
/**
* 用户选择的图片,存储为图片的完整路径
*/
public static List<String> mSelectedImage = new LinkedList<String>();
private ArrayList<String> shuju;
private MyAdapter myAdapter;
private List_File_PopWind popWind;
public static Activity_Image_Add imageAdd;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//加载的那个对话框 销毁
mprogressDialog.dismiss();
//view绑定数据
dateView();
//初始化Popwind
initPopWind();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_add);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
screenHeight = displayMetrics.heightPixels;
Log.e("screenHeight---->", "" + screenHeight);
imageAdd = this;
findId();
kongJianSheZhi();
getImages();
initEvent();
}
// 返回按键调用
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (MainActivity.activity!=null)
MainActivity.activity.finish();
shuju = new ArrayList<String>();
for (int i = 0; i < mSelectedImage.size(); i++)
shuju.add(mSelectedImage.get(i));
Intent intent = new Intent(getApplicationContext(),MainActivity.class);
intent.putStringArrayListExtra("shuju",shuju);
startActivity(intent);
}
return true;
}
/**
* 弹出popwind
*/
private void initEvent() {
relativeLayout_popwind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
popWind.setAnimationStyle(R.style.AnimBottom);
popWind.showAtLocation(Activity_Image_Add.this.findViewById(R.id.imagebutton_imageadd_back),
Gravity.BOTTOM, 0, 0);
// 设置背景颜色变暗
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 0.3f;
getWindow().setAttributes(lp);
}
});
}
/**
* 绑定view的数据
*/
private void dateView() {
if (maxImageFile == null) {
Toast.makeText(getApplicationContext(), "没有扫描到图片", Toast.LENGTH_SHORT).show();
return;
}
//aslist 连接列表与数组,当一个更新时 另一个也自动更新但是没有add 和remove方法
mImags = Arrays.asList(maxImageFile.list());
myAdapter = new MyAdapter(getApplicationContext(), mImags, R.layout.item_gridview_imageadd,
maxImageFile.getAbsolutePath());
gridView_ImageAdd.setAdapter(myAdapter);
//显示多少张图片 在popwind中
textview_ImageCount.setText(totalCount + "张");
}
/**
* 初始化popwind的弹出界面
*/
private void initPopWind() {
popWind = new List_File_PopWind(LinearLayout.LayoutParams.MATCH_PARENT, (int) (screenHeight
* 0.7), imageFolders, LayoutInflater.from(getApplicationContext())
.inflate(R.layout.list_dir, null));
popWind.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
// 设置背景颜色变暗
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 1.0f;
getWindow().setAttributes(lp);
}
});
//设置文件夹的回调
popWind.setOnImageDirSelected(this);
}
/**
* 利用contentProvider扫描手机中的图片,并获取jpn最多的那个文件夹
* ContentProvider 为Android四大组件,详情见我的博客
* Android四大组件介绍http://blog.csdn.net/qq_30000411/article/details/51355390
*/
private void getImages() {
//判断Sd卡的状态 是否可用
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
Toast.makeText(getApplicationContext(), "没有找到SD", Toast.LENGTH_SHORT).show();
}
//显示进度条 加载中...
mprogressDialog = ProgressDialog.show(this, null, "图片读取中...");
new Thread(new Runnable() {
@Override
public void run() {
//读取第一张图片
String firstImagePath = null;
//EXTERNAL_CONTENT_URI多选
Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
//ContentResolver应用之间数据共享
ContentResolver mResolver = Activity_Image_Add.this.getContentResolver();
//数据查找,找出JPEG和png格式的图片,,,MediaStore为Android手机系统的多媒体数据库
Cursor mCursor = mResolver.query(mImageUri, null, MediaStore.Images.Media.MIME_TYPE + "=? or "
+ MediaStore.Images.Media.MIME_TYPE + "=?",
new String[]{"image/jpeg", "image/png"}, MediaStore.Images.Media.DATE_MODIFIED);
//读取图片
while (mCursor.moveToNext()) {
//定义图片的路径
String imagePath = mCursor.getString(mCursor.getColumnIndex
(MediaStore.Images.Media.DATA));
//获取第一张图片的路径
if (firstImagePath == null)
firstImagePath = imagePath;
//获取该图片的父路径名
File parentFile = new File(imagePath).getParentFile();
if (parentFile == null)
continue;
String folderPath = parentFile.getAbsolutePath();
ImageFolder imageFolder = null;
//利用hashset防止一个文件夹被多次扫描
if (mImagePath.contains(folderPath)) {
continue;
} else {
mImagePath.add(folderPath);
//初始化 ImageFolder
imageFolder = new ImageFolder();
imageFolder.setFolderPath(folderPath);
imageFolder.setFirstImagePath(imagePath);
}
int picSize = parentFile.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
if (filename.endsWith(".png") || filename.endsWith(".jpg")
|| filename.endsWith(".jpeg"))
return true;
return false;
}
}).length;
totalCount += picSize;
imageFolder.setImageCount(picSize);
imageFolders.add(imageFolder);
//更新最大数量文件夹
if (picSize > mPicSize) {
mPicSize = picSize;
maxImageFile = parentFile;
}
}
mCursor.close();
//扫描完成 hashset释放
mImagePath = null;
//通知 线程Handler 图片扫秒完成
handler.sendEmptyMessage(0x110);
}
}).start();
}
private void findId() {
gridView_ImageAdd = (GridView) findViewById(R.id.gridview_imageadd);
imageButton_ImageAdd_back = (ImageButton) findViewById(R.id.imagebutton_imageadd_back);
imageButton_ImageAdd_finish = (ImageButton) findViewById(R.id.imagebutton_imageadd_finish);
textview_ChooseDir = (TextView) findViewById(R.id.id_choose_dir);
textview_ImageCount = (TextView) findViewById(R.id.id_total_count);
relativeLayout_popwind = (RelativeLayout) findViewById(R.id.id_bottom_ly);
}
private void kongJianSheZhi() {
imageButton_ImageAdd_finish.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("完成--->","完成");
if (MainActivity.activity!=null)
MainActivity.activity.finish();
shuju = new ArrayList<String>();
for (int i = 0; i < mSelectedImage.size(); i++)
shuju.add(mSelectedImage.get(i));
Intent intent = new Intent(getApplicationContext(),MainActivity.class);
intent.putStringArrayListExtra("shuju",shuju);
startActivity(intent);
}
});
imageButton_ImageAdd_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
public void selected(ImageFolder floder) {
maxImageFile = new File(floder.getFolderPath());
mImags = Arrays.asList(maxImageFile.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
if (filename.endsWith(".jpg") || filename.endsWith(".png")
|| filename.endsWith(".jpeg"))
return true;
return false;
}
}));
/**
* 可以看到文件夹的路径和图片的路径分开保存,极大的减少了内存的消耗;
*/
myAdapter = new MyAdapter(getApplicationContext(), mImags,
R.layout.item_gridview_imageadd, maxImageFile.getAbsolutePath());
gridView_ImageAdd.setAdapter(myAdapter);
// mAdapter.notifyDataSetChanged();
textview_ImageCount.setText(floder.getImageCount() + "张");
textview_ChooseDir.setText(floder.getFolderName());
popWind.dismiss();
}
/**
* gridview的定义适配器
*/
public class MyAdapter extends CommonAdapter<String> {
/**
* 文件夹路径
*/
private String mDirPath;
public MyAdapter(Context context, List<String> mDatas, int itemLayoutId,
String dirPath) {
super(context, mDatas, itemLayoutId);
this.mDirPath = dirPath;
}
@Override
public void convert(final ViewHolder helper, final String item) {
//设置no_pic
helper.setImageResource(R.id.id_item_image, R.drawable.pictures_no);
//设置no_selected
helper.setImageResource(R.id.id_item_select,
R.drawable.picture_unselected);
//设置图片
helper.setImageByUrl(R.id.id_item_image, mDirPath + "/" + item);
final ImageView mImageView = helper.getView(R.id.id_item_image);
final ImageView mSelect = helper.getView(R.id.id_item_select);
mImageView.setColorFilter(null);
//设置ImageView的点击事件
mImageView.setOnClickListener(new View.OnClickListener() {
//选择,则将图片变暗,反之则反之
@Override
public void onClick(View v) {
// 已经选择过该图片
if (mSelectedImage.contains(mDirPath + "/" + item)) {
mSelectedImage.remove(mDirPath + "/" + item);
mSelect.setImageResource(R.drawable.picture_unselected);
mImageView.setColorFilter(null);
} else {// 未选择该图片
mSelectedImage.add(mDirPath + "/" + item);
mSelect.setImageResource(R.drawable.pictures_selected);
mImageView.setColorFilter(Color.parseColor("#77000000"));
}
}
});
/**
* 已经选择过的图片,显示出选择过的效果
*/
if (mSelectedImage.contains(mDirPath + "/" + item)) {
mSelect.setImageResource(R.drawable.pictures_selected);
mImageView.setColorFilter(Color.parseColor("#77000000"));
}
}
}
}
BitmapUtilities问价:用于缩小图片的尺寸,避免OOM问题出现
package com.xiyouliwp.fangweixin;
/**
* Created by lwp940118 on 2016/5/31.
*/
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
public class BitmapUtilities {
public BitmapUtilities() {
// TODO Auto-generated constructor stub
}
public static Bitmap getBitmapThumbnail(String path,int width,int height){
Bitmap bitmap = null;
//这里可以按比例缩小图片:
/*BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 4;//宽和高都是原来的1/4
bitmap = BitmapFactory.decodeFile(path, opts); */
/*进一步的,
如何设置恰当的inSampleSize是解决该问题的关键之一。BitmapFactory.Options提供了另一个成员inJustDecodeBounds。
设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。
有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。*/
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, opts);
opts.inSampleSize = Math.max((int)(opts.outHeight / (float) height), (int)(opts.outWidth / (float) width));
opts.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(path, opts);
return bitmap;
}
public static Bitmap getBitmapThumbnail(Bitmap bmp,int width,int height){
Bitmap bitmap = null;
if(bmp != null ){
int bmpWidth = bmp.getWidth();
int bmpHeight = bmp.getHeight();
if(width != 0 && height !=0){
Matrix matrix = new Matrix();
float scaleWidth = ((float) width / bmpWidth);
float scaleHeight = ((float) height / bmpHeight);
matrix.postScale(scaleWidth, scaleHeight);
bitmap = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, true);
}else{
bitmap = bmp;
}
}
return bitmap;
}
}
CommonAdapter文件:超级适配器,也成通配器,可以使用gridview和listview共同使用:
package com.xiyouliwp.fangweixin;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
/**
* 通配器,CommonAdapter通过封装BaseAdapter和RecyclerView.Adapter得到通用的、简单易用的Adapter。
* 作为ListView和GridView的通用适配器。
* 超级适配器
* @param <T>
*/
public abstract class CommonAdapter<T> extends BaseAdapter {
protected LayoutInflater mInflater;
protected Context mContext;
protected List<T> mDatas;
protected final int mItemLayoutId;
public CommonAdapter(Context context, List<T> mDatas, int itemLayoutId) {
this.mContext = context;
this.mInflater = LayoutInflater.from(mContext);
this.mDatas = mDatas;
this.mItemLayoutId = itemLayoutId;
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public T getItem(int position) {
return mDatas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder = getViewHolder(position, convertView,
parent);
convert(viewHolder, getItem(position));
return viewHolder.getConvertView();
}
public abstract void convert(ViewHolder helper, T item);
private ViewHolder getViewHolder(int position, View convertView,
ViewGroup parent) {
return ViewHolder.get(mContext, convertView, parent, mItemLayoutId,
position);
}
}
DiskLruCache文件:点击获取到的图片的path路径进行解析
package com.xiyouliwp.fangweixin;
/**
* Created by lwp940118 on 2016/5/31.
*/
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
public class DiskLruCache {
private static final String CACHE_FILENAME_PREFIX = "cache_";
private static final int MAX_REMOVALS = 4;
private static final int INITIAL_CAPACITY = 32;
private static final float LOAD_FACTOR = 0.75f;
private final File mCacheDir;
private int cacheSize = 0;
private int cacheByteSize = 0;
private final int maxCacheItemSize = 64; // 64 item default
private long maxCacheByteSize = 1024 * 1024 * 5; // 5MB default
private CompressFormat mCompressFormat = CompressFormat.JPEG;
private int mCompressQuality = 70;
private final int IO_BUFFER_SIZE = 4 * 1024;
private final Map<String, String> mLinkedHashMap = Collections.synchronizedMap(new LinkedHashMap<String, String>(INITIAL_CAPACITY, LOAD_FACTOR, true));
/**
* A filename filter to use to identify the cache filenames which have CACHE_FILENAME_PREFIX prepended.
*/
private static final FilenameFilter cacheFileFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
return filename.startsWith(CACHE_FILENAME_PREFIX);
}
};
/**
* Used to fetch an instance of DiskLruCache.
*
* @param context
* @param cacheDir
* @param maxByteSize
* @return
*/
public static DiskLruCache openCache(Context context, File cacheDir, long maxByteSize) {
if (!cacheDir.exists()) {
cacheDir.mkdir();
}
if (cacheDir.isDirectory() && cacheDir.canWrite()) {
return new DiskLruCache(cacheDir, maxByteSize);
}
return null;
}
/**
* @param cacheDir
* @param maxByteSize
*/
private DiskLruCache(File cacheDir, long maxByteSize) {
mCacheDir = cacheDir;
maxCacheByteSize = maxByteSize;
}
/**
* Add a bitmap to the disk cache.
*
* @param key A unique identifier for the bitmap.
* @param data The bitmap to store.
*/
public void put(String key, Bitmap data) {
synchronized (mLinkedHashMap) {
if (mLinkedHashMap.get(key) == null) {
try {
final String file = createFilePath(mCacheDir, key);
if (writeBitmapToFile(data, file)) {
put(key, file);
flushCache();
}
} catch (final FileNotFoundException e) {
} catch (final IOException e) {
}
}
}
}
private void put(String key, String file) {
mLinkedHashMap.put(key, file);
cacheSize = mLinkedHashMap.size();
cacheByteSize += new File(file).length();
}
/**
* Flush the cache, removing oldest entries if the total size is over the specified cache size. Note that this isn't keeping track of stale files in the cache directory that
* aren't in the HashMap. If the images and keys in the disk cache change often then they probably won't ever be removed.
*/
private void flushCache() {
Entry<String, String> eldestEntry;
File eldestFile;
long eldestFileSize;
int count = 0;
while (count < MAX_REMOVALS && (cacheSize > maxCacheItemSize || cacheByteSize > maxCacheByteSize)) {
eldestEntry = mLinkedHashMap.entrySet().iterator().next();
eldestFile = new File(eldestEntry.getValue());
eldestFileSize = eldestFile.length();
mLinkedHashMap.remove(eldestEntry.getKey());
eldestFile.delete();
cacheSize = mLinkedHashMap.size();
cacheByteSize -= eldestFileSize;
count++;
}
}
/**
* Get an image from the disk cache.
*
* @param key The unique identifier for the bitmap
* @return The bitmap or null if not found
*/
public Bitmap get(String key) {
synchronized (mLinkedHashMap) {
try {
final String file = mLinkedHashMap.get(key);
if (file != null) {
return BitmapFactory.decodeFile(file);
} else {
final String existingFile = createFilePath(mCacheDir, key);
if (new File(existingFile).exists()) {
put(key, existingFile);
return BitmapFactory.decodeFile(existingFile);
}
}
} catch (OutOfMemoryError e) {
}
return null;
}
}
/**
* Checks if a specific key exist in the cache.
*
* @param key The unique identifier for the bitmap
* @return true if found, false otherwise
*/
public boolean containsKey(String key) {
// See if the key is in our HashMap
if (mLinkedHashMap.containsKey(key)) {
return true;
}
// Now check if there's an actual file that exists based on the key
final String existingFile = createFilePath(mCacheDir, key);
if (new File(existingFile).exists()) {
// File found, add it to the HashMap for future use
put(key, existingFile);
return true;
}
return false;
}
/**
* Removes all disk cache entries from this instance cache dir
*/
public void clearCache() {
DiskLruCache.clearCache(mCacheDir);
}
/**
* Removes all disk cache entries from the application cache directory in the uniqueName sub-directory.
*
* @param context The context to use
* @param uniqueName A unique cache directory name to append to the app cache directory
*/
public static void clearCache(Context context, String uniqueName) {
File cacheDir = getDiskCacheDir(context, uniqueName);
clearCache(cacheDir);
}
/**
* Removes all disk cache entries from the given directory. This should not be called directly, call {@link DiskLruCache#clearCache(Context, String)} or
* {@link DiskLruCache#clearCache()} instead.
*
* @param cacheDir The directory to remove the cache files from
*/
private static void clearCache(File cacheDir) {
final File[] files = cacheDir.listFiles(cacheFileFilter);
for (int i = 0; i < files.length; i++) {
files[i].delete();
}
}
/**
* Get a usable cache directory (external if available, internal otherwise).
*
* @param context The context to use
* @param uniqueName A unique directory name to append to the cache dir
* @return The cache dir
*/
public static File getDiskCacheDir(Context context, String uniqueName) {
// Check if media is mounted or storage is built-in, if so, try and use external cache dir
// otherwise use internal cache dir
final String cachePath = context.getCacheDir().getPath();
return new File(cachePath + File.separator + uniqueName);
}
/**
* Creates a constant cache file path given a target cache directory and an image key.
*
* @param cacheDir
* @param key
* @return
*/
public static String createFilePath(File cacheDir, String key) {
try {
// Use URLEncoder to ensure we have a valid filename, a tad hacky but it will do for
// this example
return cacheDir.getAbsolutePath() + File.separator + CACHE_FILENAME_PREFIX + URLEncoder.encode(key.replace("*", ""), "UTF-8");
} catch (final UnsupportedEncodingException e) {
}
return null;
}
/**
* Create a constant cache file path using the current cache directory and an image key.
*
* @param key
* @return
*/
public String createFilePath(String key) {
return createFilePath(mCacheDir, key);
}
/**
* Sets the target compression format and quality for images written to the disk cache.
*
* @param compressFormat
* @param quality
*/
public void setCompressParams(CompressFormat compressFormat, int quality) {
mCompressFormat = compressFormat;
mCompressQuality = quality;
}
/**
* Writes a bitmap to a file. Call {@link DiskLruCache#setCompressParams(CompressFormat, int)} first to set the target bitmap compression and format.
*
* @param bitmap
* @param file
* @return
*/
private boolean writeBitmapToFile(Bitmap bitmap, String file) throws IOException, FileNotFoundException {
OutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(file), IO_BUFFER_SIZE);
return bitmap.compress(mCompressFormat, mCompressQuality, out);
} finally {
if (out != null) {
out.close();
}
}
}
}
ImageFolder文件:图片的信息的定义:
package com.xiyouliwp.fangweixin;
/**
* 需求:对手机中的图片进行扫描,直接显示在gridview上,并且在扫描结束后得到一个list,,list里面存的是所有包含
* 图片的文件夹
* Created by lwp940118 on 2016/5/29.
* 李文朋
*/
public class ImageFolder {
//文件夹的路径
private String folderPath;
//第一张图片的文件夹路径
private String firstImagePath;
//文件夹名称
private String folderName;
//图片的数量
private int imageCount = 0;
public int getImageCount() {
return imageCount;
}
public String getFirstImagePath() {
return firstImagePath;
}
public String getFolderName() {
return folderName;
}
public String getFolderPath() {
return folderPath;
}
public void setFirstImagePath(String firstImagePath) {
this.firstImagePath = firstImagePath;
}
public void setFolderPath(String folderPath) {
this.folderPath = folderPath;
//判断字符/它第一次出现的位置
int start = this.folderPath.lastIndexOf("/");
//得到从/第一次出现的位置开始 到该字符串结束的子串为folderName
this.folderName = this.folderPath.substring(start);
}
public void setImageCount(int imageCount) {
this.imageCount = imageCount;
}
}
ImageLoade文件:缓存图片,使grideview运行流畅
package com.xiyouliwp.fangweixin;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
public class ImageLoade {
/**
* 图片缓存的核心类
*/
private LruCache<String, Bitmap> mLruCache;
/**
* 线程池
*/
private ExecutorService mThreadPool;
/**
* 线程池的线程数量,默认为1
*/
private int mThreadCount = 1;
/**
* 队列的调度方式
*/
private Type mType = Type.LIFO;
/**
* 任务队列
*/
private LinkedList<Runnable> mTasks;
/**
* 轮询的线程
*/
private Thread mPoolThread;
private Handler mPoolThreadHander;
/**
* 运行在UI线程的handler,用于给ImageView设置图片
*/
private Handler mHandler;
/**
* 引入一个值为1的信号量,防止mPoolThreadHander未初始化完成
*/
private volatile Semaphore mSemaphore = new Semaphore(0);
/**
* 引入一个值为1的信号量,由于线程池内部也有一个阻塞线程,防止加入任务的速度过快,使LIFO效果不明显
*/
private volatile Semaphore mPoolSemaphore;
private static ImageLoade mInstance;
/**
* 队列的调度方式
*
* @author zhy
*/
public enum Type {
FIFO, LIFO
}
/**
* 单例获得该实例对象
*
* @return
*/
public static ImageLoade getInstance() {
if (mInstance == null) {
synchronized (ImageLoade.class) {
if (mInstance == null) {
mInstance = new ImageLoade(1, Type.LIFO);
}
}
}
return mInstance;
}
private ImageLoade(int threadCount, Type type) {
init(threadCount, type);
}
private void init(int threadCount, Type type) {
// loop thread
mPoolThread = new Thread() {
@Override
public void run() {
Looper.prepare();
mPoolThreadHander = new Handler() {
@Override
public void handleMessage(Message msg) {
mThreadPool.execute(getTask());
try {
mPoolSemaphore.acquire();
} catch (InterruptedException e) {
}
}
};
// 释放一个信号量
mSemaphore.release();
Looper.loop();
}
};
mPoolThread.start();
// 获取应用程序最大可用内存
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 8;
mLruCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bit以上是关于仿微信图片选择器的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin 实现仿微信图片选择器(增删(长按无拖动))+RecyclerView+BaseQuickAdapter(官网github)的功能
Kotlin 实现仿微信图片选择器(增删(长按无拖动))+RecyclerView+BaseQuickAdapter(官网github)的功能