一個(gè)非常好用的Android圖片選擇框架

前言

幾乎每個(gè)APP都需要圖片選擇和裁剪功能悍募,因?yàn)樯婕暗较鄼C(jī)和存儲(chǔ)茫虽,所以該功能還是要考慮很多兼容性的元咙。這也是github上有一大堆圖片選擇框架的原因示启,但是你會(huì)發(fā)現(xiàn)github上找的圖片選擇框架并不是簡(jiǎn)單的只有圖片選擇, 它還包含視頻選擇蒋失、視頻錄制返帕、圖片壓縮等等一大堆功能。其實(shí)你只需要一個(gè)頭像選擇的功能篙挽,那些框架很多功能你根本用不到荆萤,而且代碼至少也幾十個(gè)類,后期有問(wèn)題改起來(lái)也是麻煩事铣卡。所以我就封裝了一個(gè)代碼及其簡(jiǎn)潔的圖片選擇框架链韭,沒(méi)有任何多余的功能,涉及的主要功能類只有3個(gè)煮落,使用也是非常簡(jiǎn)單敞峭。

效果圖如下:
效果圖.jpg

功能特點(diǎn)

  • 支持通過(guò)拍照獲取圖片
  • 支持通過(guò)相冊(cè)獲取圖片
  • 支持圖片裁剪
  • 支持仿IOS底部彈出選擇菜單ActionSheet效果
  • 支持6.0動(dòng)態(tài)授予權(quán)限
  • 解決圖片有黑邊問(wèn)題
  • 解決7.0調(diào)用相機(jī)報(bào)FileUriExposedException的問(wèn)題
  • 解決小米miui系統(tǒng)調(diào)用系統(tǒng)裁剪圖片功能crash問(wèn)題

使用

Step 1. 添加JitPack倉(cāng)庫(kù)

在項(xiàng)目的build.gradle添加JitPack倉(cāng)庫(kù)

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}
Step 2. 添加依賴

在需要使用的module中添加依賴(最新版本見(jiàn) PictureSelector

dependencies {
    compile 'com.github.wildma:PictureSelector:1.1.1'
}

或者引用本地lib

compile project(':pictureselector')
Step 3. 拍照或者從相冊(cè)選擇圖片
        /**
         * create()方法參數(shù)一是上下文,在activity中傳activity.this蝉仇,在fragment中傳fragment.this儡陨。參數(shù)二為請(qǐng)求碼,用于結(jié)果回調(diào)onActivityResult中判斷
         * selectPicture()方法參數(shù)分別為 是否裁剪量淌、裁剪后圖片的寬(單位px)骗村、裁剪后圖片的高、寬比例呀枢、高比例胚股。都不傳則默認(rèn)為裁剪,寬200裙秋,高200琅拌,寬高比例為1:1。
         */
        PictureSelector
                .create(MainActivity.this, PictureSelector.SELECT_REQUEST_CODE)
                .selectPicture(true, 200, 200, 1, 1);

Step 4. 獲取裁剪后的圖片地址
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        /*結(jié)果回調(diào)*/
        if (requestCode == PictureSelector.SELECT_REQUEST_CODE) {
            if (data != null) {
                String picturePath = data.getStringExtra(PictureSelector.PICTURE_PATH);
            }
        }
    }

代碼

每個(gè)類的注釋我都寫(xiě)的很清楚了摘刑,所以這里只貼出主要的圖片工具類进宝,其他可以到我的Github上查看源碼(見(jiàn)文末)。

選擇圖片工具類
package com.wildma.pictureselector;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;


/**
 * Author       wildma
 * Github       https://github.com/wildma
 * CreateDate   2018/6/10
 * Desc         ${選擇圖片工具類}
 * 使用方法:
 * 1. 調(diào)用getByCamera()枷恕、getByAlbum()可通過(guò)拍照或相冊(cè)獲取圖片
 * 2. 在onActivityResult中調(diào)用本工具類的onActivityResult方法處理通過(guò)相冊(cè)或拍照獲取的圖片
 */
