魯班圖片壓縮實(shí)現(xiàn)仿微信九宮格選擇圖片效果

項(xiàng)目開(kāi)發(fā)中碰到了類似微信的圖片選擇肝劲、圖片壓縮及上傳突雪,一開(kāi)始利用一些第三方的進(jìn)行修改闪唆,但是很容就出現(xiàn)內(nèi)存溢出,而有些比較優(yōu)秀的第三方的多半是采用遠(yuǎn)程依賴的方式集成開(kāi)發(fā)的柜与,很難對(duì)源碼進(jìn)行改動(dòng)而達(dá)到自己的需求巧勤,后面在跟大牛的學(xué)習(xí)過(guò)程中,就寫了一個(gè)簡(jiǎn)單的圖片選擇弄匕,已用于項(xiàng)目開(kāi)發(fā)颅悉,并沒(méi)有出現(xiàn)內(nèi)存溢出。
簡(jiǎn)單的對(duì)實(shí)現(xiàn)做一個(gè)說(shuō)明:
1粘茄、圖片壓縮采用的是第三方的魯班圖片壓縮;

魯班圖片壓縮地址:
github:[https://github.com/Curzibn/Luban](https://github.com/Curzibn/Luban)

2秕脓、圖片加載采用的是glide柒瓣;

compile 'com.github.bumptech.glide:glide:3.7.0'

3、圖片展示列表用的是recyclerview實(shí)現(xiàn)的吠架;

compile 'com.android.support:recyclerview-v7:25.3.1'

4芙贫、實(shí)現(xiàn)了多選(可以隨便控制圖片選擇的數(shù)量)、單選傍药、隱藏拍照磺平、刪除、預(yù)覽等功能拐辽;
5拣挪、已對(duì)android6.0讀取和寫入sd權(quán)限做了適配,android7.0訪問(wèn)相機(jī)權(quán)限做了適配俱诸;
效果如下:


1.gif

圖片壓縮效果:
拍照的原圖(大小是2.59M):

2.gif

壓縮的效果(75.33kb):

3.gif

主要代碼實(shí)現(xiàn):

public class MainActivity extends AppCompatActivity {
    private static final int PHOTO_CAMERA = 1000;
    private static final int DELETE_CODE = 1002;
    private final int SELECT_IMAGE_REQUEST = 0x0011;
    private ArrayList<String> mImageList = new ArrayList<>();
    private ArrayList<String> mRuquestList = new ArrayList<>();
    @ViewById(R.id.image_list_rv)
    private RecyclerView imageListRv;
    private RequestAdapter adapter;
    private int maxChoice = 9;

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

        adapter = new RequestAdapter(this, mImageList, maxChoice);
        imageListRv.setLayoutManager(new GridLayoutManager(MainActivity.this, 4));
        imageListRv.setAdapter(adapter);
        //設(shè)置分割線
        imageListRv.addItemDecoration(new DividerGridItemDecoration(MainActivity.this, R.drawable.item_dirver_02));

        adapter.setOnItemClickListener(new ItemClickListener() {
            @Override
            public void onItemClick(Object obj, int position) {
                Log.e("position", "position---->" + position);
                if (mImageList.size() == position) {
                    //動(dòng)態(tài)申請(qǐng)權(quán)限
                    PermissionHelper.with(MainActivity.this).
                            requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}).
                            requestCode(PHOTO_CAMERA).
                            request();
                } else {
                    //跳轉(zhuǎn)至刪除或者預(yù)覽頁(yè)面
                    Intent intent = new Intent(MainActivity.this, PreViewActivity.class);
                    Bundle bundle = new Bundle();
                    bundle.putInt("choicePosition", position);
                    bundle.putSerializable("choiceList", mImageList);
                    intent.putExtras(bundle);
                    startActivity(intent);
                }
            }
        });
        adapter.setOnDeleteClickListener(new DeleteListener() {
            @Override
            public void onDeleteClick(Object obj, int position) {
                removeList(position);
            }
        });

    }

    /**
     * 刪除圖片
     *
     * @param position
     */
    private void removeList(int position) {
        mImageList.remove(position);
        adapter.nodfiyData(mImageList);
    }

    @PermissionSuccess(requestCode = PHOTO_CAMERA)
    private void toSelectImageActivity() {
        ImageSelector
                .create()
                .multi()
                .count(maxChoice)
                .showCamera(true)
                .origin(mImageList)
                .start(this, SELECT_IMAGE_REQUEST);
    }

    /**
     * 圖片壓縮  這里放在網(wǎng)絡(luò)請(qǐng)求之前做好些菠劝,放在onActivityResult里面每次圖片改動(dòng)都要調(diào)用
     * 這里沒(méi)有網(wǎng)絡(luò)請(qǐng)求環(huán)境就放在onActivityResult里面了
     */
    private void compressImg() {
        if (mRuquestList.size() != 0) {
            mRuquestList.clear();
        }
        // 把選擇好的圖片做了一下壓縮
        for (String path : mImageList) {

            // 做優(yōu)化  第一個(gè)decodeFile有可能會(huì)內(nèi)存移除
            // 一般后臺(tái)會(huì)規(guī)定尺寸  800  小米 規(guī)定了寬度 720
            // 上傳的時(shí)候可能會(huì)多張 for循環(huán) 最好用線程池 (2-3)
            Bitmap bitmap = ImageUtil.decodeFile(960, path);
            // 調(diào)用寫好的native方法
            //壓縮存儲(chǔ)的路徑
            String imageViewUrl = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +
                    new File(path).getName();
            // 用Bitmap.compress壓縮1/10
            ImageUtil.compressBitmap(bitmap, 75, imageViewUrl);

            mRuquestList.add(imageViewUrl);
        }
        adapter.nodfiyData(mImageList);
        Log.e("mRuquestList", "mRuquestList----->" + mRuquestList.size());
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_IMAGE_REQUEST && data != null) {
                mImageList = (ArrayList<String>) data.getSerializableExtra(SelectImageActivity.EXTRA_DEFAULT_SELECTED_LIST);
                adapter.nodfiyData(mImageList);
            }
        }
    }

    /**
     * 壓縮點(diǎn)擊事件
     *
     * @param view
     */
    public void tvCompress(View view) {
        compressImageView();
    }

    /**
     * 使用魯班壓縮圖片
     * 在子線程中開(kāi)啟圖片壓縮
     */
    private void compressImageView() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (mRuquestList.size() != 0) {
                    mRuquestList.clear();
                }
                for (String s : mImageList) {
                    if (s == null) {
                        s = "";
                    }
                    File file = new File(s);
                    Luban.with(MainActivity.this)
                            .load(file)//傳入要壓縮的圖片   這里采用的是單張壓縮  也可以采用多張壓縮
                            .ignoreBy(100)   // 忽略不壓縮圖片的大小  如果原圖片小于100kb不會(huì)進(jìn)行壓縮
//                    .putGear(Luban.Builder.)//設(shè)定壓縮檔次,默認(rèn)三擋
                            .setCompressListener(new OnCompressListener() { //設(shè)置回調(diào)
                                @Override
                                public void onStart() {
                                    // TODO 壓縮開(kāi)始前調(diào)用睁搭,可以在方法內(nèi)啟動(dòng) loading UI
                                }

                                @Override
                                public void onSuccess(File file) {
                                    // TODO 壓縮成功后調(diào)用赶诊,返回壓縮后的圖片文件
                                    String absolutePath = file.getAbsolutePath();
                                    mRuquestList.add(absolutePath);
                                }

                                @Override
                                public void onError(Throwable e) {
                                    // TODO 當(dāng)壓縮過(guò)程出現(xiàn)問(wèn)題時(shí)調(diào)用
                                }
                            }).launch();    //啟動(dòng)壓縮
                }
            }
        }).start();

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionHelper.requestPermissionsResult(this, requestCode, permissions, grantResults);
    }
}

