天天看點

Android-如何開發一個功能強大的圖檔選擇器

Android-如何開發一個功能強大的圖檔選擇器

圖檔選擇器是android開發中會經常用到的一個功能,特别對于社交類的應用,比如頭像設定,比如發圖檔。自然imagepicker的輪子很多,今天介紹一個功能強大的輪子simagepicker

介紹

首先功能強大之處

首先基本的圖檔讀取顯示,以及圖檔更新監控

超大圖檔預覽,比如一張19m,10000*5000px的圖檔

圖檔的裁剪功能

豐富的可配置項,支援拍照選取,選取張數定義,支援選擇的圖檔過濾,

支援多種圖檔加載器(fresco,glide等)

廢話不說,先看效果

第一張頭像模式,第二張選擇多張圖檔(包括動畫和順暢的跳轉),第三張是分片加載超大圖(19.5m,10000*5000px)  

Android-如何開發一個功能強大的圖檔選擇器

頭像模式,支援裁剪  

Android-如何開發一個功能強大的圖檔選擇器

多選圖檔,流暢的頁面跳轉 

Android-如何開發一個功能強大的圖檔選擇器

超大圖預覽,可以看到漸變加載

如何使用

1.首先初始化(推薦在application的oncreate中調用)

simagepicker.init(new pickerconfig.builder().setappcontext(this) 

.setimageloader(new frescoimageloader()) 

.settoolbasecolor(getcolor(r.color.colorprimary)) 

.build());  

2.在需要選擇圖檔的地方調用

simagepicker 

.from(mainactivity.this) 

.maxcount(9) 

.rowcount(3) 

.pickmode(simagepicker.mode_image) 

.fileinterceptor(new singlefilelimitinterceptor()) 

.forresult(request_code_image);  

可配置項

1.全局配置(即初始化時傳入的pickerconfig,此配置作用于simagepicker整個使用過程)

配置參數

參數含義

setimageloader(imageloader)

使用的圖檔加載器。demo工程中實作了fresco和glide兩種imageloader,可以參考

settoolbarcolor(int)

picker的主色調,預設值是app的primarycolor

setappcontext(context)

picker内部用到的context,傳入applicationcontext即可

2.單次配置(即每次調用simagepicker時傳入的參數,此參數隻對這次調用生效)

from(activity or fragment)

調用圖檔選擇器可從activity或者fragment進入,最後的結果會在onactivityresult()傳回,現在傳回的結果有兩個值,使用者選擇的圖檔的路徑清單data.getstringarraylistextra(photopickeractivity.extra_result_selection);使用者是否選擇了原圖data.getbooleanextra(photopickeractivity.extra_result_original, false);

maxcount(int)

此次選擇允許的最大選擇數量,預設是1.比如發朋友圈最多選擇9張圖就傳9

rowcount(int)

圖檔清單單排展示多少張圖

setselected(list)

預設已經被選中的圖檔

pickmode(int)

選圖的模式,現在有頭像模式和普通模式兩種,頭像模式選中圖檔後預設會跳到圖檔裁剪頁面且預設隻能選擇一張

cropfilepath(string)

頭像模式下裁剪圖檔存放位址

showcamera(boolen)

是否要展示拍照入口

picktext(int) 

picker裡右下角展示的文字資訊(比如配置選擇,發送,完成)

fileinterceptor(filechooseinterceptor)

圖檔過濾器,比如使用者選擇的單張圖檔大小有限制,即可寫在這個攔截器中,當使用者選擇過大圖檔時可以提示并且過濾

forresult(int requestcode)

打開圖檔選擇器,并且傳入requestcode

擷取結果

在調用圖檔選擇器的fragment或者activity中

@override 

  protected void onactivityresult(int requestcode, int resultcode, intent data) { 

    super.onactivityresult(requestcode, resultcode, data); 

    if (resultcode == activity.result_ok && requestcode == request_code_image) { 

      final arraylist<string> pathlist = 

          data.getstringarraylistextra(photopickeractivity.extra_result_selection); 

      final boolean original = 

          data.getbooleanextra(photopickeractivity.extra_result_original, false); 

    } 

  } 

