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

效果图:

【注意】Demo已更新到最新版本,并稍作调整。

之前出过一篇 Android选择与上传图片之ImagePicker教程,这个是okgo作者出的,就一般需求来讲是够了,但是没有压缩,需要自己去搞。
后来业务需求提升,页面要美,体验要好,便不是那么满足需求了,所幸在github上找到PictureSelector(然后当时没多久Matisse就开源了…可以看这里 Android选择与上传图片之Matisse教程),也不用自己再撸一个了,下面来介绍介绍PictureSelector

github

https://github.com/LuckSiege/PictureSelector

目前是一直在维护的,支持从相册或拍照选择图片或视频、音频,支持动态权限获取、裁剪(单图or多图裁剪)、压缩、主题自定义配置等功能、适配android 6.0+系统,而且你能遇到的问题,README文档都有解决方案。

功能特点

功能齐全,且兼容性好,作者也做了兼容测试

1.适配android6.0+系统
2.解决部分机型裁剪闪退问题
3.解决图片过大oom闪退问题
4.动态获取系统权限,避免闪退
5.支持相片or视频的单选和多选
6.支持裁剪比例设置,如常用的 1:1、3:4、3:2、16:9 默认为图片大小
7.支持视频预览
8.支持gif图片
9.支持.webp格式图片
10.支持一些常用场景设置:如:是否裁剪、是否预览图片、是否显示相机等
11.新增自定义主题设置
12.新增图片勾选样式设置
13.新增图片裁剪宽高设置
14.新增图片压缩处理
15.新增录视频最大时间设置
16.新增视频清晰度设置
17.新增QQ选择风格,带数字效果
18.新增自定义 文字颜色 背景色让风格和项目更搭配
19.新增多图裁剪功能
20.新增LuBan多图压缩
21.新增单独拍照功能
22.新增压缩大小设置
23.新增Luban压缩档次设置
24.新增圆形头像裁剪
25.新增音频功能查询

主题配置

这个就想怎么改就怎么改了

<!--默认样式 注意* 样式只可修改,不能删除任何一项 否则报错-->
    <style name="picture.default.style" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <!--标题栏背景色-->
        <item name="colorPrimary">@color/bar_grey</item>
        <!--状态栏背景色-->
        <item name="colorPrimaryDark">@color/bar_grey</item>
        <!--是否改变图片列表界面状态栏字体颜色为黑色-->
        <item name="picture.statusFontColor">false</item>
        <!--返回键图标-->
        <item name="picture.leftBack.icon">@drawable/picture_back</item>
        <!--标题下拉箭头-->
        <item name="picture.arrow_down.icon">@drawable/arrow_down</item>
        <!--标题上拉箭头-->
        <item name="picture.arrow_up.icon">@drawable/arrow_up</item>
        <!--标题文字颜色-->
        <item name="picture.title.textColor">@color/white</item>
        <!--标题栏右边文字-->
        <item name="picture.right.textColor">@color/white</item>
        <!--图片列表勾选样式-->
        <item name="picture.checked.style">@drawable/checkbox_selector</item>
        <!--开启图片列表勾选数字模式-->
        <item name="picture.style.checkNumMode">false</item>
        <!--选择图片样式0/9-->
        <item name="picture.style.numComplete">false</item>
        <!--图片列表底部背景色-->
        <item name="picture.bottom.bg">@color/color_fa</item>
        <!--图片列表预览文字颜色-->
        <item name="picture.preview.textColor">@color/tab_color_true</item>
        <!--图片列表已完成文字颜色-->
        <item name="picture.complete.textColor">@color/tab_color_true</item>
        <!--图片已选数量圆点背景色-->
        <item name="picture.num.style">@drawable/num_oval</item>
        <!--预览界面标题文字颜色-->
        <item name="picture.ac_preview.title.textColor">@color/white</item>
        <!--预览界面已完成文字颜色-->
        <item name="picture.ac_preview.complete.textColor">@color/tab_color_true</item>
        <!--预览界面标题栏背景色-->
        <item name="picture.ac_preview.title.bg">@color/bar_grey</item>
        <!--预览界面底部背景色-->
        <item name="picture.ac_preview.bottom.bg">@color/bar_grey_90</item>
        <!--预览界面状态栏颜色-->
        <item name="picture.status.color">@color/bar_grey_90</item>
        <!--预览界面返回箭头-->
        <item name="picture.preview.leftBack.icon">@drawable/picture_back</item>
        <!--是否改变预览界面状态栏字体颜色为黑色-->
        <item name="picture.preview.statusFontColor">false</item>
        <!--裁剪页面标题背景色-->
        <item name="picture.crop.toolbar.bg">@color/bar_grey</item>
        <!--裁剪页面状态栏颜色-->
        <item name="picture.crop.status.color">@color/bar_grey</item>
        <!--裁剪页面标题文字颜色-->
        <item name="picture.crop.title.color">@color/white</item>
        <!--相册文件夹列表选中图标-->
        <item name="picture.folder_checked_dot">@drawable/orange_oval</item>
    </style>