MainActivity類中主要是讀取和寫入sd卡權(quán)限的申請(qǐng)笼平、選擇圖片的入口函數(shù)、選擇圖片后的展示舔痪、圖片刪除寓调、圖片預(yù)覽入口、圖片壓縮等锄码。

public class RequestAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private ArrayList<String> mRequestList;
    private int mMaxNumber;
    private Context mContext;
    public  RequestAdapter(Context context,ArrayList<String> requestList,int maxNumber){
        this.mContext=context;
        this.mMaxNumber=maxNumber;
        this.mRequestList = new ArrayList<String>();
        if(mRequestList!=null)
        {
            this.mRequestList.addAll(requestList);
        }
    }
    public void nodfiyData(List<String> list){
        if(list!=null)
        {
            this.mRequestList.clear();
            this.mRequestList.addAll(list);
        }
        notifyDataSetChanged();
    }
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.request_chooser_item, parent, false);
        return new Holder(view);
    }

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
        Holder holder = (Holder) viewHolder;
        if(position==mRequestList.size()){
            holder.ivDelete.setVisibility(View.GONE);
            int resourceId = R.drawable.icon_addpic_unfocused;
            //顯示圖片 利用Glide centerCrop()
            Glide.with(mContext).load(resourceId).centerCrop().into(holder.image);
            if(position==mMaxNumber){
                holder.image.setVisibility(View.GONE);
            }
        }else{
            holder.ivDelete.setVisibility(View.VISIBLE);
            //顯示圖片 利用Glide centerCrop()
            Glide.with(mContext).load(mRequestList.get(position)).centerCrop().into(holder.image);
        }
        //條目點(diǎn)擊事件
        if(mItemClickListener!=null){
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(position==mMaxNumber){
                        return;
                    }
                    if(mRequestList.size()==position){
                        mItemClickListener.onItemClick("",position);
                    }else {
                        mItemClickListener.onItemClick(mRequestList.get(position), position);
                    }
                }
            });
        }
        if(mItemDeleteListener!=null){
            holder.ivDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mItemDeleteListener.onDeleteClick(mRequestList.get(position), position);
                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return mRequestList.size()+1;
    }
    class Holder extends RecyclerView.ViewHolder{
        SquareImageView image;
        ImageView ivDelete;

        public Holder(View itemView) {
            super(itemView);
            image = (SquareImageView) itemView.findViewById(R.id.image_show);
            ivDelete= (ImageView) itemView.findViewById(R.id.iv_delete);
        }
    }
    //使用接口回調(diào)點(diǎn)擊事件
    private ItemClickListener mItemClickListener;
    public void setOnItemClickListener(ItemClickListener itemClickListener){
        this.mItemClickListener=itemClickListener;
    }
    //使用接口回調(diào)點(diǎn)擊事件
    private DeleteListener mItemDeleteListener;
    public void setOnDeleteClickListener(DeleteListener itemDeleteListener){
        this.mItemDeleteListener=itemDeleteListener;
    }
}

