Android选择与上传图片之Matisse教程

效果图:

就目前效果图来看,好像也没什么毛病哈,其实我这个集成的过程是有点坎坷的。
而且,功能也不算是很齐全吧…主要体现在以下几个点

  • 没有回调之后的预览
  • 选择之后不能删除已选
  • 已选择的图片再次选择不能带过去
  • 剪裁
  • 压缩
  • 权限
  • Glide版本过低

但是,也是有特点的

  • MD风格
  • 白天模式和夜间模式

其他与同类相比也真的没什么了,唯一背书 就是知乎团队出的呗。。
相比之下,昨天出的Android选择与上传图片之PictureSelector教程就更加友好和人性化了。

下面来说说集成遇到的问题以及解决方案。

github:https://github.com/zhihu/Matisse

集成

Gradle:

repositories {
    jcenter()
}

dependencies {
    compile 'com.zhihu.android:matisse:0.4.3'
}

releases最新是v0.5.0-beta3的,本文还是基于官方文档0.4.3的版本

你以为这样就可以使用了吗,nonono,权限需要动态获取,你还需要RxPermissions或者其他权限库,或者自己封装

compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar'

这就完了吗,no,你还需要rxjava

compile "io.reactivex.rxjava2:rxjava:2.1.9"

现在总可以了吧,依然nonono,如果你项目集成了Glide,还是会报错,我在用的Glide版本是4.6.1的,Matisse中集成的是3.7.0的,是有区别的,具体你可以看这里 带你全面了解Glide 4的用法,你也可以用Picasso

会报异常

java.lang.NoSuchMethodError: com.bumptech.glide.RequestManager.load

解决方案就是重新自定义图片加载方式GlideEngine,具体可以看这里Matisse 与 Glide – java.lang.NoSuchMethodError: com.bumptech.glide.RequestManager.load。

到这里你以为就ok了吗,还是nonono,还是会报异常,因为两个版本会冲突啊

java.lang.NoClassDefFoundError: android.support.v4.animation.AnimatorCompatHelper

解决方案看这里java.lang.NoClassDefFoundError: android.support.v4.animation.AnimatorCompatHelper

Matisse:爱我你怕了吗

终于可以使用了,哇的哭出声

使用

你以为集成都这么坎坷了,使用应该很方便吧,no啊大胸弟,
虽然集成之前我看到150+的Issues有点头皮发麻,果然没让我失望,坎坷的路还长着呢。

最快的方式集成第三方有两种,1.看官方文档,2.看例子。

你以为从sample中copy copy代码,导下包就能跑起来了吗,nonono

选择器不光是有图片的吧,你可能还有gif和视频啊,所以在配置的时候你要选择一个type啊

sample是这样的

Matisse.from(SampleActivity.this)
    .choose(MimeType.ofAll(), false)
    ...

源码实际上是这样的

 public SelectionSpecBuilder choose(Set<MimeType> mimeType) {
        return new SelectionSpecBuilder(this, mimeType);
    }

所以,你的应该是这样

Matisse.from(MainActivity.this)
    .choose(MimeType.allOf())
    ...

没有boolean类型参数,而且也不是ofAll了,而是allOf。

上面是把所有的都列出来,那我如果只选图片怎么办呢

sample是这样的

Matisse.from(SampleActivity.this)
    .choose(MimeType.ofImage())
    ...

尼玛。。实际上MimeType这个枚举类中根本就没有ofImage

所以你的应该是这样的

Matisse.from(MainActivity.this)
    .choose(MimeType.of(MimeType.JPEG))
    ...

所以,刺不刺激?

对了,你如果要用最新版本,比如v0.5.0-beta3,注意去掉前面的v。

然后,你可以跑起来了,也不会报错了,仿佛一切都ok的样子(翻译一下:其实并没有,逃..)

遇到几个点还没有解决,也懒得深入研究了,我要回家过年,哼

  1. 拍照还是选择相册,没有处理
  2. 预览,选择图片的时候可以预览,但是回调之后并不行,没有处理
  3. onActivityResult回调之后的图片不能直接删除,没有处理
  4. 剪裁,没有处理
  5. 压缩,没有处理
  6. 哦对了,如果可以预览了,那还得可以保存图片呢,也没有处理,因为预览没有处理,哈哈哈嗝
  7. 已选择的图片,再次选择的时候带过去,没有处理

那有人就会说了,这么多没有的功能,或者文档没有介绍到的,不是可以自己去处理吗,这样岂不是定制化更高?比如筛选条件、主题…
emmm…
你说的对,但我不认同。哈哈哈

哦对了,选择图片的时候可以预览,看一下是什么样的

