仿微信图片选择器
来源:互联网 发布:淘宝直播怎么介绍自己 编辑:程序博客网 时间:2024/05/01 22:17
目标:
1、尽可能的避免内存溢出
a、根据图片的显示大小去压缩图片
b、使用缓冲对我们的图片进行管理(LruCache)
2、用户操作UI控件必须充分的流程
getView里面尽可能不去做耗时操作(异步加载+回调)
3、用户预期显示的图片尽可能的快(图片的加载策略的选择) LIFO,后进先出
ImageLoader
getView()
{
url->Bitmap
url->LruCache查找
->找到返回
->找不到 url->Task->TaskQuque且发送一个通知去提醒后台轮询线程
}
后台轮询线程
TaskQuque->Task->线程池去执行
new Thread(run(){while(){}}).start()//没有采用,效率低
Handler+Looper+Message//异步消息处理框架,采用这个
Task->run()
{
根据url加载图片
1、获得图片显示的大小
2、使用Options对图片进行压缩
3、加载图片且放入LruCache
}
Task->TaskQueue->通知后台线程池->把Task放入到它的内部任务队列
修改:利用信号量
总结
ImageLoader
Handler+Looper+Message
handler在什么线程初始化就在那个线程
图片压缩
尺寸,options
setTag(url)
popupWindow 使用回调
涉及知识点:
1.信号量 Semaphore //阻塞和释放
2.获取应用的最大可用内存 //
int maxMemory = (int) Runtime.getRuntime().maxMemory();
3.线程池 //创建线程池
mThreadPool = Executors.newFixedThreadPool(threadCount);
4.队列 // mTaskQuequ = new LinkedList();
5.单例模式 //getInstance()
6.屏幕的像素 //DisplayMetrics metrics = imageView.getContext().getResources().getDisplayMetrics();
7.压缩图片 // 使用options
8.屏幕变暗(变灰) //WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 0.3f;
getWindow().setAttributes(lp);
9.扫描图片 // 使用 Uri + ContentResolver +Cursor
10.文件过滤 //FilenameFilter
11.数组转list //list = Arrays.asList(str【】);
12.复用 // converView和viewholder
13.Set // List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复
14.private static Set mState = new HashSet(); //如果没有static 在切换文件时,选择状态不会被保存
15.PopupWindow里面 setBackgroundDrawable(new BitmapDrawable());//设置外面可以点击,点击外部区域使它消失
16.拦截点击 //setTouchInterceptor
17.使用interface给actvity回调
18.GridView 里面 android:stretchMode=”columnWidth” 缩放与列宽大小同步
19.ImageView 里面 android:scaleType=”centerCrop” 均 衡的缩放图像(保持图像原始比例)
20.PopupWindow 的动画 anim/目录下声明,styles.xml声明 ,设置动画mPopupWindow.setAnimationStyle(R.style.dir_PopupWindow_anim);
效果
-
核心工作类ImageLoader
package com.example.day0301.util;import java.util.LinkedList;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;import android.annotation.SuppressLint;import android.app.ActionBar.LayoutParams;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.BitmapFactory.Options;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.support.v4.util.LruCache;import android.text.Layout;import android.util.DisplayMetrics;import android.view.Display;import android.widget.ImageView;import android.widget.RelativeLayout;/** * * @author Administrator * 图片加载类 */public class ImageLoader { public static ImageLoader mInstance; /** * 图片缓存的核心对象 */ private LruCache<String, Bitmap> mLruCache; /** * 线程池 */ private ExecutorService mThreadPool; private static final int DEAFULT_THREAD_COUNT = 1; private Type mType = Type.LIFO; /** * 任务队列 * 里面是链表 */ private LinkedList<Runnable> mTaskQuequ; /** * 后台轮询线程 */ private Thread mPoolThread; private Handler mPoolThreadHandler; /** * UI线程中的Handler */ private Handler mUIHandler; private Semaphore mPoolThreadHandlerSemaphore = new Semaphore(0); private Semaphore mSemaphoreThreadPool; public enum Type { FIFO,LIFO } public ImageLoader(int threadCount, Type type) { init(threadCount,type); } /** * 初始化 * @param mThreadCount * @param type */ @SuppressLint("HandlerLeak") private void init(int threadCount, Type type) { //后台轮询线程 mPoolThread = new Thread() { @Override public void run() { Looper.prepare(); mPoolThreadHandler = new Handler(){ @Override public void handleMessage(Message msg) { //通过线程池取出任务去执行 mThreadPool.execute(getTask()); try { mSemaphoreThreadPool.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } } }; //释放一个信号量 mPoolThreadHandlerSemaphore.release(); Looper.loop(); } }; mPoolThread.start(); //获取应用的最大可用内存 int maxMemory = (int) Runtime.getRuntime().maxMemory(); int cacheMemory = maxMemory/8; mLruCache = new LruCache<String,Bitmap>(cacheMemory){ @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight(); } }; //创建线程池 mThreadPool = Executors.newFixedThreadPool(threadCount); mTaskQuequ = new LinkedList<Runnable>(); mType = type; mSemaphoreThreadPool = new Semaphore(threadCount); } /** * 从任务队列取出一个方法 * @return */ private Runnable getTask() { if (mType == Type.FIFO) { return mTaskQuequ.removeFirst(); } else if (mType == Type.LIFO){ return mTaskQuequ.removeLast(); } return null; } //单例模式 public static ImageLoader getInstance(int threadCount,Type tpye) { //没有做同步处理,为了提高效率 if (mInstance == null) { synchronized (ImageLoader.class) { if (mInstance == null) { mInstance = new ImageLoader(threadCount, tpye); } } } return mInstance; } /** * g根据path为ImageView设置图片 * @param path * @param imageView */ @SuppressLint("HandlerLeak") public void loadImage(final String path,final ImageView imageView) { imageView.setTag(path); if (mUIHandler == null) { mUIHandler = new Handler() { public void handleMessage(Message msg) { //获取得到的图片,为imageview回调设置图片 ImgBeanHolder holder = (ImgBeanHolder) msg.obj; Bitmap bm = holder.bitmap; ImageView imageView = holder.imageView; String path = holder.Path; //将Path与getTag存储路径进行比较 if (imageView.getTag().toString().equals(path)) { imageView.setImageBitmap(bm); } } }; } //根据Path在缓存中获取bitmap Bitmap bm = getBitmapFromLruCache(path); if (bm != null) { refreshBitmap(path, imageView, bm); } else { addTasks(new Runnable() { @Override public void run() { // 加载图片 // 图片的压缩 // 1、获得图片需要显示的大小 ImageSize imageSize = getImageViewSize(imageView); // 2、压缩图片 Bitmap bm = decodeSampledBitmapFromPath(path, imageSize.width, imageSize.height); // 3、把图片加入到缓存 addBitmapToLruCache(path, bm); //回调 refreshBitmap(path, imageView, bm); mSemaphoreThreadPool.release(); } }); } } private void refreshBitmap(final String path, final ImageView imageView, Bitmap bm) { Message message = Message.obtain(); ImgBeanHolder holder = new ImgBeanHolder(); holder.bitmap = bm; holder.imageView = imageView; holder.Path = path; message.obj = holder; mUIHandler.sendMessage(message); } /** *将图片加入LruCache * @param pathm * @param bm */ protected void addBitmapToLruCache(String path, Bitmap bm) { if (getBitmapFromLruCache(path) == null) { if (bm != null) { mLruCache.put(path, bm); } } } /** * 根据图片需要显示的宽和高对图片进行压缩 * @param path * @param width * @param height * @return */ protected Bitmap decodeSampledBitmapFromPath(String path, int width, int height) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true;//获取图片的宽和高,但是不载入内存中 BitmapFactory.decodeFile(path, options);//options获得了图片实际的宽和高 options.inSampleSize = caculateInSampleSize(options,width,height); //使用获取到的InSampleSize再次解析图片 options.inJustDecodeBounds = false;//获取图片的宽和高,但是载入内存中 Bitmap bitmap = BitmapFactory.decodeFile(path, options); return bitmap; } /** * 根据需求的宽和高以及实际的宽和高计算SampleSize * @param options * @param width * @param height * @return */ private int caculateInSampleSize(Options options, int reqWidth, int reHheight) { int width = options.outWidth; int height = options.outHeight; int inSampleSize = 1; if(width > reqWidth || height > reHheight) { int widthRadio = Math.round(width * 1.0f / reqWidth); int heightRadio = Math.round(height * 1.0f / reHheight); inSampleSize = Math.max(widthRadio, heightRadio); } return inSampleSize; } private class ImageSize { int width; int height; } /** * 根据ImageView获得适当的压缩的宽和高 * @param imageView * @return */ @SuppressLint("NewApi") protected ImageSize getImageViewSize(ImageView imageView) { ImageSize imageSize = new ImageSize(); //屏幕的宽度 DisplayMetrics metrics = imageView.getContext().getResources().getDisplayMetrics(); RelativeLayout.LayoutParams lp = (android.widget.RelativeLayout.LayoutParams) imageView.getLayoutParams(); int width = imageView.getWidth(); if (width <= 0) { width = lp.width; } if (width <= 0) { width = imageView.getMaxWidth(); } if (width <= 0) { width = metrics.widthPixels; } int height = imageView.getHeight(); if (height <= 0) { height = lp.height; } if (height <= 0) { height = imageView.getMaxHeight(); } if (height <= 0) { height = metrics.heightPixels; } imageSize.width = width; imageSize.height = height; return imageSize; } private synchronized void addTasks(Runnable runnable) { mTaskQuequ.add(runnable); // if (mPoolThreadHandler == null) wait(); if (mPoolThreadHandler == null) { try { mPoolThreadHandlerSemaphore.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } } mPoolThreadHandler.sendEmptyMessage(0x110); } //持有对象 private class ImgBeanHolder { Bitmap bitmap; ImageView imageView; String Path; } private Bitmap getBitmapFromLruCache(String path) { return mLruCache.get(path); }}
Main
package com.example.day0301;import java.io.File;import java.io.FilenameFilter;import java.lang.reflect.Array;import java.util.ArrayList;import java.util.Arrays;import java.util.HashSet;import java.util.List;import java.util.Set;import com.example.day0301.ListImageDirPopupWindow.onItemClickInterface;import com.example.day0301.adapter.ImageAdapter;import com.example.day0301.bean.FolderBean;import com.example.day0301.util.ImageLoader;import com.example.day0301.util.ImageLoader.Type;import android.app.Activity;import android.app.ProgressDialog;import android.content.ContentResolver;import android.content.Context;import android.database.Cursor;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.provider.MediaStore;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.BaseAdapter;import android.widget.GridView;import android.widget.ImageButton;import android.widget.ImageView;import android.widget.PopupWindow;import android.widget.PopupWindow.OnDismissListener;import android.widget.RelativeLayout;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity implements onItemClickInterface{ private GridView mGridView; private ImageAdapter mImageAdapter; private RelativeLayout mBottomLy; private TextView mDirName; private TextView mDirCount; private int mMaxCount = 0; private File mCurrentFile; private List<String> mImgs; private List<FolderBean> mFolderBeans = new ArrayList<FolderBean>(); private ProgressDialog mProgressDialog; private ListImageDirPopupWindow mPopupWindow; private static final int DATA_LOADED = 1; private Handler mHandler = new Handler(){ public void handleMessage(android.os.Message msg) { if (msg.what == DATA_LOADED) { if (mProgressDialog.isShowing()) { mProgressDialog.dismiss(); } //绑定数据到View中 data2view(); initPopupWindow(); } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initDatas(); initEvent(); } protected void initPopupWindow() { mPopupWindow = new ListImageDirPopupWindow(this,mFolderBeans); mPopupWindow.setItemClickListener(this); mPopupWindow.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss() { lightOn(); } }); } /** * 内容区域变亮 */ protected void lightOn() { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = 1.0f; getWindow().setAttributes(lp); } protected void lightOff() { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = 0.3f; getWindow().setAttributes(lp); } protected void data2view() { if (mCurrentFile == null) { Toast.makeText(this, "为扫描到任何图片", Toast.LENGTH_SHORT).show(); return ; } //把数组赋值给list mImgs = Arrays.asList(mCurrentFile.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; } })); mImageAdapter = new ImageAdapter(this, mImgs, mCurrentFile.getAbsolutePath()); mGridView.setAdapter(mImageAdapter); mDirCount.setText(mMaxCount+""); mDirName.setText(mCurrentFile.getName()); } private void initEvent() { mBottomLy.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mPopupWindow.setAnimationStyle(R.style.dir_PopupWindow_anim); mPopupWindow.showAsDropDown(mBottomLy, 0, 0); lightOff(); } }); } /** * 利用ContentProvider扫描图片 */ private void initDatas() { //扫描图片 if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(this, "当前存储卡不可用", Toast.LENGTH_SHORT).show(); return; } mProgressDialog = ProgressDialog.show(this,null,"正在加载..."); new Thread() { @Override public void run() { //所有图片的Uri Uri mImgUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; ContentResolver cr = MainActivity.this.getContentResolver(); 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); Set<String> mDirPaths = new HashSet<String>(); while(cursor.moveToNext()) { String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); File parentFile = new File(path).getParentFile(); if (parentFile == null) { continue; } String dirPath = parentFile.getAbsolutePath(); FolderBean folderBean = null; if(mDirPaths.contains(dirPath)) { continue; } else { mDirPaths.add(dirPath); folderBean = new FolderBean(); folderBean.setDir(dirPath); folderBean.setFirstImgPath(path); } if (parentFile.list() == null) { continue; } int picSize = parentFile.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; } }).length; folderBean.setCount(picSize); mFolderBeans.add(folderBean); if (picSize > mMaxCount) { mMaxCount = picSize; mCurrentFile = parentFile; } } cursor.close(); mHandler.sendEmptyMessage(DATA_LOADED); Log.v("TAG", "mCount="+mMaxCount); } }.start(); } private void initView() { mGridView = (GridView) findViewById(R.id.id_grid_view); mBottomLy = (RelativeLayout) findViewById(R.id.id_bottom_ly); mDirName = (TextView) findViewById(R.id.id_dir_name); mDirCount = (TextView) findViewById(R.id.id_dir_count); } @Override public void onItemClick(FolderBean folderBean) { mCurrentFile = new File(folderBean.getDir()); mMaxCount = folderBean.getCount(); data2view(); mPopupWindow.dismiss(); }}
main.xml
<RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <GridView android:id="@+id/id_grid_view" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="@android:color/transparent" android:horizontalSpacing="3dp" android:listSelector="@android:color/transparent" android:numColumns="3" android:stretchMode="columnWidth" android:verticalSpacing="3dp"></GridView> <RelativeLayout android:id="@+id/id_bottom_ly" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:background="#ee000000" android:clipChildren="true" > <TextView android:id="@+id/id_dir_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:paddingLeft="10dp" android:text="所有图片" android:textColor="#fff"/> <TextView android:id="@+id/id_dir_count" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:paddingLeft="10dp" android:text="100张" android:textColor="#fff"/> </RelativeLayout></RelativeLayout>
ImageAdapter
package com.example.day0301.adapter;import java.util.HashSet;import java.util.List;import java.util.Set;import android.content.Context;import android.graphics.Color;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 com.example.day0301.R;import com.example.day0301.util.ImageLoader;import com.example.day0301.util.ImageLoader.Type;public class ImageAdapter extends BaseAdapter { private String mDirPath; private List<String> mImgPaths; private LayoutInflater mInflater; private static Set<String> mState = new HashSet<String>(); public ImageAdapter(Context context, List<String> mDatas, String path) { this.mDirPath = path; this.mImgPaths = mDatas; mInflater = LayoutInflater.from(context); } @Override public int getCount() { return mImgPaths.size(); } @Override public Object getItem(int position) { return mImgPaths.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { final ViewHolder viewHolder ;; if (convertView == null) { convertView = mInflater.inflate(R.layout.item_gridview, null); viewHolder = new ViewHolder(); viewHolder.mImg = (ImageView) convertView.findViewById(R.id.id_item_image); viewHolder.mSelect = (ImageButton) convertView.findViewById(R.id.id_item_select); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } //重置状态 viewHolder.mImg.setImageResource(R.drawable.pictures_no); viewHolder.mSelect.setImageResource(R.drawable.picture_unselected); viewHolder.mImg.setColorFilter(null); ImageLoader.getInstance(3, Type.LIFO).loadImage(mDirPath+"/"+mImgPaths.get(position), viewHolder.mImg); final String filePath = mDirPath+"/"+mImgPaths.get(position); viewHolder.mImg.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mState.contains(filePath)) { mState.remove(filePath); viewHolder.mImg.setColorFilter(null); viewHolder.mSelect.setImageResource(R.drawable.picture_unselected); } else { mState.add(filePath); viewHolder.mImg.setColorFilter(Color.parseColor("#77000000")); viewHolder.mSelect.setImageResource(R.drawable.pictures_selected); }// notifyDataSetChanged(); 会闪屏 } }); if (mState.contains(filePath)) { viewHolder.mImg.setColorFilter(Color.parseColor("#77000000")); viewHolder.mSelect.setImageResource(R.drawable.pictures_selected); } return convertView; } private class ViewHolder { ImageView mImg; ImageButton mSelect; }}
item_gridview.xml
<RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android" > <ImageView android:id="@+id/id_item_image" android:layout_width="match_parent" android:layout_height="100dp" android:scaleType="centerCrop" android:src="@drawable/pictures_no" /> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/id_item_select" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:layout_marginTop="3dp" android:layout_marginRight="3dp" android:background="@null" android:clickable="false" android:src="@drawable/picture_unselected"/></RelativeLayout>
FolderBean
package com.example.day0301.bean;public class FolderBean { private String dir; private String firstImgPath; private String name; private int count; public String getDir() { return dir; } public void setDir(String dir) { this.dir = dir; int lastIndexOf = this.dir.indexOf("/"); this.name = this.dir.substring(lastIndexOf); } public String getFirstImgPath() { return firstImgPath; } public void setFirstImgPath(String firstImgPath) { this.firstImgPath = firstImgPath; } public String getName() { return name; } public int getCount() { return count; } public void setCount(int count) { this.count = count; }}
ListImageDirPopupWindow
package com.example.day0301;import java.util.List;import com.example.day0301.bean.FolderBean;import com.example.day0301.util.ImageLoader;import com.example.day0301.util.ImageLoader.Type;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.drawable.BitmapDrawable;import android.util.DisplayMetrics;import android.util.Log;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.View.OnTouchListener;import android.view.WindowManager;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ArrayAdapter;import android.widget.ImageView;import android.widget.ListView;import android.widget.PopupWindow;import android.widget.TextView;@SuppressLint("ClickableViewAccessibility")public class ListImageDirPopupWindow extends PopupWindow { private int mWidth; private int mHeight; private View mConvertView; private ListView mListView; private List<FolderBean> mDatas; public interface onItemClickInterface { void onItemClick(FolderBean folderBean); } private onItemClickInterface mItemClickListener = null; public void setItemClickListener(onItemClickInterface mItemClickListener) { this.mItemClickListener = mItemClickListener; } @SuppressWarnings("deprecation") public ListImageDirPopupWindow (Context context, List<FolderBean> datas) { calWidthAndHeight(context); mConvertView = LayoutInflater.from(context).inflate(R.layout.popup_main, null); mDatas = datas; setContentView(mConvertView); setWidth(mWidth); setHeight(mHeight); setFocusable(true); setTouchable(true); setOutsideTouchable(true); setBackgroundDrawable(new BitmapDrawable());//设置外面可以点击,点击外部区域使它消失 setTouchInterceptor(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { dismiss(); return true; } return false; } }); initViews(context); initEvent(); } private void initViews(Context context) { mListView = (ListView) mConvertView.findViewById(R.id.id_pop_list); mListView.setAdapter(new ListDirAdapter(context,mDatas)); } private void initEvent() { mListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (mItemClickListener != null) { mItemClickListener.onItemClick(mDatas.get(position)); } } }); } /** * 计算PopupWindow的宽度和高度 * @param context */ private void calWidthAndHeight(Context context) { //1 DisplayMetrics metrics = context.getResources().getDisplayMetrics(); //2 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); mWidth = outMetrics.widthPixels; mHeight = (int) (outMetrics.heightPixels * 0.7); Log.v("TAG", metrics.widthPixels+","+outMetrics.widthPixels); } private class ListDirAdapter extends ArrayAdapter<FolderBean> { private LayoutInflater mInflater; private List<FolderBean> mDatas; public ListDirAdapter(Context context, List<FolderBean> objects) { super(context,0,objects); mInflater = LayoutInflater.from(context); mDatas = objects; } @Override public FolderBean getItem(int position) { return mDatas.get(position); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.item_popup_main, parent,false); viewHolder = new ViewHolder(); viewHolder.mImg = (ImageView) convertView.findViewById(R.id.id_dir_item_image); viewHolder.mDirName = (TextView) convertView.findViewById(R.id.id_dir_item_name); viewHolder.mDirCount = (TextView) convertView.findViewById(R.id.id_dir_item_count); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } FolderBean bean = getItem(position); //重置 viewHolder.mImg.setImageResource(R.drawable.pictures_no); ImageLoader.getInstance(3, Type.LIFO).loadImage(bean.getFirstImgPath(), viewHolder.mImg); String name = bean.getName(); name = name.substring(name.lastIndexOf("/")); viewHolder.mDirName.setText(name); viewHolder.mDirCount.setText(bean.getCount()+""); return convertView; } private class ViewHolder { ImageView mImg; TextView mDirName; TextView mDirCount; } }}
popup_main.xml
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android" > <ListView android:id="@+id/id_pop_list" android:layout_width="match_parent" android:layout_height="match_parent"></ListView></LinearLayout>
item_popup_main.xml
<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android" android:background="#fff" > <ImageView android:id="@+id/id_dir_item_image" android:layout_width="100dp" android:layout_height="100dp" android:layout_alignParentLeft="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:text="100" android:textSize="10sp"/> </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>
PopupWindow动画
/anim目录下
slide_up.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="200" android:fromXDelta="0" android:fromYDelta="100%" android:toXDelta="0" android:toYDelta="0"/></set>
slide_down.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="200" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="0" android:toYDelta="100%"/></set>
styles.xml
<style name="dir_PopupWindow_anim"> <item name="android:windowEnterAnimation">@anim/slide_up</item> <item name="android:windowExitAnimation">@anim/slide_down</item> </style>
转载于:
http://www.imooc.com/learn/489(视频)
http://blog.csdn.net/lmj623565791/article/details/39943731(博客带源码)
- 仿微信图片选择器
- Android-仿微信图片选择器
- Android 仿微信图片选择器
- 仿微信图片选择器
- 仿微信图片选择器
- Android仿微信图片选择器
- 0.仿微信图片选择器
- Android 仿微信图片选择器
- 仿微信图片选择器
- 仿微信图片选择器,一步到位!!!
- android仿微信图片选择器
- android 仿微信图片选择器
- 仿微信图片选择器
- android 超高仿微信图片选择器
- Android开发:仿微信图片选择器
- Android 超高仿微信图片选择器
- 图片选择器
- 图片选择器
- IOS_可移动的UIImageView(随手指移动)
- AnnotationConfigBeanDefinitionParser are only available on JDK 1.5 and higher
- Android ListView异步加载图片乱序问题,原因分析及解决方案(一)
- 指向结构体的指针必须初始化
- Android性能优化典范(转载)
- 仿微信图片选择器
- Django Xadmin安装
- 【第三章】 DI 之 3.2 循环依赖 ——跟我学spring3
- 盒模型&&外边距塌陷
- 反射——不同对象属性映射赋值
- web前端开发工程师前景到底怎么样
- Testlink(1)——TestLink Win版安装
- 探秘Java中String、StringBuilder以及StringBuffer
- 10g 及之后导出/导入工具