功能配置

// 进入相册 以下是例子:用不到的api可以不写
 PictureSelector.create(MainActivity.this)
 	.openGallery()//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio()
 	.theme()//主题样式(不设置为默认样式) 也可参考demo values/styles下 例如:R.style.picture.white.style
 	.maxSelectNum()// 最大图片选择数量 int
 	.minSelectNum()// 最小选择数量 int
	.imageSpanCount(4)// 每行显示个数 int
 	.selectionMode()// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
 	.previewImage()// 是否可预览图片 true or false
 	.previewVideo()// 是否可预览视频 true or false
	.enablePreviewAudio() // 是否可播放音频 true or false
 	.isCamera()// 是否显示拍照按钮 true or false
	.imageFormat(PictureMimeType.PNG)// 拍照保存图片格式后缀,默认jpeg
	.isZoomAnim(true)// 图片列表点击 缩放效果 默认true
	.sizeMultiplier(0.5f)// glide 加载图片大小 0~1之间 如设置 .glideOverride()无效
	.setOutputCameraPath("/CustomPath")// 自定义拍照保存路径,可不填
 	.enableCrop()// 是否裁剪 true or false
 	.compress()// 是否压缩 true or false
 	.glideOverride()// int glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度
 	.withAspectRatio()// int 裁剪比例 如16:9 3:2 3:4 1:1 可自定义
 	.hideBottomControls()// 是否显示uCrop工具栏,默认不显示 true or false
 	.isGif()// 是否显示gif图片 true or false
	.compressSavePath(getPath())//压缩图片保存地址
 	.freeStyleCropEnabled()// 裁剪框是否可拖拽 true or false
 	.circleDimmedLayer()// 是否圆形裁剪 true or false
 	.showCropFrame()// 是否显示裁剪矩形边框 圆形裁剪时建议设为false   true or false
 	.showCropGrid()// 是否显示裁剪矩形网格 圆形裁剪时建议设为false    true or false
 	.openClickSound()// 是否开启点击声音 true or false
 	.selectionMedia()// 是否传入已选图片 List<LocalMedia> list
 	.previewEggs()// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中) true or false
 	.cropCompressQuality()// 裁剪压缩质量 默认90 int
 	.minimumCompressSize(100)// 小于100kb的图片不压缩
 	.synOrAsy(true)//同步true或异步false 压缩 默认同步
 	.cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效 int
 	.rotateEnabled() // 裁剪是否可旋转图片 true or false
 	.scaleEnabled()// 裁剪是否可放大缩小图片 true or false
 	.videoQuality()// 视频录制质量 0 or 1 int
	.videoMaxSecond(15)// 显示多少秒以内的视频or音频也可适用 int
    .videoMinSecond(10)// 显示多少秒以内的视频or音频也可适用 int
	.recordVideoSecond()//视频秒数录制 默认60s int
	.isDragFrame(false)// 是否可拖动裁剪框(固定)
 	.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code

集成方式

compile引入

dependencies {
    implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.2.3'
}

build.gradle加入

allprojects {
   repositories {
      jcenter()
      maven { url 'https://jitpack.io' }
   }
}

使用

使用非常简单,你想要的基本上都有

package com.yechaoa.pictureselectordemo;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
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.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;