實作

圖檔資料庫讀取cursorloader

android3.0中引入了加載器/裝載器(loader)的功能,主要用于異步的方式加載資料庫。裝載器loader的特點:

裝載器提供異步資料加載的能力

裝載器監視資料資源并且當内容改變時發送新的結果;

在配置改變後重建的時候,裝載器自動的重連最後的裝載器遊标,是以,不需要重新查詢資料。

此項目也是使用loader去加載和監控圖檔資料,對于photo和album即圖檔和相冊分别有一個loader和一個controller,loader主要用于加載對應的資料,controller主要用于資料讀取到後的重新整理已經loader的釋放。

源碼中的對應

Android-如何開發一個功能強大的圖檔選擇器

photoloader初始化

public static cursorloader newinstance(context context, album album, long minsize) { 

  if (album == null || album.isall()) { 

    return new photoloader(context, mediastore.images.media.external_content_uri, projection, 

        selection_size, new string[] {minsize + ""}, order_by); 

  return new photoloader(context, mediastore.images.media.external_content_uri, projection, 

      mediastore.images.media.bucket_id + " = ? and (" + selection_size + ")", new string[] { 

          album.getid(), minsize + ""}, order_by); 

超大圖檔加載

對于超大的圖檔如何展示,這個是個比較棘手的問題

比如這張圖

<a href="http://7xpb9x.com1.z0.glb.clouddn.com/2017/01/20/b578e4755a32ac56a9c4b9a1f7e2822d.jpg">http://7xpb9x.com1.z0.glb.clouddn.com/2017/01/20/b578e4755a32ac56a9c4b9a1f7e2822d.jpg</a>

10000*5000的像素,接近20m。

這種圖檔肯定無法一次全部load到記憶體中,可以稍微計算一下即使是rgb_565的方式全部load進記憶體也要占用幾乎90m的記憶體,顯然是不太可能。可以回頭看一下第三張demo gif,顯然使用者打開一張圖時,在預設情況下,并不要求能看到細節,當使用者點選某區域放大時此時才會需要這一塊的清晰圖。那麼如何展示這種超大圖的思路基本基本就是

首先拿到檔案路徑,讀取出圖檔的寬高,并且根據螢幕和圖檔寬高計算出一個展示全圖的情況下的samplesize,根據這個值去加載出一個全景的圖

對圖檔進行分塊,分塊會分出不同放大倍數下(即選擇不同samplesize)下的一個塊清單,比如放大2倍時,放大4倍時對應怎麼分塊

當使用者點選放大某一區域時,根據放大的倍數以及目前的中心點選擇對應的塊進行load和渲染

在simagepicker項目中主要是用了subsamplingimageview

并且根據picker的需求做了些修改,來實作超大圖的預覽

圖檔清單展示

展示

由于使用了cursorloader,對于listview的話有cursoradapter可以使用,但是對于recyclerview确沒有對應的adapter,是以在源碼中可以看到實作了一個recyclecursoradapter,用于實作從cursor擷取資料已經自動重新整理。

相容

為了能夠相容多個圖檔加載器,simagepicker抽象了一個imageloader接口用于讓使用者自定義對應的圖檔加載器。

使用建議

simagepicker提供了jitpack上的依賴庫,可以很快的接入業務中,但是由于大部分的app對于imagepicker的使用都有各種業務需求,且simagepicker隻是抽象出了比較通用的一些配置,用于讓使用者能快速內建,是以此處還是建議使用者盡可能源碼引用的方式的使用simagepicker,既友善做一些調試,也可以很快的了解實作原理,說起來這種ui元件代碼應該是很好讀的,因為本身并不複雜。

作者:聶俊鴻

來源:51cto