Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 仿微信圖片選擇器

仿微信圖片選擇器

編輯:關於Android編程

仿微信圖片選擇器

源碼下載連接:

先上圖,後上代碼:
\

打開app後點擊添加圖片按鈕:

獲取選擇的圖片 並返回在gridview中:
這裡寫圖片描述
實現該功能的重要組成部分有:利用gridview加載本地圖片,gridView控件的使用,Intent之間數據的傳遞,和利用ContentProvider獲取圖片,和PZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcHVwV2luZG93ta+z9tKzw+a1xMq508OjrMD708NCaXRtYXC94r72T09NzsrM4qGjPC9wPg0KPHA+z8LD5r+qyrzM+bP2tPrC66O6PGJyIC8+DQpNYWluQWN0aXZpdHnOxLz+tcS0+sLryOfPwqO6PGJyIC8+DQpgaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7PGJyIC8+DQppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7PGJyIC8+DQppbXBvcnQgamF2YS51dGlsLkxpc3Q7PC9wPg0KPHA+aW1wb3J0IGFuZHJvaWQuYXBwLkFjdGl2aXR5OzxiciAvPg0KaW1wb3J0IGFuZHJvaWQuY29udGVudC5JbnRlbnQ7PGJyIC8+DQppbXBvcnQgYW5kcm9pZC5ncmFwaGljcy5CaXRtYXA7PGJyIC8+DQppbXBvcnQgYW5kcm9pZC5ncmFwaGljcy5CaXRtYXBGYWN0b3J5OzxiciAvPg0KaW1wb3J0IGFuZHJvaWQub3MuQnVuZGxlOzxiciAvPg0KaW1wb3J0IGFuZHJvaWQudXRpbC5Mb2c7PGJyIC8+DQppbXBvcnQgYW5kcm9pZC52aWV3LlZpZXc7PGJyIC8+DQppbXBvcnQgYW5kcm9pZC52aWV3LldpbmRvdzs8YnIgLz4NCmltcG9ydCBhbmRyb2lkLndpZGdldC5CdXR0b247PGJyIC8+DQppbXBvcnQgYW5kcm9pZC53aWRnZXQuRWRpdFRleHQ7PGJyIC8+DQppbXBvcnQgYW5kcm9pZC53aWRnZXQuR3JpZFZpZXc7PGJyIC8+DQppbXBvcnQgYW5kcm9pZC53aWRnZXQuSW1hZ2VCdXR0b247PGJyIC8+DQppbXBvcnQgYW5kcm9pZC53aWRnZXQuSW1hZ2VWaWV3OzxiciAvPg0KaW1wb3J0IGFuZHJvaWQud2lkZ2V0LlNpbXBsZUFkYXB0ZXI7PGJyIC8+DQppbXBvcnQgYW5kcm9pZC53aWRnZXQuU2ltcGxlQWRhcHRlci5WaWV3QmluZGVyOzxiciAvPg0KaW1wb3J0IGFuZHJvaWQud2lkZ2V0LlRvYXN0OzwvcD4NCjxwPnB1YmxpYyBjbGFzcyBNYWluQWN0aXZpdHkgZXh0ZW5kcyBBY3Rpdml0eSB7PC9wPg0KPHByZSBjbGFzcz0="brush:java;"> 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 shuju = new ArrayList(); 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(); 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 mImags;

    /**
     * list存放掃描到的文件夾的信息
     */
    private List imageFolders = new ArrayList();
    /**
     * hashset  基於hashmap實現的,利用他可以防止一個文件夾  多次掃描
     */
    private HashSet mImagePath = new HashSet();

    //彈出對話框  進度條
    private ProgressDialog mprogressDialog;

    private TextView textview_ChooseDir;
    private TextView textview_ImageCount;

    //定義屏幕的高度
    private int screenHeight = 0;

    /**
     * 用戶選擇的圖片,存儲為圖片的完整路徑
     */
    public static List mSelectedImage = new LinkedList();
    private ArrayList 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();
            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();
                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 {

        /**
         * 文件夾路徑
         */
        private String mDirPath;

        public MyAdapter(Context context, List 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 
 */

public abstract class CommonAdapter extends BaseAdapter {
    protected LayoutInflater mInflater;
    protected Context mContext;
    protected List mDatas;
    protected final int mItemLayoutId;

    public CommonAdapter(Context context, List 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 mLinkedHashMap = Collections.synchronizedMap(new LinkedHashMap(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 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 mLruCache;
    /**
     * 線程池
     */
    private ExecutorService mThreadPool;
    /**
     * 線程池的線程數量,默認為1
     */
    private int mThreadCount = 1;
    /**
     * 隊列的調度方式
     */
    private Type mType = Type.LIFO;
    /**
     * 任務隊列
     */
    private LinkedList 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(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();
        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 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(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{

    private ListView mListDir;

    public List_File_PopWind(int width, int height,
                                   List datas, View convertView) {
        super(convertView, width, height, true, datas);
    }

    @Override
    public void initViews() {
        mListDir = (ListView) findViewById(R.id.listviwe_dir);
        mListDir.setAdapter(new CommonAdapter(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 extends PopupWindow {
    /**
     * 布局文件的最外層View
     */
    protected View mContentView;
    protected Context context;
    /**
     * ListView的數據集
     */
    protected List 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 mDatas) {
        this(contentView, width, height, focusable, mDatas, new Object[0]);

    }

    public BasePopupWindowForListView(View contentView, int width, int height,
                                      boolean focusable, List 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 paths;
    private int size;
    private ImageShowManager imageManager;
    private LayoutInflater li;

    public PopRecommend_ImageAdd_Adapter(Activity a, ArrayList 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 {

        private final WeakReference imageViewReference;
        private String url = null;

        public AsyncLoadImageTask(ImageView imageview) {
            super();
            imageViewReference = new WeakReference(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 loadImageTaskReference;

        public LoadingDrawable(AsyncLoadImageTask loadImageTask) {
            super(Color.BLUE);
            loadImageTaskReference = new WeakReference(
                    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 mViews;
    private int mPosition;
    private View mConvertView;

    private ViewHolder(Context context, ViewGroup parent, int layoutId,
                       int position) {
        this.mPosition = position;
        this.mViews = new SparseArray();
        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 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文件:定義彈出窗口的劃入劃出方式:





    
    





    
    

mybutton.xml按鈕形狀設置:



    
        
            
            
        
    
    
        
            

            
        
    


myedittext.xml 輸入框的邊框設置




    

    
    
    

    

    

下面給出demo中使用的布局文件
activity_image_add.xml




    
        
        

        

        

        

    
    
        

        
        

            

            
        

    



activity_main.xml




    

        

        

            

            

            
        

        

        

            

            

                

            


            

            

item_gridview_imageadd.xml




    

    

item_gridview_poprecommend.xml




    

        
    

list_dir_item.xml




    

    

        

        
    

    

list_dir.xml



    
    

 

最後別忘了給整個demo加入權限設置:


    
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved