仿微信图片选择器
打开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, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
;
};
mThreadPool = Executors.newFixedThreadPool(threadCount);
mPoolSemaphore = new Semaphore(threadCount);
mTasks = new LinkedList<Runnable>();
mType = type == null ? Type.LIFO : type;
}
/**
* 加载图片
*
* @param path
* @param imageView
*/
public void loadImage(final String path, final ImageView imageView) {
// set tag
imageView.setTag(path);
// UI线程
if (mHandler == null) {
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
ImageView imageView = holder.imageView;
Bitmap bm = holder.bitmap;
String path = holder.path;
if (imageView.getTag().toString().equals(path)) {
imageView.setImageBitmap(bm);
}
}
};
}
Bitmap bm = getBitmapFromLruCache(path);
if (bm != null) {
ImgBeanHolder holder = new ImgBeanHolder();
holder.bitmap = bm;
holder.imageView = imageView;
holder.path = path;
Message message = Message.obtain();
message.obj = holder;
mHandler.sendMessage(message);
} else {
addTask(new Runnable() {
@Override
public void run() {
ImageSize imageSize = getImageViewWidth(imageView);
int reqWidth = imageSize.width;
int reqHeight = imageSize.height;
Bitmap bm = decodeSampledBitmapFromResource(path, reqWidth,
reqHeight);
addBitmapToLruCache(path, bm);
ImgBeanHolder holder = new ImgBeanHolder();
holder.bitmap = getBitmapFromLruCache(path);
holder.imageView = imageView;
holder.path = path;
Message message = Message.obtain();
message.obj = holder;
// Log.e("TAG", "mHandler.sendMessage(message);");
mHandler.sendMessage(message);
mPoolSemaphore.release();
}
});
}
}
/**
* 添加一个任务
*
* @param runnable
*/
private synchronized void addTask(Runnable runnable) {
try {
// 请求信号量,防止mPoolThreadHander为null
if (mPoolThreadHander == null)
mSemaphore.acquire();
} catch (InterruptedException e) {
}
mTasks.add(runnable);
mPoolThreadHander.sendEmptyMessage(0x110);
}
/**
* 取出一个任务
*
* @return
*/
private synchronized Runnable getTask() {
if (mType == Type.FIFO) {
return mTasks.removeFirst();
} else if (mType == Type.LIFO) {
return mTasks.removeLast();
}
return null;
}
/**
* 单例获得该实例对象
*
* @return
*/
public static ImageLoade getInstance(int threadCount, Type type) {
if (mInstance == null) {
synchronized (ImageLoade.class) {
if (mInstance == null) {
mInstance = new ImageLoade(threadCount, type);
}
}
}
return mInstance;
}
/**
* 根据ImageView获得适当的压缩的宽和高
*
* @param imageView
* @return
*/
private ImageSize getImageViewWidth(ImageView imageView) {
ImageSize imageSize = new ImageSize();
final DisplayMetrics displayMetrics = imageView.getContext()
.getResources().getDisplayMetrics();
final LayoutParams params = imageView.getLayoutParams();
int width = params.width == LayoutParams.WRAP_CONTENT ? 0 : imageView
.getWidth(); // Get actual image width
if (width <= 0)
width = params.width; // Get layout width parameter
if (width <= 0)
width = getImageViewFieldValue(imageView, "mMaxWidth"); // Check
// maxWidth
// parameter
if (width <= 0)
width = displayMetrics.widthPixels;
int height = params.height == LayoutParams.WRAP_CONTENT ? 0 : imageView
.getHeight(); // Get actual image height
if (height <= 0)
height = params.height; // Get layout height parameter
if (height <= 0)
height = getImageViewFieldValue(imageView, "mMaxHeight"); // Check
// maxHeight
// parameter
if (height <= 0)
height = displayMetrics.heightPixels;
imageSize.width = width;
imageSize.height = height;
return imageSize;
}
/**
* 从LruCache中获取一张图片,如果不存在就返回null。
*/
private Bitmap getBitmapFromLruCache(String key) {
return mLruCache.get(key);
}
/**
* 往LruCache中添加一张图片
*
* @param key
* @param bitmap
*/
private void addBitmapToLruCache(String key, Bitmap bitmap) {
if (getBitmapFromLruCache(key) == null) {
if (bitmap != null)
mLruCache.put(key, bitmap);
}
}
/**
* 计算inSampleSize,用于压缩图片
*
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
private int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// 源图片的宽度
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1;
if (width > reqWidth && height > reqHeight) {
// 计算出实际宽度和目标宽度的比率
int widthRatio = Math.round((float) width / (float) reqWidth);
int heightRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = Math.max(widthRatio, heightRatio);
}
return inSampleSize;
}
/**
* 根据计算的inSampleSize,得到压缩后图片
*
* @param pathName
* @param reqWidth
* @param reqHeight
* @return
*/
private Bitmap decodeSampledBitmapFromResource(String pathName,
int reqWidth, int reqHeight) {
// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
// 调用上面定义的方法计算inSampleSize值
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// 使用获取到的inSampleSize值再次解析图片
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(pathName, options);
return bitmap;
}
private class ImgBeanHolder {
Bitmap bitmap;
ImageView imageView;
String path;
}
private class ImageSize {
int width;
int height;
}
/**
* 反射获得ImageView设置的最大宽度和高度
*
* @param object
* @param fieldName
* @return
*/
private static int getImageViewFieldValue(Object object, String fieldName) {
int value = 0;
try {
Field field = ImageView.class.getDeclaredField(fieldName);
field.setAccessible(true);
int fieldValue = (Integer) field.get(object);
if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) {
value = fieldValue;
Log.e("TAG", value + "");
}
} catch (Exception e) {
}
return value;
}
}
ImageShowManager文件:图片的一些信息及其缓存情况的设置
package com.xiyouliwp.fangweixin;
/**
* Created by lwp940118 on 2016/5/31.
*/
import java.io.File;
import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Looper;
import android.support.v4.util.LruCache;
public class ImageShowManager {
private static ImageShowManager imageManager;
private static Application myApp;
private LruCache<String, Bitmap> mMemoryCache;
private DiskLruCache mDiskCache;
// 硬盘缓存区域的大小,可以提升之前浏览过的图片的显示速度
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 20;
// 硬盘缓存区域的文件名称
private static final String DISK_CACHE_SUBDIR = "thumbnails";
public static final int bitmap_width = 100;
public static final int bitmap_height = 100;
public static ImageShowManager from(Context context) {
// 如果不在ui线程中,则抛出异常
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new RuntimeException("Cannot instantiate outside UI thread.");
}
if (myApp == null) {
myApp = (Application) context.getApplicationContext();
}
if (imageManager == null) {
imageManager = new ImageShowManager(myApp);
}
//
return imageManager;
}
/**
* 私有的构造器为了保持单例模式
*/
private ImageShowManager(Context context) {
/********** 初始化内存缓冲区 ******/
int memClass = ((ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
memClass = memClass > 32 ? 32 : memClass;
// 使用可用内存的1/8作为图片缓存
final int cacheSize = 1024 * 1024 * memClass / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight();
}
};
/********* 初始化硬盘缓冲区 *********/
File cacheDir = DiskLruCache
.getDiskCacheDir(context, DISK_CACHE_SUBDIR);
mDiskCache = DiskLruCache.openCache(context, cacheDir, DISK_CACHE_SIZE);
}
/**
* 将图片保存至本地缓存
* @param key
* @param value
*/
public void putBitmapToDisk(String key,Bitmap value){
mDiskCache.put(key, value);
}
/**
* 从硬盘缓存中读取图像
* @param url
* @return
*/
public Bitmap getBitmapFormDisk(String url){
return mDiskCache.get(url);
}
/**
* 从内存缓存区中获取bitmap,根据特定的url
* @param url
* @return
*/
public Bitmap getBitmapFromMemory(String url){
return mMemoryCache.get(url);
}
/**
* 将新的图片添加至内存缓存区
* @param key
* @param value
*/
public void putBitmapToMemery(String key,Bitmap value){
mMemoryCache.put(key, value);
}
}
List_File_PopWind文件:弹出窗口的设置及其定义:
package com.xiyouliwp.fangweixin;
import java.util.List;
import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.PopupWindow;
/**
* Created by lwp940118 on 2016/5/29.
*/
public class List_File_PopWind extends
BasePopupWindowForListView<ImageFolder>{
private ListView mListDir;
public List_File_PopWind(int width, int height,
List<ImageFolder> datas, View convertView) {
super(convertView, width, height, true, datas);
}
@Override
public void initViews() {
mListDir = (ListView) findViewById(R.id.listviwe_dir);
mListDir.setAdapter(new CommonAdapter<ImageFolder>(context, mDatas,
R.layout.list_dir_item) {
@Override
public void convert(ViewHolder helper, ImageFolder item) {
helper.setText(R.id.id_dir_item_name, item.getFolderName());
helper.setImageByUrl(R.id.id_dir_item_image,
item.getFirstImagePath());
helper.setText(R.id.id_dir_item_count, item.getImageCount() + "张");
}
});
}
public interface OnImageDirSelected {
void selected(ImageFolder floder);
}
private OnImageDirSelected mImageDirSelected;
public void setOnImageDirSelected(OnImageDirSelected mImageDirSelected) {
this.mImageDirSelected = mImageDirSelected;
}
@Override
public void initEvents() {
mListDir.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (mImageDirSelected != null) {
mImageDirSelected.selected(mDatas.get(position));
}
}
});
}
@Override
public void init() {
}
@Override
protected void beforeInitWeNeedSomeParams(Object... params) {
}
}
abstract class BasePopupWindowForListView<T> extends PopupWindow {
/**
* 布局文件的最外层View
*/
protected View mContentView;
protected Context context;
/**
* ListView的数据集
*/
protected List<T> mDatas;
public BasePopupWindowForListView(View contentView, int width, int height,
boolean focusable) {
this(contentView, width, height, focusable, null);
}
public BasePopupWindowForListView(View contentView, int width, int height,
boolean focusable, List<T> mDatas) {
this(contentView, width, height, focusable, mDatas, new Object[0]);
}
public BasePopupWindowForListView(View contentView, int width, int height,
boolean focusable, List<T> mDatas, Object... params) {
super(contentView, width, height, focusable);
this.mContentView = contentView;
context = contentView.getContext();
if (mDatas != null)
this.mDatas = mDatas;
if (params != null && params.length > 0) {
beforeInitWeNeedSomeParams(params);
}
setBackgroundDrawable(new BitmapDrawable());
setTouchable(true);
setOutsideTouchable(true);
setTouchInterceptor(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
dismiss();
return true;
}
return false;
}
});
initViews();
initEvents();
init();
}
protected abstract void beforeInitWeNeedSomeParams(Object... params);
public abstract void initViews();
public abstract void initEvents();
public abstract void init();
public View findViewById(int id) {
return mContentView.findViewById(id);
}
protected static int dpToPx(Context context, int dp) {
return (int) (context.getResources().getDisplayMetrics().density * dp + 0.5f);
}
}
PopRecommend_ImageAdd_Adapter文件:返回时存放选择图片的gridview的适配器
package com.xiyouliwp.fangweixin;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
/**
* Created by lwp940118 on 2016/5/31.
*/
public class PopRecommend_ImageAdd_Adapter extends BaseAdapter {
private Activity uiActivity;
private ArrayList<String> paths;
private int size;
private ImageShowManager imageManager;
private LayoutInflater li;
public PopRecommend_ImageAdd_Adapter(Activity a, ArrayList<String> paths) {
this.uiActivity = a;
this.paths = paths;
size = paths.size();
imageManager = ImageShowManager.from(uiActivity);
li = LayoutInflater.from(uiActivity);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return size;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SurfaceHolder surfaceHolder = new SurfaceHolder();
if (convertView != null) {
surfaceHolder = (SurfaceHolder) convertView.getTag();
} else {
convertView = li.inflate(R.layout.item_gridview_poprecommend, null);
surfaceHolder.iv = (ImageView) convertView
.findViewById(R.id.imageView1);
}
convertView.setTag(surfaceHolder);
String path = paths.get(position);
// 首先检测是否已经有线程在加载同样的资源(如果则取消较早的),避免出现重复加载
if (cancelPotentialLoad(path, surfaceHolder.iv)) {
AsyncLoadImageTask task = new AsyncLoadImageTask(surfaceHolder.iv);
surfaceHolder.iv.setImageDrawable(new LoadingDrawable(task));
task.execute(path);
}
return convertView;
}
static class SurfaceHolder {
ImageView iv;
}
/**
* 判断当前的imageview是否在加载相同的资源
*
* @param url
* @param imageview
* @return
*/
private boolean cancelPotentialLoad(String url, ImageView imageview) {
AsyncLoadImageTask loadImageTask = getAsyncLoadImageTask(imageview);
if (loadImageTask != null) {
String bitmapUrl = loadImageTask.url;
if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
loadImageTask.cancel(true);
} else {
// 相同的url已经在加载中.
return false;
}
}
return true;
}
/**
* 负责加载图片的异步线程
*
* @author Administrator
*/
class AsyncLoadImageTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private String url = null;
public AsyncLoadImageTask(ImageView imageview) {
super();
imageViewReference = new WeakReference<ImageView>(imageview);
}
@Override
protected Bitmap doInBackground(String... params) {
/**
* 具体的获取bitmap的部分,流程: 从内存缓冲区获取,如果没有向硬盘缓冲区获取,如果没有从sd卡/网络获取
*/
Bitmap bitmap = null;
this.url = params[0];
// 从内存缓存区域读取
bitmap = imageManager.getBitmapFromMemory(url);
if (bitmap != null) {
Log.d("dqq", "return by 内存");
return bitmap;
}
// 从硬盘缓存区域中读取
bitmap = imageManager.getBitmapFormDisk(url);
if (bitmap != null) {
imageManager.putBitmapToMemery(url, bitmap);
Log.d("dqq", "return by 硬盘");
return bitmap;
}
// 没有缓存则从原始位置读取
bitmap = BitmapUtilities.getBitmapThumbnail(url,
ImageShowManager.bitmap_width,
ImageShowManager.bitmap_height);
imageManager.putBitmapToMemery(url, bitmap);
imageManager.putBitmapToDisk(url, bitmap);
Log.d("dqq", "return by 原始读取");
return bitmap;
}
@Override
protected void onPostExecute(Bitmap resultBitmap) {
if (isCancelled()) {
// 被取消了
resultBitmap = null;
}
if (imageViewReference != null) {
ImageView imageview = imageViewReference.get();
AsyncLoadImageTask loadImageTask = getAsyncLoadImageTask(imageview);
if (this == loadImageTask) {
imageview.setImageDrawable(null);
imageview.setImageBitmap(resultBitmap);
}
}
super.onPostExecute(resultBitmap);
}
}
/**
* 根据imageview,获得正在为此imageview异步加载数据的函数
*
* @param imageview
* @return
*/
private AsyncLoadImageTask getAsyncLoadImageTask(ImageView imageview) {
if (imageview != null) {
Drawable drawable = imageview.getDrawable();
if (drawable instanceof LoadingDrawable) {
LoadingDrawable loadedDrawable = (LoadingDrawable) drawable;
return loadedDrawable.getLoadImageTask();
}
}
return null;
}
/**
* 记录imageview对应的加载任务,并且设置默认的drawable
*
* @author Administrator
*/
public static class LoadingDrawable extends ColorDrawable {
// 引用与drawable相关联的的加载线程
private final WeakReference<AsyncLoadImageTask> loadImageTaskReference;
public LoadingDrawable(AsyncLoadImageTask loadImageTask) {
super(Color.BLUE);
loadImageTaskReference = new WeakReference<AsyncLoadImageTask>(
loadImageTask);
}
public AsyncLoadImageTask getLoadImageTask() {
return loadImageTaskReference.get();
}
}
}
ViewHolde文件:从sd卡中读取图片时gridview和listview的优化:
package com.xiyouliwp.fangweixin;
/**
* Created by lwp940118 on 2016/5/29.
*/
import android.content.Context;
import android.graphics.Bitmap;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class ViewHolder {
private final SparseArray<View> mViews;
private int mPosition;
private View mConvertView;
private ViewHolder(Context context, ViewGroup parent, int layoutId,
int position) {
this.mPosition = position;
this.mViews = new SparseArray<View>();
mConvertView = LayoutInflater.from(context).inflate(layoutId, parent,
false);
// setTag
mConvertView.setTag(this);
}
/**
* 拿到一个ViewHolder对象
*/
public static ViewHolder get(Context context, View convertView,
ViewGroup parent, int layoutId, int position) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder(context, parent, layoutId, position);
} else {
holder = (ViewHolder) convertView.getTag();
holder.mPosition = position;
}
return holder;
}
public View getConvertView() {
return mConvertView;
}
/**
* 通过控件的Id获取对于的控件,如果没有则加入views
*
* @return
*/
public <T extends View> T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
/**
* 为TextView设置字符串
*
* @return
*/
public ViewHolder setText(int viewId, String text) {
TextView view = getView(viewId);
view.setText(text);
return this;
}
/**
* 为ImageView设置图片
*
* @return
*/
public ViewHolder setImageResource(int viewId, int drawableId) {
ImageView view = getView(viewId);
view.setImageResource(drawableId);
return this;
}
/**
* 为ImageView设置图片
*/
public ViewHolder setImageBitmap(int viewId, Bitmap bm) {
ImageView view = getView(viewId);
view.setImageBitmap(bm);
return this;
}
/**
* 为ImageView设置图片
*/
public ViewHolder setImageByUrl(int viewId, String url) {
ImageLoade.getInstance(3, ImageLoade.Type.LIFO).loadImage(url, (ImageView) getView(viewId));
return this;
}
public int getPosition() {
return mPosition;
}
}
push_bottom_in.xml push_bottom_out.xml文件:定义弹出窗口的划入划出方式:
<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromYDelta="100%p"
android:toYDelta="0"
/>
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="200"
/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromYDelta="0"
android:toYDelta="50%p" />
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="200"
/>
</set>
mybutton.xml按钮形状设置:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape
android:shape="rectangle"
>
<corners
android:radius="8dp"/>
<solid
android:color="#ffffff"/>
</shape>
</item>
<item
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp">
<shape android:shape="rectangle" >
<corners android:radius="8dp" />
<solid android:color="#ddf0ed" />
</shape>
</item>
</layer-list>
myedittext.xml 输入框的边框设置
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<!-- <gradient
android:angle="45"
android:endColor="#CCCCCC"
android:startColor="#CCCCCC" /> -->
<padding
android:bottom="7dp"
android:left="7dp"
android:right="7dp"
android:top="7dp" />
<!-- 设置圆角矩形 -->
<corners android:radius="6dp" />
<stroke
android:width="5px"
android:color="#1199EF" />
<solid android:color="#CCCCCC" />
</shape>
下面给出demo中使用的布局文件
activity_image_add.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:background="#ddf0ed">
<ImageButton
android:id="@+id/imagebutton_imageadd_back"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="center"
android:layout_marginLeft="15dp"
android:background="@drawable/share_search_back"
/>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="iPet选择图片"
android:gravity="center"
android:textSize="20dp"/>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<ImageButton
android:id="@+id/imagebutton_imageadd_finish"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_gravity="center"
android:layout_marginRight="15dp"
android:background="@drawable/finish"/>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="@+id/gridview_imageadd"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="@android:color/transparent"
android:clipChildren="true"
android:gravity="center"
android:horizontalSpacing="3dip"
android:listSelector="@android:color/transparent"
android:numColumns="3"
android:stretchMode="columnWidth"
android:verticalSpacing="3dip">
</GridView>
<RelativeLayout
android:id="@+id/id_bottom_ly"
android:layout_width="match_parent"
android:layout_height="50dip"
android:layout_alignParentBottom="true"
android:background="#e0000000"
android:clickable="true">
<TextView
android:id="@+id/id_choose_dir"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:gravity="center_vertical"
android:paddingLeft="10dip"
android:text="所有图片"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/id_total_count"
android:layout_width="50dip"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:gravity="center"
android:text="0张"
android:textColor="@android:color/white" />
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/linearlayout_pop_recommend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="20dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#ddf0ed"
android:orientation="horizontal">
<TextView
android:id="@+id/textview_recommend_list"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="15dp"
android:gravity="left|center"
android:text="动态发布:"
android:textColor="#fb0b0b0b"
android:textSize="20dp" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<ImageButton
android:id="@+id/imagview_poprecommend_back"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginRight="15dp"
android:background="@drawable/quxiao" />
</LinearLayout>
<EditText
android:id="@+id/edittext_poprecommend"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="@drawable/myedittext" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="70dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<LinearLayout
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:background="#ddf0ed">
<ImageButton
android:id="@+id/iamgebutton_poprecommend_tianjiatupian"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:background="@drawable/tianjiatupian" />
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="5" />
<Button
android:id="@+id/button_poprecommend_fabu"
android:layout_width="70dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:background="@drawable/mybutton"
android:text="发布"
android:textSize="20dp" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
<GridView
android:id="@+id/gridview_poprecommend"
android:layout_width="match_parent"
android:layout_height="150dp"
android:cacheColorHint="@android:color/transparent"
android:clipChildren="true"
android:gravity="center"
android:horizontalSpacing="3dip"
android:listSelector="@android:color/transparent"
android:numColumns="4"
android:stretchMode="columnWidth"
android:verticalSpacing="3dip">
</GridView>
<TextView
android:layout_width="match_parent"
android:layout_height="20dp"/>
</LinearLayout>
item_gridview_imageadd.xml
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="@+id/id_item_image"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:background="@drawable/pictures_no"
android:scaleType="centerCrop" />
<ImageButton
android:id="@+id/id_item_select"
android:clickable="false"
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/pictures_selected" />
</RelativeLayout>
item_gridview_poprecommend.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:orientation="vertical" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="10dp"
android:scaleType="centerInside"
android:background="@drawable/pictures_no"/>
</RelativeLayout>
</LinearLayout>
list_dir_item.xml
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp" >
<ImageView
android:id="@+id/id_dir_item_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="@drawable/pic_dir"
android:paddingBottom="17dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="9dp"
android:scaleType="fitXY"
android:src="@drawable/ic_launcher" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@id/id_dir_item_image"
android:orientation="vertical" >
<TextView
android:id="@+id/id_dir_item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="所有图片"
android:textSize="10sp" />
<TextView
android:id="@+id/id_dir_item_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="4723张"
android:textColor="#444"
android:textSize="8sp" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="20dp"
android:src="@drawable/dir_choose" />
</RelativeLayout>
list_dir.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/listviwe_dir"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:divider="#EEE3D9"
android:dividerHeight="1px" >
</ListView>
</LinearLayout>
本demo参考博文有:
http://blog.csdn.net/lmj623565791/article/details/39943731/
还有一些小的问题是从网上百度的 忘记地址了,总之谢谢他们
最后别忘了给整个demo加入权限设置:
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>