Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果

首先我们先看第一个界面吧,使用将手机中的图片扫描出来,然后根据图片的所在的文件夹将其分类出来,并显示所在文件夹里面的一张图片和文件夹中图片个数,我们根据界面元素(文件夹名,
文件夹图片个数,文件夹中的一张图片)使用一个实体对象ImageBean来封装这三个属性


package com.example.imagescan;

/**
* GridView的每个item的数据对象
*
* @author len
*
*/
public class ImageBean{
/**
* 文件夹的第一张图片路径
*/
private String topImagePath;
/**
* 文件夹名
*/
private String folderName;
/**
* 文件夹中的图片数
*/
private int imageCounts;

public String getTopImagePath() {
return topImagePath;
}
public void setTopImagePath(String topImagePath) {
this.topImagePath = topImagePath;
}
public String getFolderName() {
return folderName;
}
public void setFolderName(String folderName) {
this.folderName = folderName;
}
public int getImageCounts() {
return imageCounts;
}
public void setImageCounts(int imageCounts) {
this.imageCounts = imageCounts;
}

}

接下来就是主界面的布局啦,上面的导航栏我没有加进去,只有下面的GridView,所以说主界面布局中只有一个GridView


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<GridView
android:id="@+id/main_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:listSelector="@android:color/transparent"
android:cacheColorHint="@android:color/transparent"
android:stretchMode="columnWidth"
android:horizontalSpacing="20dip"
android:gravity="center"
android:verticalSpacing="20dip"
android:columnWidth="90dip"
android:numColumns="2" >
</GridView>

</RelativeLayout>

接下来就是GridView的Item的布局,看上面的图也行你会认为他的效果是2张图片添加的效果,其实不是,后面的叠加效果只是一张背景图片而已,代码先贴上来


<?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" >

<FrameLayout
android:id="@+id/framelayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >

<com.example.imagescan.MyImageView
android:id="@+id/group_image"
android:background="@drawable/albums_bg"
android:src="@drawable/friends_sends_pictures_no"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:paddingTop="18dip"
android:paddingBottom="30dip"
android:scaleType="fitXY"
android:layout_width="fill_parent"
android:layout_height="150dip" />

<TextView
android:id="@+id/group_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/albums_icon_bg"
android:gravity="center"
android:layout_marginBottom="10dip"
android:text="5"
android:layout_gravity="bottom|center_horizontal" />
</FrameLayout>

<TextView
android:id="@+id/group_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_below="@id/framelayout"
android:layout_centerHorizontal="true"
android:ellipsize="end"
android:singleLine="true"
android:text="Camera"
android:textSize="16sp" />

</RelativeLayout>

看到上面的布局代码,也行你已经发现了,上面使用的是自定义的MyImageView,我先不说这个自定义MyImageView的作用,待会再给大家说,我们继续看代码第一个界面的主要代码


package com.example.imagescan;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
/**
* @blog http://blog.csdn.net/xiaanming
*
* @author xiaanming
*
*
*/
public class MainActivity extends Activity {
private HashMap<String, List<String>> mGruopMap = new HashMap<String, List<String>>();
private List<ImageBean> list = new ArrayList<ImageBean>();
private final static int SCAN_OK = 1;
private ProgressDialog mProgressDialog;
private GroupAdapter adapter;
private GridView mGroupGridView;

private Handler mHandler = new Handler(){

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SCAN_OK:
//关闭进度条
mProgressDialog.dismiss();

adapter = new GroupAdapter(MainActivity.this, list = subGroupOfImage(mGruopMap), mGroupGridView);
mGroupGridView.setAdapter(adapter);
break;
}
}

};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mGroupGridView = (GridView) findViewById(R.id.main_grid);

getImages();

mGroupGridView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
List<String> childList = mGruopMap.get(list.get(position).getFolderName());

Intent mIntent = new Intent(MainActivity.this, ShowImageActivity.class);
mIntent.putStringArrayListExtra("data", (ArrayList<String>)childList);
startActivity(mIntent);

}
});

}