public class PictureSelectUtils {

    public static final int GET_BY_ALBUM  = 0x11;//相冊(cè)標(biāo)記
    public static final int GET_BY_CAMERA = 0x12;//拍照標(biāo)記
    public static final int CROP          = 0x13;//裁剪標(biāo)記
    private static Uri takePictureUri;//拍照?qǐng)D片uri
    public static Uri cropPictureTempUri;//裁剪圖片uri

    /**
     * 通過(guò)相冊(cè)獲取圖片
     * @param activity
     */
    public static void getByAlbum(Activity activity) {
        Intent intent = new Intent(Intent.ACTION_PICK,
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.setType("image/*");
        activity.startActivityForResult(intent, GET_BY_ALBUM);
    }

    /**
     * 通過(guò)拍照獲取圖片
     * @param activity
     */
    public static void getByCamera(Activity activity) {
        takePictureUri = createImagePathUri(activity);
        if (takePictureUri != null) {
            Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            i.putExtra(MediaStore.EXTRA_OUTPUT, takePictureUri);//輸出路徑(拍照后的保存路徑)
            activity.startActivityForResult(i, GET_BY_CAMERA);
        } else {
            Toast.makeText(activity, "無(wú)法保存到相冊(cè)", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 創(chuàng)建一個(gè)圖片地址uri,用于保存拍照后的照片
     *
     * @param activity
     * @return          圖片的uri
     */
    public static Uri createImagePathUri(Activity activity) {

        try {
            FileUtils.createOrExistsDir(Constant.DIR_ROOT);
            StringBuffer buffer = new StringBuffer();
            String pathName = buffer.append(Constant.DIR_ROOT).append(Constant.APP_NAME).append(".").append(System.currentTimeMillis()).append(".jpg").toString();
            File file = new File(pathName);

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //解決Android 7.0 拍照出現(xiàn)FileUriExposedException的問(wèn)題
                String authority = activity.getPackageName() + ".fileProvider";
                takePictureUri = FileProvider.getUriForFile(activity, authority, file);
            } else {
                takePictureUri = Uri.fromFile(file);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(activity, "無(wú)法保存到相冊(cè)", Toast.LENGTH_LONG).show();
        }
        return takePictureUri;
    }

    /**
     * 處理拍照或相冊(cè)獲取的圖片党晋,默認(rèn)大小480*480,比例1:1
     * @param activity      上下文
     * @param requestCode   請(qǐng)求碼
     * @param resultCode    結(jié)果碼
     * @param data          Intent
     * @return
     */
    public static Bitmap onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
        return onActivityResult(activity, requestCode, resultCode, data, 0, 0, 0, 0);
    }

    /**
     * 處理拍照或相冊(cè)獲取的圖片
     * @param activity      上下文
     * @param requestCode   請(qǐng)求碼
     * @param resultCode    結(jié)果碼
     * @param data          Intent
     * @param w             輸出寬
     * @param h             輸出高
     * @param aspectX       寬比例
     * @param aspectY       高比例
     * @return
     */
    public static Bitmap onActivityResult(Activity activity, int requestCode, int resultCode, Intent data,
                                          int w, int h, int aspectX, int aspectY) {
        Bitmap bm = null;
        if (resultCode == Activity.RESULT_OK) {
            Uri uri = null;
            switch (requestCode) {
                case GET_BY_ALBUM:
                    uri = data.getData();
                    activity.startActivityForResult(crop(uri, w, h, aspectX, aspectY), CROP);
                    break;
                case GET_BY_CAMERA:
                    uri = takePictureUri;
                    activity.startActivityForResult(crop(uri, w, h, aspectX, aspectY), CROP);
                    break;
                case CROP:
                    bm = dealCrop(activity);
                    break;
            }
        }
        return bm;
    }

    /**
     * 裁剪,默認(rèn)裁剪輸出480*480徐块,比例1:1
     * @param uri   圖片的uri
     * @return
     */
    public static Intent crop(Uri uri) {
        return crop(uri, 480, 480, 1, 1);
    }

    /**
     * 裁剪未玻,例如:輸出100*100大小的圖片,寬高比例是1:1
     * @param uri     圖片的uri
     * @param w       輸出寬
     * @param h       輸出高
     * @param aspectX 寬比例
     * @param aspectY 高比例
     * @return
     */
    public static Intent crop(Uri uri, int w, int h, int aspectX, int aspectY) {
        if (w == 0 && h == 0) {
            w = h = 480;
        }
        if (aspectX == 0 && aspectY == 0) {
            aspectX = aspectY = 1;
        }
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", aspectX);
        intent.putExtra("aspectY", aspectY);
        intent.putExtra("outputX", w);
        intent.putExtra("outputY", h);

        /*解決圖片有黑邊問(wèn)題*/
        intent.putExtra("scale", true);
        intent.putExtra("scaleUpIfNeeded", true);

        /*解決跳轉(zhuǎn)到裁剪提示“圖片加載失敗”問(wèn)題*/
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        /*解決小米miui系統(tǒng)調(diào)用系統(tǒng)裁剪圖片功能camera.action.CROP后崩潰或重新打開(kāi)app的問(wèn)題*/
        StringBuffer buffer = new StringBuffer();
        String pathName = buffer.append("file:///").append(FileUtils.getRootPath()).append(File.separator).append(Constant.APP_NAME).append(".temp.jpg").toString();
        cropPictureTempUri = Uri.parse(pathName);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, cropPictureTempUri);//輸出路徑(裁剪后的保存路徑)
        // 輸出格式
        intent.putExtra("outputFormat", "JPEG");
        // 不啟用人臉識(shí)別
        intent.putExtra("noFaceDetection", true);
        //是否將數(shù)據(jù)保留在Bitmap中返回
        intent.putExtra("return-data", false);
        return intent;
    }

    /**
     * 處理裁剪胡控,獲取裁剪后的圖片
     * @param context   上下文
     * @return
     */
    public static Bitmap dealCrop(Context context) {
        Bitmap bitmap = null;
        try {
            bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(cropPictureTempUri));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

}

github地址:PictureSelector
ps:如果對(duì)你有幫助扳剿,點(diǎn)下喜歡就是對(duì)我最大的認(rèn)可。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末昼激,一起剝皮案震驚了整個(gè)濱河市庇绽,隨后出現(xiàn)的幾起案子锡搜,更是在濱河造成了極大的恐慌,老刑警劉巖瞧掺,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件余爆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡夸盟,警方通過(guò)查閱死者的電腦和手機(jī)蛾方,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)上陕,“玉大人桩砰,你說(shuō)我怎么就攤上這事∈筒荆” “怎么了亚隅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)庶溶。 經(jīng)常有香客問(wèn)我煮纵,道長(zhǎng),這世上最難降的妖魔是什么偏螺? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任行疏,我火速辦了婚禮,結(jié)果婚禮上套像,老公的妹妹穿的比我還像新娘酿联。我一直安慰自己,他們只是感情好夺巩,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布贞让。 她就那樣靜靜地躺著,像睡著了一般柳譬。 火紅的嫁衣襯著肌膚如雪喳张。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天美澳,我揣著相機(jī)與錄音销部,去河邊找鬼。 笑死人柿,一個(gè)胖子當(dāng)著我的面吹牛柴墩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凫岖,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼逢净!你這毒婦竟也來(lái)了哥放?” 一聲冷哼從身側(cè)響起歼指,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎甥雕,沒(méi)想到半個(gè)月后踩身,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡社露,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年挟阻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峭弟。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡附鸽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瞒瘸,到底是詐尸還是另有隱情坷备,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布情臭,位于F島的核電站省撑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏俯在。R本人自食惡果不足惜竟秫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望跷乐。 院中可真熱鬧鸿摇,春花似錦、人聲如沸劈猿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)揪荣。三九已至筷黔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間仗颈,已是汗流浹背佛舱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挨决,地道東北人请祖。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像脖祈,于是被迫代替她去往敵國(guó)和親肆捕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

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