Android 知乎開源的圖片選擇庫

在開始正文之前并徘,先欣賞一下這個圖片選擇器的效果

Matisse

一、基本使用

1扰魂、導入相應的依賴庫

Gradle? ?implementation'com.github.bumptech.glide:glide:4.6.1'

? ? ? ? ? ? ? ?implementation'com.zhihu.android:matisse:0.5.2-beta3'

有一點要注意一下麦乞, 這個圖片選擇庫是使用 Glide 或 Picasso 作為圖片加載引擎

如果你使用 Glide 作為你的圖片加載引擎,請?zhí)砑?Glide 的 README 上所說的規(guī)則劝评,以及添加額外的規(guī)則:

-dontwarncom.squareup.picasso.**

如果你使用 Picasso 作為你的圖片加載引擎姐直,請?zhí)砑?Picasso 的 README 上所說的規(guī)則,以及添加額外的規(guī)則:

-dontwarncom.bumptech.glide.**

2蒋畜、啟動 Matisse

在正式寫代碼之前简肴,有兩個相關的權限需要先申請:

android.permission.READ_EXTERNAL_STORAGEandroid.permission.WRITE_EXTERNAL_STORAGE

所以,如果你的 APP 是跑在 Android 6.0+ 的話百侧,你需要在下個步驟之前處理一下運行時權限砰识。

public class GifSizeFilterextends Filter {

private int mMinWidth;

? ? private int mMinHeight;

? ? private int mMaxSize;

? ? public GifSizeFilter(int minWidth, int minHeight, int maxSizeInBytes) {

? ? ? ? mMinWidth = minWidth;

? ? ? ? mMinHeight = minHeight;

? ? ? ? mMaxSize = maxSizeInBytes;

? ? }

@Override

? ? public SetconstraintTypes() {

????????????return new HashSet() {{

????????????????????add(MimeType.GIF);

? ? ? ? }};

? ? }

@SuppressLint("StringFormatInvalid")

@Override

? ? public IncapableCausefilter(Context context, Item item) {

????????if (!needFiltering(context, item))

????????????????return null;

? ? ? ? Point size = PhotoMetadataUtils

????????????????????????????.getBitmapBound(context.getContentResolver(),?

????????????????????????????item.getContentUri());

? ? ? ????? if (size.x mMaxSize) {

????????????????????????????return new IncapableCause(IncapableCause.DIALOG,?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? context.getString(R.string.error_gif, mMinWidth,?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String.valueOf(PhotoMetadataUtils

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.getSizeInMB(mMaxSize))));

? ? ? ????? }

????????return null;

? ? }

}

//Glide4

import android.content.Context;

import android.graphics.drawable.Drawable;

import android.net.Uri;

import android.widget.ImageView;

import com.bumptech.glide.Glide;

import com.bumptech.glide.Priority;

import com.bumptech.glide.request.RequestOptions;

import com.zhihu.matisse.engine.ImageEngine;

/**

* {@link ImageEngine} implementation using Glide.

*/

