Matisse 是知乎最近开源的一款 Android 图片/视频选择器。

GitHub地址:https://github.com/zhihu/Matisse

  • 可以在 Activity 或者 Fragment 使用
  • 可以选择JPEG, PNG, GIF 类型的图片,也支持选择 MPEG, MP4等格式的视频
  • 可以应用在不同的主题,包括 Matisse 两套内置主题和自定义主题
  • 支持不同的图片加载库,目前支持 Glide 和 Picasso。
  • 支持自定义筛选规则

先看下知乎的效果图:

ZhihuStyle

Dracula Style

Preview




下面我们就开始使用一下Matisse:

1、依赖配置

在bulid.gradle文件中添加依赖:

compile 'com.zhihu.android:matisse:0.5.0-alpha2'

另外这些依赖也要添加(可根据提示添加相应的依赖):

compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:support-annotations:25.3.1'
compile 'com.android.support:recyclerview-v7:25.3.1'
compile 'com.android.support:support-v4:25.3.1'

2.添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Android 6.0之后需要动态获取一些涉及隐私的权限(原demo使用的是RxJava获取权限,这里使用了另外一种方式):

/**
 * android 6.0之后需要动态获取权限
 */
@TargetApi(23)
private void getPersimmions() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

        ArrayList<String> permissions = new ArrayList<String>();
        /**
         * 读写权限非必要权限(建议授予)只会申请一次,用户同意或者禁止,只会弹一次
         */
        if (addPermission(permissions, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            permissionInfo += "Manifest.permission.WRITE_EXTERNAL_STORAGE Deny \n";
        }

        if (addPermission(permissions, Manifest.permission.READ_EXTERNAL_STORAGE)) {
            permissionInfo += "Manifest.permission.READ_EXTERNAL_STORAGE Deny \n";
        }

        if (permissions.size() > 0) {
            requestPermissions(permissions.toArray(new String[permissions.size()]), SDK_PERMISSION_REQUEST);
        }
    }
}

@TargetApi(23)
private boolean addPermission(ArrayList<String> permissionsList, String permission) {
    if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { // 如果应用没有获得对应权限,则添加到列表中,准备批量申请
        if (shouldShowRequestPermissionRationale(permission)){
            return true;
        }else{
            permissionsList.add(permission);
            return false;
        }

    }else{
        return true;
    }
}

@TargetApi(23)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    // TODO Auto-generated method stub
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

}

3.ProGuard

如果使用Glide作为图片加载开源库

-keep public class * implements com.bumptech.glide.module.GlideModule
 -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
  # for DexGuard only
 -keepresourcexmlelements manifest/application/meta-data@value=GlideModule

如果使用Picasso作为图片加载开源库

-dontwarn com.squareup.okhttp.**

4.代码使用

知乎主题:

Matisse.from(MainActivity.this)
       .choose(MimeType.ofAll())
       .countable(true)
       .maxSelectable(9)
       .addFilter(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K))
       .gridExpectedSize(getResources().getDimensionPixelSize(R.dimen.grid_expected_size))
       .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
       .thumbnailScale(0.85f)
       .imageEngine(new GlideEngine())
       .forResult(REQUEST_CODE_CHOOSE);

Dracula主题:

Matisse.from(MainActivity.this)
       .choose(MimeType.of(MimeType.JPEG, MimeType.PNG))
       .theme(R.style.Matisse_Dracula)
       .countable(false)
       .maxSelectable(9)
       .imageEngine(new PicassoEngine())
       .forResult(REQUEST_CODE_CHOOSE);

自定义主题:

Matisse.from(MainActivity.this)
       .choose(MimeType.ofVideo())
       .theme(R.style.Matisse_Custom)
       .countable(false)
       .maxSelectable(9)
       .forResult(REQUEST_CODE_CHOOSE);

需要在colors,styles文件下设置相关的属性。

colors

styles



效果如下:

处理结果:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) {
        mAdapter.setData(Matisse.obtainResult(data));
    }
}

5.方法参数解析

choose(Set mimeType): 选择图片、视频类型。支持jpg,jpeg,png,gif ,mpeg, mp4, mov, 3gpp, 3pp2, mkv, webm, ts, avi。

theme(@StyleRes int themeId):设置主题风格。

countable(boolean countable):用于判断是否标记选中项数量。返回true则从 1 开始计数。默认是false。

maxSelectable(int maxSelectable):最大可选中项数

addFilter(Filter filter):添加过滤条件。我们可以通过集成Filter抽象类实现对应的过滤条件来对图片进行筛选,可以添加多个Filter。

例如这里设置了gif类型的图片Filter: new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K):长宽不小于320dpx,且大小不超过 5M 的gif文件。

gridExpectedSize(int size):设置要求展示的图片大小值

thumbnailScale(float scale):图片缩略值。范围在(0.0, 1.0],默认值是0.5。

restrictOrientation(int orientation):设置屏幕方向。横/竖屏 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT

imageEngine(ImageEngine imageEngine):图片加载接口。目前支持GlideEngine,PicassoEngine。(Glide全包含Picasso支持的功能,而且Picasso不支持Gif)

代码中知乎主题下使用的是 GlideEngine ,支持Gif类型的文件。

代码中Dracula主题下使用的是 PicassoEngine ,Picasso不支持Gif类型的文件。

6.类分析

类名

描述

ImageEngine

图片加载接口,方便后面根据Glide和Picasso分别实现

GlideEngine

Glide实现ImageEngine

PicassoEngine

Picasso实现ImageEngine

Filter

过滤条件抽象类,我们可以通过集成Filter实现对应的过滤条件来对图片进行筛选,可以添加多个Filter,具体参考官方Demo中的GifSizeFilter

Album

相册Entity

CaptureStrategy

拍照相关,媒体处理authority

IncapableCause

信息处理,toast和dialog

Item

选择媒体界面的Item

SelectionSpec

选择参数类

AlbumLoader

相册CursorLoader

AlbumMediaLoader

图片和视频CursorLoader

AlbumCollection

AlbumLoader回调

AlbumMediaCollection

AlbumMediaLoader回调

SelectedItemCollection

被选中项集合

internal/ui包

界面显示的Adapter,自定义视图,Fragment和Activity

internal/utils包

工具类

MatisseActivity

关键类,执行选择媒体操作的时候展示出来的Activity

Matisse

开源库的入口和出口,用来传递Activity和Fragment,创建SelectionSpecBuilder和返回结果

MimeType

媒体类型

SelectionSpecBuilder

Build构造类,用来传递参数