/**
* 利用ContentProvider扫描手机中的图片,此方法在运行在子线程中
*/
private void getImages() {
//显示进度条
mProgressDialog = ProgressDialog.show(this, null, "正在加载...");

new Thread(new Runnable() {

@Override
public void run() {
Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver mContentResolver = MainActivity.this.getContentResolver();

//只查询jpeg和png的图片
Cursor mCursor = mContentResolver.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);

if(mCursor == null){
return;
}

while (mCursor.moveToNext()) {
//获取图片的路径
String path = mCursor.getString(mCursor
.getColumnIndex(MediaStore.Images.Media.DATA));

//获取该图片的父路径名
String parentName = new File(path).getParentFile().getName();

//根据父路径名将图片放入到mGruopMap中
if (!mGruopMap.containsKey(parentName)) {
List<String> chileList = new ArrayList<String>();
chileList.add(path);
mGruopMap.put(parentName, chileList);
} else {
mGruopMap.get(parentName).add(path);
}
}

//通知Handler扫描图片完成
mHandler.sendEmptyMessage(SCAN_OK);
mCursor.close();
}
}).start();

}

/**
* 组装分组界面GridView的数据源,因为我们扫描手机的时候将图片信息放在HashMap中
* 所以需要遍历HashMap将数据组装成List
*
* @param mGruopMap
* @return
*/
private List<ImageBean> subGroupOfImage(HashMap<String, List<String>> mGruopMap){
if(mGruopMap.size() == 0){
return null;
}
List<ImageBean> list = new ArrayList<ImageBean>();

Iterator<Map.Entry<String, List<String>>> it = mGruopMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, List<String>> entry = it.next();
ImageBean mImageBean = new ImageBean();
String key = entry.getKey();
List<String> value = entry.getValue();

mImageBean.setFolderName(key);
mImageBean.setImageCounts(value.size());
mImageBean.setTopImagePath(value.get(0));//获取该组的第一张图片

list.add(mImageBean);
}

