Android選擇與上傳圖片之PictureSelector教程
效果圖:
【注意】Demo已更新到最新版本,并稍作調(diào)整。
之前出過一篇 Android選擇與上傳圖片之ImagePicker教程,這個是okgo作者出的,就一般需求來講是夠了,但是沒有壓縮,需要自己去搞。
后來業(yè)務(wù)需求提升,頁面要美,體驗(yàn)要好,便不是那么滿足需求了,所幸在github上找到PictureSelector(然后當(dāng)時沒多久Matisse就開源了…可以看這里 Android選擇與上傳圖片之Matisse教程),也不用自己再擼一個了,下面來介紹介紹PictureSelector
github
https://github.com/LuckSiege/PictureSelector
目前是一直在維護(hù)的,支持從相冊或拍照選擇圖片或視頻、音頻,支持動態(tài)權(quán)限獲取、裁剪(單圖or多圖裁剪)、壓縮、主題自定義配置等功能、適配android 6.0+系統(tǒng),而且你能遇到的問題,README文檔都有解決方案。
功能特點(diǎn)
功能齊全,且兼容性好,作者也做了兼容測試
1.適配android6.0+系統(tǒng)
2.解決部分機(jī)型裁剪閃退問題
3.解決圖片過大oom閃退問題
4.動態(tài)獲取系統(tǒng)權(quán)限,避免閃退
5.支持相片or視頻的單選和多選
6.支持裁剪比例設(shè)置,如常用的 1:1、3:4、3:2、16:9 默認(rèn)為圖片大小
7.支持視頻預(yù)覽
8.支持gif圖片
9.支持.webp格式圖片
10.支持一些常用場景設(shè)置:如:是否裁剪、是否預(yù)覽圖片、是否顯示相機(jī)等
11.新增自定義主題設(shè)置
12.新增圖片勾選樣式設(shè)置
13.新增圖片裁剪寬高設(shè)置
14.新增圖片壓縮處理
15.新增錄視頻最大時間設(shè)置
16.新增視頻清晰度設(shè)置
17.新增QQ選擇風(fēng)格,帶數(shù)字效果
18.新增自定義 文字顏色 背景色讓風(fēng)格和項(xiàng)目更搭配
19.新增多圖裁剪功能
20.新增LuBan多圖壓縮
21.新增單獨(dú)拍照功能
22.新增壓縮大小設(shè)置
23.新增Luban壓縮檔次設(shè)置
24.新增圓形頭像裁剪
25.新增音頻功能查詢
主題配置
這個就想怎么改就怎么改了
<!--默認(rèn)樣式 注意* 樣式只可修改,不能刪除任何一項(xiàng) 否則報(bào)錯--> <style name="picture.default.style" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <!--標(biāo)題欄背景色--> <item name="colorPrimary">@color/bar_grey</item> <!--狀態(tài)欄背景色--> <item name="colorPrimaryDark">@color/bar_grey</item> <!--是否改變圖片列表界面狀態(tài)欄字體顏色為黑色--> <item name="picture.statusFontColor">false</item> <!--返回鍵圖標(biāo)--> <item name="picture.leftBack.icon">@drawable/picture_back</item> <!--標(biāo)題下拉箭頭--> <item name="picture.arrow_down.icon">@drawable/arrow_down</item> <!--標(biāo)題上拉箭頭--> <item name="picture.arrow_up.icon">@drawable/arrow_up</item> <!--標(biāo)題文字顏色--> <item name="picture.title.textColor">@color/white</item> <!--標(biāo)題欄右邊文字--> <item name="picture.right.textColor">@color/white</item> <!--圖片列表勾選樣式--> <item name="picture.checked.style">@drawable/checkbox_selector</item> <!--開啟圖片列表勾選數(shù)字模式--> <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> <!--圖片列表預(yù)覽文字顏色--> <item name="picture.preview.textColor">@color/tab_color_true</item> <!--圖片列表已完成文字顏色--> <item name="picture.complete.textColor">@color/tab_color_true</item> <!--圖片已選數(shù)量圓點(diǎn)背景色--> <item name="picture.num.style">@drawable/num_oval</item> <!--預(yù)覽界面標(biāo)題文字顏色--> <item name="picture.ac_preview.title.textColor">@color/white</item> <!--預(yù)覽界面已完成文字顏色--> <item name="picture.ac_preview.complete.textColor">@color/tab_color_true</item> <!--預(yù)覽界面標(biāo)題欄背景色--> <item name="picture.ac_preview.title.bg">@color/bar_grey</item> <!--預(yù)覽界面底部背景色--> <item name="picture.ac_preview.bottom.bg">@color/bar_grey_90</item> <!--預(yù)覽界面狀態(tài)欄顏色--> <item name="picture.status.color">@color/bar_grey_90</item> <!--預(yù)覽界面返回箭頭--> <item name="picture.preview.leftBack.icon">@drawable/picture_back</item> <!--是否改變預(yù)覽界面狀態(tài)欄字體顏色為黑色--> <item name="picture.preview.statusFontColor">false</item> <!--裁剪頁面標(biāo)題背景色--> <item name="picture.crop.toolbar.bg">@color/bar_grey</item> <!--裁剪頁面狀態(tài)欄顏色--> <item name="picture.crop.status.color">@color/bar_grey</item> <!--裁剪頁面標(biāo)題文字顏色--> <item name="picture.crop.title.color">@color/white</item> <!--相冊文件夾列表選中圖標(biāo)--> <item name="picture.folder_checked_dot">@drawable/orange_oval</item> </style>
功能配置
// 進(jìn)入相冊 以下是例子:用不到的api可以不寫 PictureSelector.create(MainActivity.this) .openGallery()//全部.PictureMimeType.ofAll()、圖片.ofImage()、視頻.ofVideo()、音頻.ofAudio() .theme()//主題樣式(不設(shè)置為默認(rèn)樣式) 也可參考demo values/styles下 例如:R.style.picture.white.style .maxSelectNum()// 最大圖片選擇數(shù)量 int .minSelectNum()// 最小選擇數(shù)量 int .imageSpanCount(4)// 每行顯示個數(shù) int .selectionMode()// 多選 or 單選 PictureConfig.MULTIPLE or PictureConfig.SINGLE .previewImage()// 是否可預(yù)覽圖片 true or false .previewVideo()// 是否可預(yù)覽視頻 true or false .enablePreviewAudio() // 是否可播放音頻 true or false .isCamera()// 是否顯示拍照按鈕 true or false .imageFormat(PictureMimeType.PNG)// 拍照保存圖片格式后綴,默認(rèn)jpeg .isZoomAnim(true)// 圖片列表點(diǎn)擊 縮放效果 默認(rèn)true .sizeMultiplier(0.5f)// glide 加載圖片大小 0~1之間 如設(shè)置 .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工具欄,默認(rèn)不顯示 true or false .isGif()// 是否顯示gif圖片 true or false .compressSavePath(getPath())//壓縮圖片保存地址 .freeStyleCropEnabled()// 裁剪框是否可拖拽 true or false .circleDimmedLayer()// 是否圓形裁剪 true or false .showCropFrame()// 是否顯示裁剪矩形邊框 圓形裁剪時建議設(shè)為false true or false .showCropGrid()// 是否顯示裁剪矩形網(wǎng)格 圓形裁剪時建議設(shè)為false true or false .openClickSound()// 是否開啟點(diǎn)擊聲音 true or false .selectionMedia()// 是否傳入已選圖片 List<LocalMedia> list .previewEggs()// 預(yù)覽圖片時 是否增強(qiáng)左右滑動圖片體驗(yàn)(圖片滑動一半即可看到上一張是否選中) true or false .cropCompressQuality()// 裁剪壓縮質(zhì)量 默認(rèn)90 int .minimumCompressSize(100)// 小于100kb的圖片不壓縮 .synOrAsy(true)//同步true或異步false 壓縮 默認(rèn)同步 .cropWH()// 裁剪寬高比,設(shè)置如果大于圖片本身寬高則無效 int .rotateEnabled() // 裁剪是否可旋轉(zhuǎn)圖片 true or false .scaleEnabled()// 裁剪是否可放大縮小圖片 true or false .videoQuality()// 視頻錄制質(zhì)量 0 or 1 int .videoMaxSecond(15)// 顯示多少秒以內(nèi)的視頻or音頻也可適用 int .videoMinSecond(10)// 顯示多少秒以內(nèi)的視頻or音頻也可適用 int .recordVideoSecond()//視頻秒數(shù)錄制 默認(rèn)60s int .isDragFrame(false)// 是否可拖動裁剪框(固定) .forResult(PictureConfig.CHOOSE_REQUEST);//結(jié)果回調(diào)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: // 預(yù)覽圖片 可自定長按保存路徑 //PictureSelector.create(MainActivity.this).externalPicturePreview(position, "/custom_file", selectList); PictureSelector.create(MainActivity.this).externalPicturePreview(position, selectList); break; case 2: // 預(yù)覽視頻 PictureSelector.create(MainActivity.this).externalPictureVideo(media.getPath()); break; case 3: // 預(yù)覽音頻 PictureSelector.create(MainActivity.this).externalPictureAudio(media.getPath()); break; } } } }); } private GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() { @SuppressLint("CheckResult") @Override public void onAddPicClick() { //獲取寫的權(quán)限 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) {// 用戶已經(jīng)同意該權(quán)限 //第一種方式,彈出選擇和拍照的dialog showPop(); //第二種方式,直接進(jìn)入相冊,但是 是有拍照得按鈕的 // showAlbum(); } else { Toast.makeText(MainActivity.this, "拒絕", Toast.LENGTH_SHORT).show(); } } }); } }; private void showAlbum() { //參數(shù)很多,根據(jù)需要添加 PictureSelector.create(MainActivity.this) .openGallery(PictureMimeType.ofImage())// 全部.PictureMimeType.ofAll()、圖片.ofImage()、視頻.ofVideo()、音頻.ofAudio() .maxSelectNum(maxSelectNum)// 最大圖片選擇數(shù)量 .minSelectNum(1)// 最小選擇數(shù)量 .imageSpanCount(4)// 每行顯示個數(shù) .selectionMode(PictureConfig.MULTIPLE)// 多選 or 單選PictureConfig.MULTIPLE : PictureConfig.SINGLE .previewImage(true)// 是否可預(yù)覽圖片 .isCamera(true)// 是否顯示拍照按鈕 .isZoomAnim(true)// 圖片列表點(diǎn)擊 縮放效果 默認(rèn)true //.setOutputCameraPath("/CustomPath")// 自定義拍照保存路徑 .enableCrop(true)// 是否裁剪 .compress(true)// 是否壓縮 //.sizeMultiplier(0.5f)// glide 加載圖片大小 0~1之間 如設(shè)置 .glideOverride()無效 .glideOverride(160, 160)// glide 加載寬高,越小圖片列表越流暢,但會影響列表圖片瀏覽的清晰度 .withAspectRatio(1, 1)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定義 //.selectionMedia(selectList)// 是否傳入已選圖片 //.previewEggs(false)// 預(yù)覽圖片時 是否增強(qiáng)左右滑動圖片體驗(yàn)(圖片滑動一半即可看到上一張是否選中) //.cropCompressQuality(90)// 裁剪壓縮質(zhì)量 默認(rèn)100 //.compressMaxKB()//壓縮最大值kb compressGrade()為Luban.CUSTOM_GEAR有效 //.compressWH() // 壓縮寬高比 compressGrade()為Luban.CUSTOM_GEAR有效 //.cropWH()// 裁剪寬高比,設(shè)置如果大于圖片本身寬高則無效 .rotateEnabled(false) // 裁剪是否可旋轉(zhuǎn)圖片 //.scaleEnabled()// 裁剪是否可放大縮小圖片 //.recordVideoSecond()//錄制視頻秒數(shù) 默認(rèn)60s .forResult(PictureConfig.CHOOSE_REQUEST);//結(jié)果回調(diào)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) {// 圖片選擇結(jié)果回調(diào) 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 // 如果裁剪并壓縮了,以取壓縮路徑為準(zhǔn),因?yàn)槭窍炔眉艉髩嚎s的 adapter.setList(selectList); adapter.notifyDataSetChanged(); } } } }
Demo下載地址:點(diǎn)此下載
到此這篇關(guān)于Android選擇與上傳圖片之PictureSelector教程的文章就介紹到這了,更多相關(guān)Android圖片選擇上傳PictureSelector內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++使用WideCharToMultiByte函數(shù)生成UTF-8編碼文件的方法
- SpringCloud2020.0.x版UnderTow AccessLog相關(guān)配置簡介
- 解決SpringBoot加載application.properties配置文件的坑
- C語言container of()函數(shù)案例詳解
- gaussdb 200安裝 data studio jdbc idea鏈接保姆級安裝步驟
- OpenCV實(shí)現(xiàn)特征檢測和特征匹配方法匯總
- easycom模式開發(fā)UNI-APP組件調(diào)用必須掌握的實(shí)用技巧
- C語言MultiByteToWideChar和WideCharToMultiByte案例詳解
- Android選擇與上傳圖片之ImagePicker教程
- Android選擇與上傳圖片之Matisse教程
相關(guān)文章
android RecyclerView添加footerview詳解
大家好,本篇文章主要講的是android RecyclerView添加footerview詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01簡單實(shí)現(xiàn)安卓里百度地圖持續(xù)定位
本文主要介紹了在安卓的百度地圖開發(fā)里面簡單實(shí)現(xiàn)持續(xù)定位的方法,具有一定的參考價值,下面跟著小編一起來看下吧2017-01-01Android開發(fā)實(shí)現(xiàn)帶有反彈效果仿IOS反彈scrollview教程詳解
本文給大家分享android開發(fā)實(shí)現(xiàn)帶有反彈效果,模仿ios反彈scrollview詳細(xì)教程,本文介紹的非常詳細(xì),具有參考借鑒價值,感興趣的朋友一起看看吧2016-09-09Android通過命令連接wifi的方法(解決usb不能用問題)
這篇文章主要介紹了Android通過命令連接wifi的方法(解決usb不能用的情況),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02Android性能優(yōu)化之ViewPagers?+?Fragment緩存優(yōu)化
這篇文章主要介紹了Android性能優(yōu)化之ViewPagers+Fragment緩存優(yōu)化,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08Android 實(shí)現(xiàn)按兩次返回鍵退出程序(兩種方法)
這篇文章主要介紹了Android 實(shí)現(xiàn)按兩次返回鍵退出程序(兩種方法)的相關(guān)資料,這里不僅實(shí)現(xiàn)還對原理進(jìn)行了分析,需要的朋友可以參考下2017-07-07