RequestAdapter是MainActivity類中RecyclerView的列表適配器夺英,主要是根據(jù)position和選擇圖片的數(shù)量來(lái)顯示圖片和“+”選擇更多、刪除圖片巍耗、圖片點(diǎn)擊的一些回調(diào)秋麸。

public class SelectImageActivity extends AppCompatActivity implements View.OnClickListener{
    //相機(jī)
    public static final String EXTRA_SHOW_CAMERA = "EXTRA_SHOW_CAMERA";
    //選擇張數(shù)
    public static final String EXTRA_SELECT_COUNT = "EXTRA_SELECT_COUNT";
    //原始的圖片路徑
    public static final String EXTRA_DEFAULT_SELECTED_LIST = "EXTRA_DEFAULT_SELECTED_LIST";
    //選擇的模式
    public static final String EXTRA_SELECT_MODE = "EXTRA_SELECT_MODE";
    //返回選擇圖片的列表
    public static final String EXTRA_RESULT = "EXTRA_RESULT";
    //多選
    public static final int MODE_MULTI = 0x0011;
    //單選
    public static final int MODE_SINGLE = 0x0012;
    private static final int LOADER_TYPE = 0x0021;
    private static final int REQUEST_CAMERA = 0x0022;
    private static final int PHOTO_CAMERA = 1002;
    private static final int PREVIEW_CODE = 1003;
    //單選或多選
    private int mMode = MODE_MULTI;
    //選擇圖片的張數(shù)
    private int mMaxCount = 9;
    //是否顯示拍照按鈕
    private boolean mShowCamera = true;
    //選擇圖片的list
    private ArrayList<String> mResultList;
    @ViewById(R.id.btn_back)
    private ImageView btnBack;
    @ViewById(R.id.image_list_rv)
    private RecyclerView imageListRv;
    //預(yù)覽
    @ViewById(R.id.select_preview)
    private TextView selectPreview;
    @ViewById(R.id.select_num)
    private TextView selectNum;
    @ViewById(R.id.select_finshi)
    private TextView selectFinshi;
    private File mTempFile;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_select_image);
        ViewUtils.inject(this);
        initData();


    }

    /**
     * 初始化本地?cái)?shù)據(jù)
     */
    private void initImageList() {
        //獲取本地圖片  耗時(shí)操作
        getLoaderManager().initLoader(LOADER_TYPE, null, mLoaderCallBack);

    }

    private LoaderManager.LoaderCallbacks<Cursor> mLoaderCallBack = new LoaderManager.LoaderCallbacks<Cursor>() {
        private final String[] IMAGE_PROJECTION = {
                MediaStore.Images.Media.DATA,
                MediaStore.Images.Media.DISPLAY_NAME,
                MediaStore.Images.Media.DATE_ADDED,
                MediaStore.Images.Media.MIME_TYPE,
                MediaStore.Images.Media.SIZE,
                MediaStore.Images.Media._ID,

        };

        @Override
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            CursorLoader cursorLoader = new CursorLoader(SelectImageActivity.this,
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    IMAGE_PROJECTION, IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[3] + "=? OR "
                    + IMAGE_PROJECTION[3] + "=? ",
                    new String[]{"image/jpeg", "image/png"},
                    IMAGE_PROJECTION[2] + " DESC");
            return cursorLoader;
        }

        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
            //如果有數(shù)據(jù)變化
            if (data != null && data.getCount() > 0) {
                ArrayList<String> images = new ArrayList<>();
                //如果需要顯示拍照就添加一條空數(shù)據(jù)
                if (mShowCamera) {
                    //封裝數(shù)據(jù)對(duì)象
//                    ImageEntity photoImage = new ImageEntity("", "", 0);
                    images.add("");
                }
                //不斷遍歷循環(huán)
                while (data.moveToNext()) {
                    String path = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
//                    String name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
//                    long dateTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));
//                    Log.e("TAG", path + " " + name + " " + dateTime);
//                    //判斷文件是否存在
//                    if (!pathExist(path)) {
//                        continue;
//                    }
//                    Log.e("TAG", path + " " + name + " " + dateTime);
                    //封裝數(shù)據(jù)對(duì)象
//                    ImageEntity image = new ImageEntity(path, name, dateTime);
                    images.add(path);
                }
                //顯示列表數(shù)據(jù)
                showListData(images);
            }
        }

        /**
         * 判斷文件是否存在
         *
         * @param path
         * @return
         */
        private boolean pathExist(String path) {
            if (!TextUtils.isEmpty(path)) {
                return new File(path).exists();
            }
            return false;
        }

        @Override
        public void onLoaderReset(Loader<Cursor> loader) {

        }
    };


    /**
     * 顯示列表數(shù)據(jù)
     *
     * @param images
     */
    private void showListData(ArrayList<String> images) {
        SelectImageAdapter adapter = new SelectImageAdapter(SelectImageActivity.this, images, mResultList,mMaxCount, R.layout.media_chooser_item);
        imageListRv.setLayoutManager(new GridLayoutManager(SelectImageActivity.this, 4));
        imageListRv.setAdapter(adapter);
        //設(shè)置分割線
        imageListRv.addItemDecoration(new DividerGridItemDecoration(SelectImageActivity.this,R.drawable.item_dirver_01));
        adapter.setOnSelectImageListener(new SelectImageListener() {
            @Override
            public void select(int number) {
                exchangViewShow(number);
            }
        });
        //拍照回調(diào)
        adapter.setTakePhotoListener(new TakePhotoListener() {
            @Override
            public void takePhoto() {
                //動(dòng)態(tài)申請(qǐng)權(quán)限
                PermissionHelper.with(SelectImageActivity.this).
                        requestPermission(new String[]{Manifest.permission.CAMERA}).
                        requestCode(PHOTO_CAMERA).
                        request();
            }
        });
    }

    /**
     * 拍照這里要做Android6.0以下 Android6.0和Android7.0以上的適配
     */
    @PermissionSuccess(requestCode = PHOTO_CAMERA)
    private void takePhoto(){
        mTempFile=new File(getInnerSDCardPath(), "imagephoto" + SystemClock.currentThreadTimeMillis() + ".jpg");
        if (!mTempFile.getParentFile().exists()){
            mTempFile.getParentFile().mkdirs();
        }
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            //Android7.0 com.picchoice替換成自己的包名
            Uri imageUri = FileProvider.getUriForFile(SelectImageActivity.this, "com.picchoice.fileprovider", mTempFile);//通過(guò)FileProvider創(chuàng)建一個(gè)content類型的Uri
            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加這一句表示對(duì)目標(biāo)應(yīng)用臨時(shí)授權(quán)該Uri所代表的文件
            intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//設(shè)置Action為拍照
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//將拍取的照片保存到指定URI
            startActivityForResult(intent,REQUEST_CAMERA);
        }else {
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile));
            startActivityForResult(intent, REQUEST_CAMERA);
        }