public class Glide4Engineimplements ImageEngine {

@Override

? ? public void loadThumbnail(Context context, int resize, Drawable placeholder, ImageView imageView, Uri uri) {

????????Glide.with(context)

????????????????????.asBitmap()// some .jpeg files are actually gif

????? ? ? ? ? ? ? ? .load(uri)

????????????????????.apply(new RequestOptions()

????????????????????.override(resize, resize)

????????????????????.placeholder(placeholder)

????????????????????.centerCrop())

????????????????????.into(imageView);

? ? }

@Override

? ? public void loadGifThumbnail(Context context, int resize, Drawable placeholder, ImageView imageVie , Uri uri) {

????????????????????Glide.with(context)

????????????????????????????????.asBitmap()// some .jpeg files are actually gif

????????????????? ? ? ? ? ? ? ? .load(uri)

????????????????????????????????.apply(new RequestOptions()

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .override(resize, resize)

????????????????????????????????.placeholder(placeholder)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .centerCrop())

????????????????????????????????.into(imageView);

? ? }

@Override

? ? public void loadImage(Context context, int resizeX, int resizeY, ImageView imageView, Uri uri) {

????????Glide.with(context)

????????????.load(uri)

????????????.apply(new RequestOptions()

????????????.override(resizeX, resizeY)

????????????.priority(Priority.HIGH)

????????????.fitCenter())

????????????.into(imageView);

? ? }

@Override

? ? public void loadGifImage(Context context, int resizeX, int resizeY, ImageView imageView, Uri uri) {

????????Glide.with(context)

????????????.asGif()

????????????.load(uri)

????????????.apply(new RequestOptions()

????????????.override(resizeX, resizeY)

????????????.priority(Priority.HIGH)

????????????.fitCenter())

????????????.into(imageView);

? ?}

@Override

? ? public boolean supportAnimatedGif() {

????????????return true;

? ? }

}

我們可以在平常的 Activity 或 Fragment 中啟動 MatisseActivity

Matisse.from(EdiUserInfoActivity.this)

????.choose(MimeType.ofAll())

????.countable(true)

????.maxSelectable(9)

????.addFilter(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K))

.????gridExpectedSize(getResources().getDimensionPixelSize(R.dimen.picsize))

????.restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)

????.thumbnailScale(0.85f)

????.imageEngine(new Glide4Engine())//Glide4

????.forResult(REQUEST_CODE_CHOOSE);

3、接收選擇的結果

在啟動圖片選擇器的 Activity 或 Fragment 中的 onActivityResult() 進行結果的回調處理

//activity回調

ListmSelected;

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

super.onActivityResult(requestCode, resultCode, data);

? ? if (requestCode ==REQUEST_CODE_CHOOSE && resultCode ==RESULT_OK) {

mSelected = Matisse.obtainResult(data);

? ? ? ? Log.d("Matisse", "mSelected: " +mSelected);

? ? }

}

二佣渴、常用的 API

Mime 類型

Matisse 支持以下的 mime 類型

Mime typeFile extensionsMedia type??

?image/jpegjpg, jpegimage

image/pngpngimage

image/gifgifimage

imagex-ms-bmpbmpimage

video/mpegmpeg, mpgvideo

video/mp4mp4, m4vvideo

video/quicktimemovvideo

video/3gpp3gp, 3gppvideo

video/3gpp23g2, 3gpp2video

video/x-matroskamkvvideo

video/webmwebmvideo

video/mp2tstsvideo

video/aviavivideo

默認情況下辫狼,所有的圖像和視頻都將顯示在 Matisse 中,而且你并不能通過以下方法來限制可選擇的 mime 類型:

MimeType.ofAll()

MimeType.of(MimeType type, MimeType... rest)

MimeType.ofImage()

MimeType.ofVideo()

不過你可以讓 Matisse 只顯示一種媒體類型辛润,如果

啟動的時候膨处,調用?showSingleMediaType(true)

只選擇圖片或者視頻

數(shù)量

默認情況

在縮略圖的右上角有一個復選標記,讓你不僅可以選擇一個圖像

自動增長的數(shù)目

使用?countable(true)?來顯示一個從 1 開始的數(shù)字

最大的數(shù)字數(shù)量

使用?maxSelectable(int maxSelectable)?來限制可選擇的最大數(shù)目

方向

使用?restrictOrientation*(@ScreenOrientation int orientation)?來設置圖像選擇和預覽活動所需的方向。

網(wǎng)格的規(guī)格

如果你想要固定的跨度計數(shù)真椿,請使用?spanCount(int spanCount)鹃答,當方向更改時,范圍計數(shù)將保持不變突硝。

如果希望可以靈活地適應不同屏幕的網(wǎng)格大小测摔,請使用?spanCount(int spanCount),該值不一定被應用解恰,因為圖片網(wǎng)格應該填滿視圖容器锋八。測量的圖片網(wǎng)格的大小將盡可能接近該值。

