圖片選擇器 Matisse 在 6.0 以上手機使用相機以及選擇圖片過濾小圖功能

2018-7-23 更新

Matisse使用文檔

Matisse 中使用 Filter 過濾圖片大小等操做

Filter 過濾器,Matisse 中這樣描述:Filter for choosing a {@link Item}. You can add multiple Filters through 也就是在你選擇圖片的時候過濾掉你不想選擇的內容。java

例如:網上常見的過濾gif功能,還有我這裏說明的過濾圖片大小功能.
首先建立一個子類,繼承 Matisse 中使用 Filterandroid

public class MiniSizeFilter extends Filter { 
 
   

    private int mMinWidth;
    private int mMinHeight;
    private int mMaxSize;
    public MiniSizeFilter(int minWidth, int minHeight, int maxSizeInBytes) {
        mMinWidth = minWidth;
        mMinHeight = minHeight;
        mMaxSize = maxSizeInBytes;
    }

    /** * 約束的圖片類型 * @return */
    @Override
    protected Set<MimeType> constraintTypes() {
        return EnumSet.of(MimeType.JPEG, MimeType.PNG, MimeType.BMP, MimeType.WEBP);
    }

    @Override
    public IncapableCause filter(Context context, Item item) {
        if (!needFiltering(context, item)){
            return null;
        }

        Point size = PhotoMetadataUtils.getBitmapBound(context.getContentResolver(), item.getContentUri());
// Log.e(TAG, "filter: mimeType--------->"+item.mimeType);
// Log.e(TAG, "filter: describeContents--------->"+item.describeContents());
// Log.e(TAG, "filter: duration--------->"+item.duration);
// Log.e(TAG, "filter: getContentUri--------->"+item.getContentUri());
// Log.e(TAG, "filter: id--------->"+item.id);
// 圖片的大小
// Log.e(TAG, "filter: size--------->"+item.size);
// Log.e(TAG, "filter: uri--------->"+item.uri);
// 圖片的寬高
// Log.e(TAG, "filter: size.x--------->"+size.x );
// Log.e(TAG, "filter: size.y--------->"+size.y );
        if (size.x < mMinWidth || size.y < mMinHeight || item.size > mMaxSize) {
            // IncapableCause.TOAST 表示 Toast 提示,它有三個選擇:{TOAST, DIALOG, NONE}
            return new IncapableCause(IncapableCause.TOAST, context.getString(R.string.image_size_to_small, mMinWidth,
                    String.valueOf(PhotoMetadataUtils.getSizeInMB(mMaxSize))));
        }
        return null;
    }
}

使用方式以下:git

Matisse.from(MainActivity.this)
    ...
    .addFilter(new MiniSizeFilter(320, 320, 5 * Filter.K * Filter.K)) // 控制寬高爲320*320 以上,大小爲 50M 如下
    .forResult(REQUEST_CODE_CHOOSE);

以上爲2018-7-23更新github


首發地址:dongxi520.com
需求:實現一個圖片選擇器,能選擇本地圖片拍照web

拿到需求,第一個想法就是看本身在規定時間上可否又快又好的實現。顯然是不能( 。。),如今那麼多前輩都把輪子都造好了,咱們直接拼裝不久能夠了嗎?目前爲止,我仍是這樣,等功能深厚成爲前輩了再擼幾個輪子給後輩使用,這些都是後話,先實現這個需求吧。app

先去GitHub搜索一圈圖片選擇器,發現知乎開源的Matisse傢伙長的挺好看的,就選它了。使用步驟看GitHub的,官方的纔是最正確的使用姿式。Matisse ide

或者是參看一下這位仁兄的介紹:Android 一塊兒來看看知乎開源的圖片選擇庫svg

官網的使用方式 默認是不開啓拍照功能的,所以須要拍照功能的能夠這麼寫ui