啊。。scaleType不对就不说了,可是你让我的toolbar兄弟如何自处?又要挨window爸爸的打了。。

哦对了,0.5的版本加了新功能,但是正式版还没有发布

最后,不要忘了加权限和FileProvider。
然后贴一下MainActivity的代码和gayhub的地址

package com.yechaoa.matissedemo;

import android.Manifest;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.tbruyelle.rxpermissions2.RxPermissions;
import com.zhihu.matisse.Matisse;
import com.zhihu.matisse.MimeType;
import com.zhihu.matisse.internal.entity.CaptureStrategy;

import java.util.List;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private UriAdapter mAdapter;
    private static final int REQUEST_CODE_CHOOSE = 23;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.zhihu).setOnClickListener(this);
        findViewById(R.id.dracula).setOnClickListener(this);

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
        recyclerView.setAdapter(mAdapter = new UriAdapter());
    }

    /**
     * 1 预览  2 已选择带过去  3 剪裁  4 压缩
     * <p>
     * 120 显示三列  100显示四列
     */

    @Override
    public void onClick(final View v) {
        RxPermissions rxPermissions = new RxPermissions(MainActivity.this);
        rxPermissions.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .subscribe(new Observer<Boolean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Boolean aBoolean) {
                        if (aBoolean) {
                            switch (v.getId()) {
                                case R.id.zhihu:
                                    Matisse.from(MainActivity.this)
                                            .choose(MimeType.allOf())//ofAll()
                                            .theme(R.style.Matisse_Zhihu)//主题,夜间模式R.style.Matisse_Dracula
                                            .countable(true)//是否显示选中数字
                                            .capture(true)//是否提供拍照功能
                                            .captureStrategy(new CaptureStrategy(true, "com.zhihu.matisse.sample.fileprovider"))//存储地址
                                            .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 MyGlideEngine())//图片加载方式
                                            .forResult(REQUEST_CODE_CHOOSE);//请求码
                                    break;
                                case R.id.dracula:
                                    Matisse.from(MainActivity.this)
                                            .choose(MimeType.of(MimeType.JPEG))//ofImage()
                                            .theme(R.style.Matisse_Dracula)
                                            .countable(false)
                                            .maxSelectable(9)
                                            .imageEngine(new MyGlideEngine())
                                            .forResult(REQUEST_CODE_CHOOSE);
                                    break;
                            }
                            mAdapter.setData(null);
                        } else {
                            Toast.makeText(MainActivity.this, "权限被拒绝了..", Toast.LENGTH_LONG).show();
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    @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));
        }
    }

    private class UriAdapter extends RecyclerView.Adapter<UriAdapter.UriViewHolder> {

        private List<Uri> mUris;

        void setData(List<Uri> uris) {
            mUris = uris;
            notifyDataSetChanged();
        }

        @Override
        public UriViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new UriViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.uri_item, parent, false));
        }

        @Override
        public void onBindViewHolder(UriViewHolder holder, int position) {
            Glide.with(MainActivity.this).load(mUris.get(position)).into(holder.mImg);
        }

        @Override
        public int getItemCount() {
            return mUris == null ? 0 : mUris.size();
        }

        class UriViewHolder extends RecyclerView.ViewHolder {

            private ImageView mImg;

            UriViewHolder(View contentView) {
                super(contentView);
                mImg = (ImageView) contentView.findViewById(R.id.img);
            }
        }
    }

}

github:https://github.com/yechaoa/MatisseDemo