//        File file=new File(Environment.getExternalStorageDirectory(), "/temp/"+System.currentTimeMillis() + ".jpg");
    }
    /**
     * 獲取內(nèi)置SD卡路徑
     * @return
     */
    public String getInnerSDCardPath() {
        return Environment.getExternalStorageDirectory().getPath();
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionHelper.requestPermissionsResult(this,requestCode,permissions,grantResults);
    }
    @Click({R.id.btn_back,R.id.select_finshi})
    private void Click(View view) {
        switch (view.getId()) {
            case R.id.btn_back:
                finish();
                break;
            case R.id.select_finshi://確定
                Intent intent=new Intent();
                Bundle bundle=new Bundle();
                bundle.putSerializable(SelectImageActivity.EXTRA_DEFAULT_SELECTED_LIST,mResultList);
                intent.putExtras(bundle);
                setResult(RESULT_OK,intent);
                finish();
                break;
        }
    }

    /**
     * 獲取傳遞過(guò)來(lái)的參數(shù)
     */
    private void initData() {
        Intent intent = getIntent();
        mMode = intent.getIntExtra(EXTRA_SELECT_MODE, mMode);
        mMaxCount = intent.getIntExtra(EXTRA_SELECT_COUNT, mMaxCount);
        mShowCamera = intent.getBooleanExtra(EXTRA_SHOW_CAMERA, mShowCamera);
        mResultList = (ArrayList<String>) intent.getSerializableExtra(EXTRA_DEFAULT_SELECTED_LIST);
        if (mResultList == null) {
            mResultList = new ArrayList<>();
        }
        //初始化本地?cái)?shù)據(jù)
        initImageList();
        //改變顯示
        exchangViewShow(mResultList.size());
    }

    /**
     * 改變顯示
     */
    private void exchangViewShow(int numder) {
        if (numder> 0) {
            selectPreview.setTextColor(Color.parseColor("#FF4081"));
            selectFinshi.setTextColor(Color.parseColor("#FF4081"));
            selectPreview.setEnabled(true);
            selectPreview.setOnClickListener(this);
        } else {
            selectPreview.setTextColor(Color.parseColor("#ffffff"));
            selectFinshi.setTextColor(Color.parseColor("#ffffff"));
            selectPreview.setEnabled(false);
            selectPreview.setOnClickListener(null);
        }
        selectNum.setText(numder + "/" + mMaxCount);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.select_preview://預(yù)覽
                //跳轉(zhuǎn)至刪除或者預(yù)覽頁(yè)面
                Intent intent=new Intent(SelectImageActivity.this,PreViewActivity.class);
                Bundle bundle=new Bundle();
                bundle.putInt("choicePosition",0);
                bundle.putSerializable("choiceList",mResultList);
                intent.putExtras(bundle);
                startActivity(intent);
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //第一個(gè)要把圖片添加到集合
        //調(diào)用Click方法
        //通知系統(tǒng)本地有圖片改變了  下次進(jìn)來(lái)可以找到這張圖片
        if(resultCode==RESULT_OK){
            if(requestCode==REQUEST_CAMERA){
                sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(mTempFile)));
                mResultList.add(mTempFile.getAbsolutePath());
                setResult();
            }
        }
    }

    /**
     * 設(shè)置返回結(jié)果
     */
    private void setResult(){
        Intent intent=new Intent();
        Bundle bundle=new Bundle();
//        bundle.putSerializable(EXTRA_RESULT,mResultList);//EXTRA_DEFAULT_SELECTED_LIST
        bundle.putSerializable(EXTRA_DEFAULT_SELECTED_LIST,mResultList);
        intent.putExtras(bundle);
        setResult(RESULT_OK,intent);
        //關(guān)閉當(dāng)前頁(yè)面
        finish();
    }
}