Matisse.from(PublishActivity.this)
               .choose(MimeType.allOf()) // 選擇 mime 的類型
               .countable(true) // 顯示選擇的數量
               .capture(true)  // 開啓相機,和 captureStrategy 一併使用不然報錯
               .captureStrategy(new CaptureStrategy(true,"com.meiqu.pianxin.ui.publish.MyFileProvider")) // 拍照的圖片路徑
               .theme(R.style.Matisse_Dracula) // 黑色背景
               .maxSelectable(9) // 圖片選擇的最多數量
               .gridExpectedSize(getResources().getDimensionPixelSize(R.dimen.grid_expected_size)) // 列表中顯示的圖片大小
               .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
               .thumbnailScale(0.85f) // 縮略圖的比例
               .imageEngine(new GlideEngine()) // 使用的圖片加載引擎
               .forResult(REQUEST_CODE_CHOOSE); // 設置做爲標記的請求碼,返回圖片時使用
  • captureStrategy(new CaptureStrategy(true,"com.meiqu.pianxin.ui.publish.MyFileProvider"))
    主要是告知系統拍照的圖片存儲位置
  • 第二個參數是本身實現繼承FileProvider類的一個空類,須要在manifest文件中添加以下代碼
<provider  android:name="android.support.v4.content.FileProvider" android:authorities="com.meiqu.pianxin.ui.publish.MyFileProvider" android:exported="false" android:grantUriPermissions="true">
                <meta-data  android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths"/>
</provider>
  • android:resource=」@xml/filepaths」 是在res/xml 目錄下的建立的文件filepaths.xml
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--表明外部存儲區域的根目錄下的文件 Environment.getExternalStorageDirectory()/DCIM/camerademo目錄-->
        <external-path name="mq_DCIM" path="DCIM/camerademo" />

       <!--表明外部存儲區域的根目錄下的文件 Environment.getExternalStorageDirectory()/Pictures/camerademo目錄-->
       <external-path name="mq_Pictures" path="Pictures/camerademo" />

       <!--表明app 私有的存儲區域 Context.getFilesDir()目錄下的images目錄 /data/user/0/com.hm.camerademo/files/images-->
        <files-path name="mq_private_files" path="images" />

        <!--表明app 私有的存儲區域 Context.getCacheDir()目錄下的images目錄 /data/user/0/com.hm.camerademo/cache/images-->
        <cache-path name="mq_private_cache" path="images" />

      <!--表明app 外部存儲區域根目錄下的文件 Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)目錄下的Pictures目錄-->
        <external-files-path name="mq_external_files" path="Pictures" />
        <!--表明app 外部存儲區域根目錄下的文件 Context.getExternalCacheDir目錄下的images目錄-->
        <external-cache-path name="mq_external_cache" path="" />

        <root-path name="mq_external_cache" path="" />
    </paths>

以上使用在 5.0 如下的手機是沒毛病的,在 6.0 這個動態權限的控制下就有些問題了this

6.0 以上使用 Matisse 的正確姿式

Matisse 和 PermissionsDispatcher 的使用姿式

Matisse 須要用到相機和讀寫本地數據的權限

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.Manifest.permission.READ_PHONE_STATE" />

因此在調用了這些權限的地方是使用 PermissionsDispatcher 去動態設置,看PermissionsDispatcher 官網介紹

我在實際中使用

​步驟:

  • 在Activity或者Fragment上添加 @RuntimePermissions
  • 在用到權限的方法( 例如:void initData(),不能加上 private 修飾)名上添加@NeedsPermission(Manifest.permission.READ_PHONE_STATE)
  • 重寫onRequestPermissionsResult方法,MainActivityPermissionsDispatcher.onRequestPermissionsResult(MainActivity.this, requestCode, grantResults);
  • 在onCreate方法調用MainActivityPermissionsDispatcher.initDataWithCheck(MainActivity.this);​

實例:

@RuntimePermissions  // 必須添加
public class MainActivity extends AppCompatActivity { 
 
   
 ...
    @Override   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       ....
       MainActivityPermissionsDispatcher.initDataWithCheck(MainActivity.this);
       ....
   }
    @NeedsPermission(Manifest.permission.READ_PHONE_STATE) // 必須添加
   void initData() {  // 會調用用戶信息權限
       DataCenter dc = DataCenter.getInstance();
       dc.initDataCenter(this);
   }
      @Override
   public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
       super.onRequestPermissionsResult(requestCode, permissions, grantResults);
       MainActivityPermissionsDispatcher.onRequestPermissionsResult(MainActivity.this, requestCode, grantResults);
   }
}

本文同步分享在 博客「_龍衣」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索