縮略圖縮放

使用?thumnailScale(float scale)?來設置縮略圖位圖相對于視圖大小的縮放比例护盈,而且它應該是(0.0挟纱,1.0)中的浮點值。

三腐宋、主題

內置的主題

在 Matisse 中有兩種內置的主題:

Zhihu(亮藍色主題)

Dracula(黑色主題)

當啟動 Matisse 的時候紊服,調用 theme(@styleRes int themeId) 方法來使用其中一種主題

Matisse.from(MainActivity.this)? ? ...? ? .theme(R.style.Matisse_Zhihu | R.style.Matisse_Dracula)? ? .forResult(REQUEST_CODE_CHOOSE);

自定義主題

從兩個內置主題,甚至是他們的父母派生自定義主題胸竞,你可以自定義 Matisse 的外觀

這些屬性(在 attrs.xml 中定義)可以修改:

屬性作用

colorPrimary應用欄的顏色

colorPrimaryDark狀態(tài)欄的較暗變體

toolbar: toolbartoolbar 的風格

album.dropdown.title.color專輯名稱下的專輯中的下拉列表中的顏色

album.dropdown.count.color工具欄元素的顏色围苫,元素包括導航圖標,所選的相冊標題和右側的下拉箭頭圖標

album.thumbnail.placeholder相冊縮略圖的占位符

album.emptyView繪制圖片的空視圖

album.emptyView.textColor空白視圖的文字顏色

item.placeholder媒體網(wǎng)格的占位符顏色或 drawable

page.bgActivity 或 Fragment 頁面的背景顏色或 drawable

bottomToolbar.preview.textColor底部工具欄的背景顏色或 drawable

bottomToolbar.apply.textColor預覽按鈕文本的底部工具欄上的顏色

listPopupWindwoStyle專輯列表的下拉菜單樣式

capture.textColor可能出現(xiàn)在頂部的捕獲網(wǎng)格的文本顏色

以上便是本文的全部內容撤师,如果想進一步了解 Matisse 的源碼實現(xiàn)剂府,可以看下這篇文章:知乎 Matisse 源碼解析,帶你探究高效圖片選擇庫的秘密

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末剃盾,一起剝皮案震驚了整個濱河市腺占,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌痒谴,老刑警劉巖衰伯,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異积蔚,居然都是意外死亡意鲸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門尽爆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怎顾,“玉大人,你說我怎么就攤上這事漱贱』蔽恚” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵幅狮,是天一觀的道長募强。 經常有香客問我株灸,道長,這世上最難降的妖魔是什么擎值? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任慌烧,我火速辦了婚禮,結果婚禮上鸠儿,老公的妹妹穿的比我還像新娘屹蚊。我一直安慰自己,他們只是感情好捆交,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著腐巢,像睡著了一般品追。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上冯丙,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天肉瓦,我揣著相機與錄音,去河邊找鬼胃惜。 笑死泞莉,一個胖子當著我的面吹牛,可吹牛的內容都是我干的船殉。 我是一名探鬼主播鲫趁,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼利虫!你這毒婦竟也來了挨厚?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤糠惫,失蹤者是張志新(化名)和其女友劉穎疫剃,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體硼讽,經...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡巢价,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了固阁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壤躲。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖备燃,靈堂內的尸體忽然破棺而出柒爵,到底是詐尸還是另有隱情,我是刑警寧澤赚爵,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布棉胀,位于F島的核電站法瑟,受9級特大地震影響,放射性物質發(fā)生泄漏唁奢。R本人自食惡果不足惜霎挟,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望麻掸。 院中可真熱鬧酥夭,春花似錦、人聲如沸脊奋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诚隙。三九已至讶隐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間久又,已是汗流浹背巫延。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留地消,地道東北人炉峰。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像脉执,于是被迫代替她去往敵國和親疼阔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353