SelectImageActivity類主要是獲取系統(tǒng)sd里面的圖片并展示跌榔、android7.0訪問(wèn)相機(jī)適配催跪、相機(jī)拍照后圖片的刷新和保存等疾层。

public class SelectImageAdapter extends RecyclerCommonAdapter<String> {
    private Context mContext;
    private List<String> imageList;
    private int mMaxCount;

    public SelectImageAdapter(Context context, List<String> data, List<String> choice, int maxCount, int layoutId) {
        super(context, data, layoutId);
        this.mContext = context;
        this.imageList = choice;
        this.mMaxCount = maxCount;
    }

    @Override
    protected void bindData(ViewHolder holder, final String mPath, final int position) {
        if (TextUtils.isEmpty(mPath)) {
            //顯示拍照
            holder.setViewVisibility(R.id.camear_ll, View.VISIBLE);
            holder.setViewVisibility(R.id.media_selected_indicator, View.INVISIBLE);
            holder.setViewVisibility(R.id.image_show, View.INVISIBLE);
            //拍照
            holder.getView(R.id.camear_ll).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //調(diào)用拍照
                    if(takePhotoListener!=null){
                        takePhotoListener.takePhoto();
                    }
                }
            });
        } else {
            //顯示圖片
            holder.setViewVisibility(R.id.camear_ll, View.INVISIBLE);
            holder.setViewVisibility(R.id.media_selected_indicator, View.VISIBLE);
            holder.setViewVisibility(R.id.image_show, View.VISIBLE);
            SquareImageView image = holder.getView(R.id.image_show);
            //顯示圖片 利用Glide centerCrop()
            Glide.with(mContext).load(mPath).centerCrop().into(image);
            ImageView selectImageView = holder.getView(R.id.media_selected_indicator);
            if (imageList.contains(mPath)) {
                //設(shè)置勾選圖片
                selectImageView.setSelected(true);
            } else {
                selectImageView.setSelected(false);
            }
            //給條目添加點(diǎn)擊事件
            image.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //沒(méi)有就加入集合
                    if (!imageList.contains(mPath)) {
                        if (imageList.size() >= mMaxCount) {
                            Toast.makeText(mContext, "最多只能選擇" + mMaxCount + "張圖片", Toast.LENGTH_LONG).show();
                            return;
                        }
                        imageList.add(mPath);
                    } else {
                        //有就移除
                        imageList.remove(mPath);
                    }
                    //刷新數(shù)據(jù)
                    notifyDataSetChanged();
                    //通知顯示布局
                    if (selectImageListener != null) {
                        selectImageListener.select(imageList.size());
                    }
                }
            });
        }
    }

    private SelectImageListener selectImageListener;

    public void setOnSelectImageListener(SelectImageListener listener) {
        this.selectImageListener = listener;
    }
    private TakePhotoListener takePhotoListener;

    public void setTakePhotoListener(TakePhotoListener listener) {
        this.takePhotoListener = listener;
    }
}