到此这篇关于Android选择与上传图片之Matisse教程的文章就介绍到这了,更多相关Android图片选择上传Matisse内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • easycom模式开发UNI-APP组件调用必须掌握的实用技巧

    本文旨在抛砖引玉,具体文档和easycom规范请移步uni-app官网.[传送门]easycom模式说明 easycom组件模式介绍 自HBuilderX 2.5.5起支持easycom组件模式.若HBuiderX版本较低,请先检查更新! uni-app基于VUE开发,通常组件的使用都是先安装,然后全局或者局部引入,注册.然后方可在页面中使用相应的组件.过程较为繁琐,而uni-app使用easycom组件模式对上述三个步骤进行了简化,使得用户在使用组件的时候无需引用和注册直接可在页面中使用组件.

  • C语言container of()函数案例详解

          在linux 内核编程中,会经常见到一个宏函数container_of(ptr,type,member), 但是当你通过追踪源码时,像我们这样的一般人就会绝望了(这一堆都是什么呀? 函数还可以这样定义??? 怎么还有0呢???  哎,算了,还是放弃吧...). 这就是内核大佬们厉害的地方,随便两行代码就让我们怀疑人生,凡是都需要一个过程,慢慢来吧.         其实,原理很简单:  已知结构体type的成员member的地址ptr,求解结构体type的起始地址.        

  • Android选择与上传图片之PictureSelector教程

    效果图: [注意]Demo已更新到最新版本,并稍作调整. 之前出过一篇 Android选择与上传图片之ImagePicker教程,这个是okgo作者出的,就一般需求来讲是够了,但是没有压缩,需要自己去搞. 后来业务需求提升,页面要美,体验要好,便不是那么满足需求了,所幸在github上找到PictureSelector(然后当时没多久Matisse就开源了-可以看这里 Android选择与上传图片之Matisse教程),也不用自己再撸一个了,下面来介绍介绍PictureSelector gith

  • 解决java.lang.NoClassDefFoundError: android.support.v4.animation.AnimatorCompatHelper问题

    在开发过程中,有的时候引入了多个三方库.在调用的时候会出现版本对应不上的原因.就会出现如标题的异常.解决的办法就是在你的build.gradle里面加入如下代码块: configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> def requested = details.requested if (requested.group == 'com.android.supp

  • OpenCV实现特征检测和特征匹配方法汇总

    目录 1.SURF 2.SIFT 3.ORB 4.FAST 5.Harris角点 一幅图像中总存在着其独特的像素点,这些点我们可以认为就是这幅图像的特征,成为特征点.计算机视觉领域中的很重要的图像特征匹配就是一特征点为基础而进行的,所以,如何定义和找出一幅图像中的特征点就非常重要.这篇文章我总结了视觉领域最常用的几种特征点以及特征匹配的方法. 在计算机视觉领域,兴趣点(也称关键点或特征点)的概念已经得到了广泛的应用, 包括目标识别. 图像配准. 视觉跟踪. 三维重建等. 这个概念的原理是, 从图

  • Android选择与上传图片之ImagePicker教程

    效果图: 后来又出了两篇,也可以看一下 Android选择与上传图片之PictureSelector教程 Android选择与上传图片之Matisse教程 添加依赖: 选择图片:compile 'com.lzy.widget:imagepicker:0.5.4' github地址:https://github.com/jeasonlzy/ImagePicker 上传文件:compile 'com.zhy:okhttputils:2.6.2' github地址:https://github.com

  • SpringCloud2020.0.x版UnderTow AccessLog相关配置简介

    目录 01.accesslog相关配置 02.日志文件rotate目前只能按照日期 03.access占位符 总结 本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 01.accesslog相关配置 server: undertow: # access log相关配置 accesslog: # 存放目录,默认为 logs dir: ./log # 是否开启 enab

  • gaussdb 200安装 data studio jdbc idea链接保姆级安装步骤

    安装步骤 所使用linux为:openEuler-20.03-LTS-x86_64 openEuler下载地址 修改本机的ip地址 vi /etc/sysconfig/network-scripts/ifcfg-ens33 TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=static DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DE

  • C语言MultiByteToWideChar和WideCharToMultiByte案例详解

    目录 注意: 一.函数简单介绍 ( 1 ) MultiByteToWideChar() ( 2 ) WideCharToMultiByte() 二.使用方法 ( 1 ) 将多字节字符串转为宽字符串: ( 2 ) 从宽字节转为窄字节字符串 三.MultiByteToWideChar()函数乱码的问题 注意: 这两个函数是由Windows提供的转换函数,不具有通用性 C语言提供的转换函数为mbstowcs()/wcstombs() 一.函数简单介绍 涉及到的头文件: 函数所在头文件:windows.

  • 解决SpringBoot加载application.properties配置文件的坑

    SpringBoot加载application.properties配置文件的坑 事情的起因是这样的 一次,本人在现场升级程序,升级完成后进行测试,结果接口调用都报了这么个错误: 大概意思是https接口需要证书校验,这就奇怪了,项目启动加载的是包外的application.properties配置文件,配置文件里没有配置使用https啊.本人马上检查了下包内的application.properties配置文件,发现包内确实配置了https相关的配置项: 明明包外的配置文件优先级高于包内的,为

  • C++使用WideCharToMultiByte函数生成UTF-8编码文件的方法

    WideCharToMultiByte函数映射一个unicode字符串到一个多字节字符串. 函数原型: int WideCharToMultiByte UINT CodePage, //指定执行转换的代码页 DWORD dwFlags, //允许你进行额外的控制,它会影响使用了读音符号(比如重音)的字符 LPCWSTR lpWideCharStr, //指定要转换为宽字节字符串的缓冲区 int cchWideChar, //指定由参数lpWideCharStr指向的缓冲区的字符个数 LPSTR

随机推荐