return list;

}

}

  • 首先看getImages()这个方法,该方法是使用ContentProvider将手机中的图片扫描出来,我这里只扫描了手机的外部存储中的图片,由于手机中可能存在很多的图片,扫描图片又比较耗时,所以我们在这里开启了子线程去获取图片,扫描的图片都存放在Cursor中,我们先要将图片按照文件夹进行分类,我们使用了HashMap来进行分类并将结果存储到mGruopMap(Key是文件夹名,Value是文件夹中的图片路径的List)中,分类完了关闭Cursor并利用Handler来通知主线程

  • 然后是subGroupOfImage()方法,改方法是将mGruopMap的数据组装到List中,在List中存放GridView中的每个item的数据对象ImageBean,
    遍历HashMap对象,具体的逻辑看代码,之后就是给GridView设置Adapter。

  • 设置item点击事件,点击文件夹跳转到展示文件夹图片的Activity,
    我们需要传递每个文件夹中的图片的路径的集合看GroupAdapter的代码之前,我们先看一个比较重要的类,本地图片加载器NativeImageLoader


    package com.example.imagescan;

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;

    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Point;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v4.util.LruCache;

    /**
    * 本地图片加载器,采用的是异步解析本地图片,单例模式利用getInstance()获取NativeImageLoader实例
    * 调用loadNativeImage()方法加载本地图片,此类可作为一个加载本地图片的工具类
    *
    * @blog http://blog.csdn.net/xiaanming
    *
    * @author xiaanming
    *
    */
    public class NativeImageLoader {
    private LruCache<String, Bitmap> mMemoryCache;
    private static NativeImageLoader mInstance = new NativeImageLoader();
    private ExecutorService mImageThreadPool = Executors.newFixedThreadPool(1);

    private NativeImageLoader(){
    //获取应用程序的最大内存
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

    //用最大内存的1/4来存储图片
    final int cacheSize = maxMemory / 4;
    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {

    //获取每张图片的大小
    @Override
    protected int sizeOf(String key, Bitmap bitmap) {
    return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
    }
    };
    }

    /**
    * 通过此方法来获取NativeImageLoader的实例
    * @return
    */
    public static NativeImageLoader getInstance(){
    return mInstance;
    }

    /**
    * 加载本地图片,对图片不进行裁剪
    * @param path
    * @param mCallBack
    * @return
    */
    public Bitmap loadNativeImage(final String path, final NativeImageCallBack mCallBack){
    return this.loadNativeImage(path, null, mCallBack);
    }

    /**
    * 此方法来加载本地图片,这里的mPoint是用来封装ImageView的宽和高,我们会根据ImageView控件的大小来裁剪Bitmap
    * 如果你不想裁剪图片,调用loadNativeImage(final String path, final NativeImageCallBack mCallBack)来加载
    * @param path
    * @param mPoint
    * @param mCallBack
    * @return
    */
    public Bitmap loadNativeImage(final String path, final Point mPoint, final NativeImageCallBack mCallBack){
    //先获取内存中的Bitmap
    Bitmap bitmap = getBitmapFromMemCache(path);

    final Handler mHander = new Handler(){

    @Override
    public void handleMessage(Message msg) {
    super.handleMessage(msg);
    mCallBack.onImageLoader((Bitmap)msg.obj, path);
    }

    };

    //若该Bitmap不在内存缓存中,则启用线程去加载本地的图片,并将Bitmap加入到mMemoryCache中
    if(bitmap == null){
    mImageThreadPool.execute(new Runnable() {

    @Override
    public void run() {
    //先获取图片的缩略图
    Bitmap mBitmap = decodeThumbBitmapForFile(path, mPoint == null ? 0: mPoint.x, mPoint == null ? 0: mPoint.y);
    Message msg = mHander.obtainMessage();
    msg.obj = mBitmap;
    mHander.sendMessage(msg);

    //将图片加入到内存缓存
    addBitmapToMemoryCache(path, mBitmap);
    }
    });
    }
    return bitmap;

    }

    /**
    * 往内存缓存中添加Bitmap
    *
    * @param key
    * @param bitmap
    */
    private void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null && bitmap != null) {
    mMemoryCache.put(key, bitmap);
    }
    }

    /**
    * 根据key来获取内存中的图片
    * @param key
    * @return
    */
    private Bitmap getBitmapFromMemCache(String key) {
    return mMemoryCache.get(key);
    }

    /**
    * 根据View(主要是ImageView)的宽和高来获取图片的缩略图
    * @param path
    * @param viewWidth
    * @param viewHeight
    * @return
    */
    private Bitmap decodeThumbBitmapForFile(String path, int viewWidth, int viewHeight){
    BitmapFactory.Options options = new BitmapFactory.Options();
    //设置为true,表示解析Bitmap对象,该对象不占内存
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path, options);
    //设置缩放比例
    options.inSampleSize = computeScale(options, viewWidth, viewHeight);

    //设置为false,解析Bitmap对象加入到内存中
    options.inJustDecodeBounds = false;

    return BitmapFactory.decodeFile(path, options);
    }

    /**
    * 根据View(主要是ImageView)的宽和高来计算Bitmap缩放比例。默认不缩放
    * @param options
    * @param width
    * @param height
    */
    private int computeScale(BitmapFactory.Options options, int viewWidth, int viewHeight){
    int inSampleSize = 1;
    if(viewWidth == 0 || viewWidth == 0){
    return inSampleSize;
    }
    int bitmapWidth = options.outWidth;
    int bitmapHeight = options.outHeight;

    //假如Bitmap的宽度或高度大于我们设定图片的View的宽高,则计算缩放比例
    if(bitmapWidth > viewWidth || bitmapHeight > viewWidth){
    int widthScale = Math.round((float) bitmapWidth / (float) viewWidth);
    int heightScale = Math.round((float) bitmapHeight / (float) viewWidth);

    //为了保证图片不缩放变形,我们取宽高比例最小的那个
    inSampleSize = widthScale < heightScale ? widthScale : heightScale;
    }
    return inSampleSize;
    }

    /**
    * 加载本地图片的回调接口
    *
    * @author xiaanming
    *
    */
    public interface NativeImageCallBack{
    /**
    * 当子线程加载完了本地的图片,将Bitmap和图片路径回调在此方法中
    * @param bitmap
    * @param path
    */
    public void onImageLoader(Bitmap bitmap, String path);
    }
    }

    该类是一个单例类,提供了本地图片加载,内存缓存,裁剪等逻辑,该类在加载本地图片的时候采用的是异步加载的方式,对于大图片的加载也是比较耗时的,所以采用子线程的方式去加载,对于图片的缓存机制使用的是LruCache,使用手机分配给应用程序内存的1/4用来缓存图片,除了使用LruCache缓存图片之外,还对图片进行了裁剪,举个很简单的例子,假如我们的控件大小是100
    * 100,
    而我们的图片是400*400,我们加载这么大的图片需要很多的内存,所以我们采用了图片裁剪,根据控件的大小来确定图片的裁剪比例,从而减小内存的消耗,提高GridView滑动的流畅度,介绍里面几个比较重要的方法

    1. computeScale()计算图片需要裁剪的比例,根据控件的大小和图片的大小确定比例,如果图片比控件大,我们就进行裁剪,否则不需要。

    2. decodeThumbBitmapForFile()方法是根据计算好了图片裁剪的比例之后从文件中加载图片,我们先设置options.inJustDecodeBounds
      =
      true表示解析不占用内存,但是我们能获取图片的具体大小,利用computeScale()计算好比例,在将options.inJustDecodeBounds=false,再次解析Bitmap,这样子就对图片进行了裁剪。

    3. loadNativeImage(final String path, final Point mPoint, final
      NativeImageCallBack
      mCallBack)我们在客户端只需要调用该方法就能获取到Bitmap对象,里面的具体逻辑是先判断内存缓存LruCache中是否存在该Bitmap,不存在就开启子线程去读取,为了方便管理加载本地图片线程,这里使用了线程池,池中只能容纳一个线程,读取完了本地图片先将Bitmap加入到LruCache中,保存的Key为图片路径,然后再使用Handler通知主线程图片加载好了,之后将Bitmap和路径回调到方法onImageLoader(Bitmap
      bitmap, String path)中,该方法的mPoint是用来封装控件的宽和高的对象

    4. 如果不对图片进行裁剪直接这个方法的重载方法loadNativeImage(final String path, final
      NativeImageCallBack mCallBack) 就行了,逻辑是一样的,只是这个方法不对图片进行裁剪

    接下来就是GridView的Adapter类的代码


    package com.example.imagescan;

    import java.util.List;

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Point;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.GridView;
    import android.widget.ImageView;
    import android.widget.TextView;

    import com.example.imagescan.MyImageView.OnMeasureListener;
    import com.example.imagescan.NativeImageLoader.NativeImageCallBack;

    public class GroupAdapter extends BaseAdapter{
    private List<ImageBean> list;
    private Point mPoint = new Point(0, 0);//用来封装ImageView的宽和高的对象
    private GridView mGridView;
    protected LayoutInflater mInflater;

    @Override
    public int getCount() {
    return list.size();
    }

    @Override
    public Object getItem(int position) {
    return list.get(position);
    }

    @Override
    public long getItemId(int position) {
    return position;
    }

    public GroupAdapter(Context context, List<ImageBean> list, GridView mGridView){
    this.list = list;
    this.mGridView = mGridView;
    mInflater = LayoutInflater.from(context);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder viewHolder;
    ImageBean mImageBean = list.get(position);
    String path = mImageBean.getTopImagePath();
    if(convertView == null){
    viewHolder = new ViewHolder();
    convertView = mInflater.inflate(R.layout.grid_group_item, null);
    viewHolder.mImageView = (MyImageView) convertView.findViewById(R.id.group_image);
    viewHolder.mTextViewTitle = (TextView) convertView.findViewById(R.id.group_title);
    viewHolder.mTextViewCounts = (TextView) convertView.findViewById(R.id.group_count);

    //用来监听ImageView的宽和高
    viewHolder.mImageView.setOnMeasureListener(new OnMeasureListener() {

    @Override
    public void onMeasureSize(int width, int height) {
    mPoint.set(width, height);
    }
    });

    convertView.setTag(viewHolder);
    }else{
    viewHolder = (ViewHolder) convertView.getTag();
    viewHolder.mImageView.setImageResource(R.drawable.friends_sends_pictures_no);
    }

    viewHolder.mTextViewTitle.setText(mImageBean.getFolderName());
    viewHolder.mTextViewCounts.setText(Integer.toString(mImageBean.getImageCounts()));
    //给ImageView设置路径Tag,这是异步加载图片的小技巧
    viewHolder.mImageView.setTag(path);

    //利用NativeImageLoader类加载本地图片
    Bitmap bitmap = NativeImageLoader.getInstance().loadNativeImage(path, mPoint, new NativeImageCallBack() {

    @Override
    public void onImageLoader(Bitmap bitmap, String path) {
    ImageView mImageView = (ImageView) mGridView.findViewWithTag(path);
    if(bitmap != null && mImageView != null){
    mImageView.setImageBitmap(bitmap);
    }
    }
    });

    if(bitmap != null){
    viewHolder.mImageView.setImageBitmap(bitmap);
    }else{
    viewHolder.mImageView.setImageResource(R.drawable.friends_sends_pictures_no);
    }

    return convertView;
    }

    public static class ViewHolder{
    public MyImageView mImageView;
    public TextView mTextViewTitle;
    public TextView mTextViewCounts;
    }

    }

    首先我们将每个item的图片路径设置Tag到该ImageView上面,然后利用NativeImageLoader来加载本地图片,但是我们显示的图片的宽和高可能远大于GirdView
    item中ImageView的大小,于是为了节省内存,我们需要对图片进行裁剪,需要对图片裁剪我们利用loadNativeImage(final String
    path, final Point mPoint, final NativeImageCallBack
    mCallBack)方法,我们就必须要获取ImageView的宽和高了

    但是我们想在getView()中获取ImageView的宽和高存在问题,在getView()里面刚开始显示item的时候利用ImageView.getWidth()
    获取的都是0,为什么刚开始获取不到宽和高呢,因为我们使用LayoutInflater来将XML布局文件Inflater()成View的时候,View并没有显示在界面上面,表明并没有对View进行onMeasure(),
    onLayout(),
    onDraw()等操作,必须等到retrue convertView的时候,表示该item对应的View已经绘制在ListView的位置上了, 此时才对item对应的View进行onMeasure(),
    onLayout(),
    onDraw()等操作,这时候才能获取到Item的宽和高,于是我想到了自定义ImageView,在onMeasure()中利用回调的模式主动通知我ImageView测量的宽和高,但是这有一个小小的问题,就是显示GridView的第一个item的时候,获取的宽和高还是0,第二个就能正常获取了,第一个宽和高为0,表示我们不对第一张图片进行裁剪而已,在效率上也没啥问题,不知道大家有没有好的方法,可以在getView()中获取Item中某个控件的宽和高。

    自定义MyImageView的代码,我们只需要设置OnMeasureListener监听,当MyImageView测量完毕之后,就会将测量的宽和高回调到onMeasureSize()中,然后我们可以根据MyImageView的大小来裁剪图片


    package com.example.imagescan;

    import android.content.Context;
    import android.util.AttributeSet;
    import android.widget.ImageView;

    public class MyImageView extends ImageView {
    private OnMeasureListener onMeasureListener;

    public void setOnMeasureListener(OnMeasureListener onMeasureListener) {
    this.onMeasureListener = onMeasureListener;
    }

    public MyImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    }

    public MyImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    //将图片测量的大小回调到onMeasureSize()方法中
    if(onMeasureListener != null){
    onMeasureListener.onMeasureSize(getMeasuredWidth(), getMeasuredHeight());
    }
    }

    public interface OnMeasureListener{
    public void onMeasureSize(int width, int height);
    }

    }

    上面这些代码就完成了第一个界面的功能了,接下来就是点击GridView的item跳转另一个界面来显示该文件夹下面的所有图片,功能跟第一个界面差不多,也是使用GridView来显示图片,第二个界面的布局代码我就不贴了,直接贴上界面的代码


    package com.example.imagescan;

    import java.util.List;

    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.GridView;
    import android.widget.Toast;

    public class ShowImageActivity extends Activity {
    private GridView mGridView;
    private List<String> list;
    private ChildAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.show_image_activity);

    mGridView = (GridView) findViewById(R.id.child_grid);
    list = getIntent().getStringArrayListExtra("data");

    adapter = new ChildAdapter(this, list, mGridView);
    mGridView.setAdapter(adapter);

    }

    @Override
    public void onBackPressed() {
    Toast.makeText(this, "选中 " + adapter.getSelectItems().size() + " item", Toast.LENGTH_LONG).show();
    super.onBackPressed();
    }

    }

    GridView的item上面一个我们自定义的MyImageView用来显示图片,另外还有一个CheckBox来记录我们选中情况,Adapter的代码如下


    package com.example.imagescan;

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Point;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.CheckBox;
    import android.widget.CompoundButton;
    import android.widget.ImageView;
    import android.widget.CompoundButton.OnCheckedChangeListener;
    import android.widget.GridView;

    import com.example.imagescan.MyImageView.OnMeasureListener;
    import com.example.imagescan.NativeImageLoader.NativeImageCallBack;
    import com.nineoldandroids.animation.AnimatorSet;
    import com.nineoldandroids.animation.ObjectAnimator;

    public class ChildAdapter extends BaseAdapter {
    private Point mPoint = new Point(0, 0);//用来封装ImageView的宽和高的对象
    /**
    * 用来存储图片的选中情况
    */
    private HashMap<Integer, Boolean> mSelectMap = new HashMap<Integer, Boolean>();
    private GridView mGridView;
    private List<String> list;
    protected LayoutInflater mInflater;

    public ChildAdapter(Context context, List<String> list, GridView mGridView) {
    this.list = list;
    this.mGridView = mGridView;
    mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
    return list.size();
    }

    @Override
    public Object getItem(int position) {
    return list.get(position);
    }

    @Override
    public long getItemId(int position) {
    return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
    final ViewHolder viewHolder;
    String path = list.get(position);

    if(convertView == null){
    convertView = mInflater.inflate(R.layout.grid_child_item, null);
    viewHolder = new ViewHolder();
    viewHolder.mImageView = (MyImageView) convertView.findViewById(R.id.child_image);
    viewHolder.mCheckBox = (CheckBox) convertView.findViewById(R.id.child_checkbox);

    //用来监听ImageView的宽和高
    viewHolder.mImageView.setOnMeasureListener(new OnMeasureListener() {

    @Override
    public void onMeasureSize(int width, int height) {
    mPoint.set(width, height);
    }
    });

    convertView.setTag(viewHolder);
    }else{
    viewHolder = (ViewHolder) convertView.getTag();
    viewHolder.mImageView.setImageResource(R.drawable.friends_sends_pictures_no);
    }
    viewHolder.mImageView.setTag(path);
    viewHolder.mCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    //如果是未选中的CheckBox,则添加动画
    if(!mSelectMap.containsKey(position) || !mSelectMap.get(position)){
    addAnimation(viewHolder.mCheckBox);
    }
    mSelectMap.put(position, isChecked);
    }
    });

    viewHolder.mCheckBox.setChecked(mSelectMap.containsKey(position) ? mSelectMap.get(position) : false);

    //利用NativeImageLoader类加载本地图片
    Bitmap bitmap = NativeImageLoader.getInstance().loadNativeImage(path, mPoint, new NativeImageCallBack() {

    @Override
    public void onImageLoader(Bitmap bitmap, String path) {
    ImageView mImageView = (ImageView) mGridView.findViewWithTag(path);
    if(bitmap != null && mImageView != null){
    mImageView.setImageBitmap(bitmap);
    }
    }
    });

    if(bitmap != null){
    viewHolder.mImageView.setImageBitmap(bitmap);
    }else{
    viewHolder.mImageView.setImageResource(R.drawable.friends_sends_pictures_no);
    }

    return convertView;
    }

    /**
    * 给CheckBox加点击动画,利用开源库nineoldandroids设置动画
    * @param view
    */
    private void addAnimation(View view){
    float [] vaules = new float[]{0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.25f, 1.2f, 1.15f, 1.1f, 1.0f};
    AnimatorSet set = new AnimatorSet();
    set.playTogether(ObjectAnimator.ofFloat(view, "scaleX", vaules),
    ObjectAnimator.ofFloat(view, "scaleY", vaules));
    set.setDuration(150);
    set.start();
    }

    /**
    * 获取选中的Item的position
    * @return
    */
    public List<Integer> getSelectItems(){
    List<Integer> list = new ArrayList<Integer>();
    for(Iterator<Map.Entry<Integer, Boolean>> it = mSelectMap.entrySet().iterator(); it.hasNext();){
    Map.Entry<Integer, Boolean> entry = it.next();
    if(entry.getValue()){
    list.add(entry.getKey());
    }
    }

    return list;
    }

    public static class ViewHolder{
    public MyImageView mImageView;
    public CheckBox mCheckBox;
    }

    }

Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果,布布扣,bubuko.com