SelectImageAdapter類是SelectImageActivity類中RecyclerView的適配器趾诗,展示系統(tǒng)sd獲取的圖片卒稳、控制圖片選擇的數(shù)量等粘姜。

public class PreViewActivity extends AppCompatActivity implements View.OnClickListener {
    @ViewById(R.id.btn_back)
    private ImageView btnBack;
    @ViewById(R.id.viewpager)
    private ViewPager viewpager;

    private List<String> choiceList;
    private DeleteAdapter adapter;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_delete);
        ViewUtils.inject(this);
        choiceList = (List<String>) getIntent().getSerializableExtra("choiceList");
        if(choiceList==null){
            choiceList=new ArrayList<>();
        }

        adapter=new DeleteAdapter(getSupportFragmentManager());
        viewpager.setAdapter(adapter);

        btnBack.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_back:
                finish();
                break;
        }
    }
    class DeleteAdapter extends FragmentPagerAdapter{
        public DeleteAdapter(FragmentManager fm) {
            super(fm);

        }

        @Override
        public Fragment getItem(int position) {
            return ImageViewFragment.newInstance(choiceList.get(position));
        }

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

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            super.destroyItem(container, position, object);
        }
    }
}
public class ImageViewFragment extends Fragment{
    public static ImageViewFragment newInstance(String item){
        ImageViewFragment fragment=new ImageViewFragment();
        Bundle bundle=new Bundle();
        bundle.putString("url",item);
        fragment.setArguments(bundle);
        return fragment;
    }
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_imageview, container, false);
        ImageView image = (ImageView) view.findViewById(R.id.image);
        Bundle bundle = getArguments();
        String url = bundle.getString("url");
        if(url==null){
            url="";
        }
        int screenWidth = getW(getActivity());

        Bitmap diskBitmap = getDiskBitmap(url);
        if(diskBitmap!=null){
            //獲取Bitmap的寬高
            int width = diskBitmap.getWidth();
            int height = diskBitmap.getHeight();

            //根據(jù)Bitmap的寬高和屏幕的寬高重新設(shè)置imageview顯示的大小
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) image.getLayoutParams();
            layoutParams.width=screenWidth;
            layoutParams.height=screenWidth*height/width;

            image.setLayoutParams(layoutParams);
        }
        //顯示圖片 利用Glide centerCrop()
        Glide.with(this).load(url).centerCrop().into(image);
        return view;
    }

    /**
     * 根據(jù)url獲取一個(gè)bitmap對(duì)象
     * @param pathString  圖片路徑
     * @return  返回對(duì)應(yīng)的Bitmap對(duì)象
     */
    private Bitmap getDiskBitmap(String pathString) {
        Bitmap bitmap = null;
        try
        {
            File file = new File(pathString);
            if(file.exists()) {
                bitmap = BitmapFactory.decodeFile(pathString);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return bitmap;
    }
    /*
     * 獲取屏幕的寬度
     */
    private int getW(Context context){
        DisplayMetrics dm = new DisplayMetrics();
        WindowManager windowMgr = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        windowMgr.getDefaultDisplay().getMetrics(dm);
        return dm.widthPixels;
    }
}

PreViewActivity類和ImageViewFragment類是圖片預(yù)覽宰翅,這里的圖片預(yù)覽效果做的不是很好穴墅,可以根據(jù)自己的需要進(jìn)行修改霎迫。

public class ImageSelector {
    //選擇圖片張數(shù)
    private int mMaxCount = 9;
    //選擇圖片的模式
    private int mMode = SelectImageActivity.MODE_MULTI;
    //是否顯示拍照的相機(jī)
    private boolean mShowCamera = true;
    //原始的圖片
    private ArrayList<String> mOriginData;

    private ImageSelector() {

    }

    public static ImageSelector create() {
        return new ImageSelector();
    }

    /**
     * 單選模式
     *
     * @return
     */
    public ImageSelector single() {
        mMode = SelectImageActivity.MODE_SINGLE;
        return this;
    }

    /**
     * 多選模式
     *
     * @return
     */
    public ImageSelector multi() {
        mMode = SelectImageActivity.MODE_MULTI;
        return this;
    }

    /**
     * 設(shè)置可以選擇的圖片張數(shù)
     *
     * @param count
     * @return
     */
    public ImageSelector count(int count) {
        mMaxCount = count;
        return this;
    }

    /**
     * 是否顯示相機(jī)
     *
     * @param showCamera
     * @return
     */
    public ImageSelector showCamera(boolean showCamera) {
        mShowCamera = showCamera;
        return this;
    }

    /**
     * 選擇好的圖片
     *
     * @param originList
     * @return
     */
    public ImageSelector origin(ArrayList<String> originList) {
        this.mOriginData = originList;
        return this;

    }

    /**
     * 啟動(dòng)requestCode
     *
     * @param activity
     * @param requestCode
     */
    public void start(Activity activity, int requestCode) {
        Intent intent = new Intent(activity, SelectImageActivity.class);
        addParmasByIntent(intent);
        activity.startActivityForResult(intent, requestCode);
    }

    /**
     * 啟動(dòng)requestCode
     *
     * @param fragment
     * @param requestCode
     */
    public void start(Fragment fragment, int requestCode) {
        Intent intent = new Intent(fragment.getContext(), SelectImageActivity.class);
        addParmasByIntent(intent);
        fragment.startActivityForResult(intent, requestCode);
    }

    /**
     * 設(shè)置參數(shù)
     *
     * @param intent
     */
    private void addParmasByIntent(Intent intent) {
        Bundle bundle = new Bundle();
        bundle.putInt(SelectImageActivity.EXTRA_SELECT_COUNT, mMaxCount);
        bundle.putInt(SelectImageActivity.EXTRA_SELECT_MODE, mMode);
        bundle.putBoolean(SelectImageActivity.EXTRA_SHOW_CAMERA, mShowCamera);
        if (mOriginData != null && mMode == SelectImageActivity.MODE_MULTI) {
            bundle.putSerializable(SelectImageActivity.EXTRA_DEFAULT_SELECTED_LIST, mOriginData);
        }
        intent.putExtras(bundle);
    }
}

ImageSelector類是一個(gè)工具類斋枢,里面提供了設(shè)置圖片多選還是單選,選擇圖片的數(shù)量知给,是否顯示相機(jī)等瓤帚。

上面這些就是實(shí)現(xiàn)的主要代碼,下面會(huì)提供源碼涩赢,可以根據(jù)自己的需要對(duì)源碼進(jìn)行修改戈次。

源碼地址:
http://pan.baidu.com/s/1bp50kLT

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市筒扒,隨后出現(xiàn)的幾起案子怯邪,更是在濱河造成了極大的恐慌,老刑警劉巖花墩,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悬秉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡冰蘑,警方通過(guò)查閱死者的電腦和手機(jī)和泌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)祠肥,“玉大人允跑,你說(shuō)我怎么就攤上這事。” “怎么了聋丝?”我有些...
    開(kāi)封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵索烹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我弱睦,道長(zhǎng)百姓,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任况木,我火速辦了婚禮垒拢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘火惊。我一直安慰自己求类,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布屹耐。 她就那樣靜靜地躺著尸疆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惶岭。 梳的紋絲不亂的頭發(fā)上寿弱,一...
    開(kāi)封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音按灶,去河邊找鬼症革。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鸯旁,可吹牛的內(nèi)容都是我干的噪矛。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼铺罢,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼艇挨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起畏铆,我...
    開(kāi)封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤雷袋,失蹤者是張志新(化名)和其女友劉穎吉殃,沒(méi)想到半個(gè)月后辞居,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蛋勺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年瓦灶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抱完。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贼陶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情碉怔,我是刑警寧澤烘贴,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站撮胧,受9級(jí)特大地震影響桨踪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芹啥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一锻离、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧墓怀,春花似錦汽纠、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至啤呼,卻和暖如春卧秘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背官扣。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工翅敌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惕蹄。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓蚯涮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親卖陵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子遭顶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容