import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
import com.luck.picture.lib.permissions.Permission;
import com.luck.picture.lib.permissions.RxPermissions;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.functions.Consumer;

public class MainActivity extends AppCompatActivity {

    private int maxSelectNum = 9;
    private List<LocalMedia> selectList = new ArrayList<>();
    private GridImageAdapter adapter;
    private RecyclerView mRecyclerView;
    private PopupWindow pop;

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

        mRecyclerView = findViewById(R.id.recycler);

        initWidget();
    }

    private void initWidget() {
        FullyGridLayoutManager manager = new FullyGridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false);
        mRecyclerView.setLayoutManager(manager);
        adapter = new GridImageAdapter(this, onAddPicClickListener);
        adapter.setList(selectList);
        adapter.setSelectMax(maxSelectNum);
        mRecyclerView.setAdapter(adapter);
        adapter.setOnItemClickListener(new GridImageAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(int position, View v) {
                if (selectList.size() > 0) {
                    LocalMedia media = selectList.get(position);
                    String pictureType = media.getPictureType();
                    int mediaType = PictureMimeType.pictureToVideo(pictureType);
                    switch (mediaType) {
                        case 1:
                            // 预览图片 可自定长按保存路径
                            //PictureSelector.create(MainActivity.this).externalPicturePreview(position, "/custom_file", selectList);
                            PictureSelector.create(MainActivity.this).externalPicturePreview(position, selectList);
                            break;
                        case 2:
                            // 预览视频
                            PictureSelector.create(MainActivity.this).externalPictureVideo(media.getPath());
                            break;
                        case 3:
                            // 预览音频
                            PictureSelector.create(MainActivity.this).externalPictureAudio(media.getPath());
                            break;
                    }
                }
            }
        });
    }

    private GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() {

        @SuppressLint("CheckResult")
        @Override
        public void onAddPicClick() {
            //获取写的权限
            RxPermissions rxPermission = new RxPermissions(MainActivity.this);
            rxPermission.requestEach(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    .subscribe(new Consumer<Permission>() {
                        @Override
                        public void accept(Permission permission) {
                            if (permission.granted) {// 用户已经同意该权限
                                //第一种方式,弹出选择和拍照的dialog
                                showPop();

                                //第二种方式,直接进入相册,但是 是有拍照得按钮的
//                                showAlbum();
                            } else {
                                Toast.makeText(MainActivity.this, "拒绝", Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
        }
    };

    private void showAlbum() {
        //参数很多,根据需要添加
        PictureSelector.create(MainActivity.this)
                .openGallery(PictureMimeType.ofImage())// 全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio()
                .maxSelectNum(maxSelectNum)// 最大图片选择数量
                .minSelectNum(1)// 最小选择数量
                .imageSpanCount(4)// 每行显示个数
                .selectionMode(PictureConfig.MULTIPLE)// 多选 or 单选PictureConfig.MULTIPLE : PictureConfig.SINGLE
                .previewImage(true)// 是否可预览图片
                .isCamera(true)// 是否显示拍照按钮
                .isZoomAnim(true)// 图片列表点击 缩放效果 默认true
                //.setOutputCameraPath("/CustomPath")// 自定义拍照保存路径
                .enableCrop(true)// 是否裁剪
                .compress(true)// 是否压缩
                //.sizeMultiplier(0.5f)// glide 加载图片大小 0~1之间 如设置 .glideOverride()无效
                .glideOverride(160, 160)// glide 加载宽高,越小图片列表越流畅,但会影响列表图片浏览的清晰度
                .withAspectRatio(1, 1)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义
                //.selectionMedia(selectList)// 是否传入已选图片
                //.previewEggs(false)// 预览图片时 是否增强左右滑动图片体验(图片滑动一半即可看到上一张是否选中)
                //.cropCompressQuality(90)// 裁剪压缩质量 默认100
                //.compressMaxKB()//压缩最大值kb compressGrade()为Luban.CUSTOM_GEAR有效
                //.compressWH() // 压缩宽高比 compressGrade()为Luban.CUSTOM_GEAR有效
                //.cropWH()// 裁剪宽高比,设置如果大于图片本身宽高则无效
                .rotateEnabled(false) // 裁剪是否可旋转图片
                //.scaleEnabled()// 裁剪是否可放大缩小图片
                //.recordVideoSecond()//录制视频秒数 默认60s
                .forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code
    }

    private void showPop() {
        View bottomView = View.inflate(MainActivity.this, R.layout.layout_bottom_dialog, null);
        TextView mAlbum = bottomView.findViewById(R.id.tv_album);
        TextView mCamera = bottomView.findViewById(R.id.tv_camera);
        TextView mCancel = bottomView.findViewById(R.id.tv_cancel);

        pop = new PopupWindow(bottomView, -1, -2);
        pop.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        pop.setOutsideTouchable(true);
        pop.setFocusable(true);
        WindowManager.LayoutParams lp = getWindow().getAttributes();
        lp.alpha = 0.5f;
        getWindow().setAttributes(lp);
        pop.setOnDismissListener(new PopupWindow.OnDismissListener() {

            @Override
            public void onDismiss() {
                WindowManager.LayoutParams lp = getWindow().getAttributes();
                lp.alpha = 1f;
                getWindow().setAttributes(lp);
            }
        });
        pop.setAnimationStyle(R.style.main_menu_photo_anim);
        pop.showAtLocation(getWindow().getDecorView(), Gravity.BOTTOM, 0, 0);

        View.OnClickListener clickListener = new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                switch (view.getId()) {
                    case R.id.tv_album:
                        //相册
                        PictureSelector.create(MainActivity.this)
                                .openGallery(PictureMimeType.ofImage())
                                .maxSelectNum(maxSelectNum)
                                .minSelectNum(1)
                                .imageSpanCount(4)
                                .selectionMode(PictureConfig.MULTIPLE)
                                .forResult(PictureConfig.CHOOSE_REQUEST);
                        break;
                    case R.id.tv_camera:
                        //拍照
                        PictureSelector.create(MainActivity.this)
                                .openCamera(PictureMimeType.ofImage())
                                .forResult(PictureConfig.CHOOSE_REQUEST);
                        break;
                    case R.id.tv_cancel:
                        //取消
                        //closePopupWindow();
                        break;
                }
                closePopupWindow();
            }
        };

        mAlbum.setOnClickListener(clickListener);
        mCamera.setOnClickListener(clickListener);
        mCancel.setOnClickListener(clickListener);
    }

    public void closePopupWindow() {
        if (pop != null && pop.isShowing()) {
            pop.dismiss();
            pop = null;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        List<LocalMedia> images;
        if (resultCode == RESULT_OK) {
            if (requestCode == PictureConfig.CHOOSE_REQUEST) {// 图片选择结果回调

                images = PictureSelector.obtainMultipleResult(data);
                selectList.addAll(images);

                //selectList = PictureSelector.obtainMultipleResult(data);

                // 例如 LocalMedia 里面返回三种path
                // 1.media.getPath(); 为原图path
                // 2.media.getCutPath();为裁剪后path,需判断media.isCut();是否为true
                // 3.media.getCompressPath();为压缩后path,需判断media.isCompressed();是否为true
                // 如果裁剪并压缩了,以取压缩路径为准,因为是先裁剪后压缩的
                adapter.setList(selectList);
                adapter.notifyDataSetChanged();
            }
        }
    }

}

Demo下载地址:点此下载

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

(0)

相关推荐

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

    效果图: 就目前效果图来看,好像也没什么毛病哈,其实我这个集成的过程是有点坎坷的. 而且,功能也不算是很齐全吧-主要体现在以下几个点 没有回调之后的预览 选择之后不能删除已选 已选择的图片再次选择不能带过去 剪裁 压缩 权限 Glide版本过低 但是,也是有特点的 MD风格 白天模式和夜间模式 其他与同类相比也真的没什么了,唯一背书 就是知乎团队出的呗.. 相比之下,昨天出的Android选择与上传图片之PictureSelector教程就更加友好和人性化了. 下面来说说集成遇到的问题以及解决方

  • C语言MultiByteToWideChar和WideCharToMultiByte案例详解

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

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

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

  • 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

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

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

  • 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

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

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

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

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

  • 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

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

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

随机推荐