时间: 2024-08-02 02:41:52

Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果的相关文章

android高仿微信UI点击头像显示大图片效果, Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果

http://www.cnblogs.com/Jaylong/archive/2012/09/27/androidUI.html http://blog.csdn.net/xiaanming/article/details/18730223

android 在 ListView 的 item 中插入 GridView 仿微信朋友圈图片显示。

转载请声明出处(http://www.cnblogs.com/linguanh/) 先上张效果图: 1,思路简述 这个肯定是要重写 baseAdapter的了,这里我分了两个数据适配器,一个是自定义的 listView的item 风格xml,另一个是该风格xml文件里面的嵌套的GridView数据适配.然后我们需要两个数据辅助类,类似上述,一个是专门来保存在GridView中要显示的每张图片的信息,例如它的url.name.id等等,暂称该辅助类为 UserImgs,大家可以随便增删,另一个是总

Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果

大家好!过完年回来到现在差不多一个月没写文章了,一是觉得不知道写哪些方面的文章,没有好的题材来写,二是因为自己的一些私事给耽误了,所以过完年的第一篇文章到现在才发表出来,2014年我还是会继续在CSDN上面更新我的博客,欢迎大家关注一下,今天这篇文章主要的是介绍下开源库StickyGridHeaders的使用,StickyGridHeaders是一个自定义GridView带sections和headers的Android库,sections就是GridView item之间的分隔,headers

在InternetExplorer.Application中显示本地图片

忘记了,喜欢一个人的感觉 Demon's Blog  ?  程序设计  ?  在InternetExplorer.Application中显示本地图片 ? 对VBS效率的再思考--处理二进制数据 WordPress判断用户是否登录 ? 在InternetExplorer.Application中显示本地图片 标题: 在InternetExplorer.Application中显示本地图片作者: Demon链接: http://demon.tw/programming/internetexplor

Atitit.&#160;html&#160;使用js显示本地图片的设计方案.doc

Atitit. html 使用js显示本地图片的设计方案.doc 1.  Local mode  是可以的..web模式走有的不能兰.1 2. IE8.0 显示本地图片 img.src=本地图片路径无效的解决方案1 2.1. div来完成 .filter1 2.2. URL.createObjectURL (html5 api  ma sida)2 2.3. Css 背景(吗四大)2 2.4. 这是Data URI scheme (base64).2 3. --code2 4. 参考2 1.  

UIWebView显示本地图片的方法

在UIWebView显示本地图片,由此可借助UIWebView实现图文混排(内容编码成html格式即可). // ViewController.m // // Created by zc on 8/1/14. // Copyright (c) 2014 cuibo. All rights reserved. // #import "ViewController.h" @interface ViewController () <UIWebViewDelegate> @prop

Django在浏览器上显示本地图片, 外部图片

摘自:https://blog.csdn.net/lvluobo/article/details/80945257 url的配置: 如何在浏览器上显示图片呢? Django项目在浏览器上显示本地图片,本来还以为直接放在虚拟机上,开启Django项目就可以访问到了,后来发现并不是这样的简单- 步入正题,如何在浏览器上显示本地图片,关键在于url的配置: url的配置: from django.views.static import serve url(r'^book/(?P<path>.*)$'

Android中Textview显示带html文本【Textview显示本地图片】

Textview可以显示基本的HTML标签 <a href="..."> <b> <big> <blockquote> <br> <cite> <dfn> <div align="..."> <em> <font size="..." color="..." face="..."> <

android开发 实现同时显示png/jpg 等bitmap图片还可以显示gif图片,有效防止OOM

本来使用第三方jar包 GifView.jar  发现使用的时候不能显示png图片,而且多次setgifimage的时候还会OOM: 现在使用了一个新的第三方,demo是别人的, 下载链接:http://files.cnblogs.com/files/feijian/drawable_gif_demo.rar 注意里面需要添加的包