Android選擇與上傳圖片之PictureSelector教程
效果圖:




【注意】Demo已更新到最新版本,并稍作調(diào)整。
之前出過一篇 Android選擇與上傳圖片之ImagePicker教程,這個是okgo作者出的,就一般需求來講是夠了,但是沒有壓縮,需要自己去搞。
后來業(yè)務(wù)需求提升,頁面要美,體驗要好,便不是那么滿足需求了,所幸在github上找到PictureSelector(然后當時沒多久Matisse就開源了…可以看這里 Android選擇與上傳圖片之Matisse教程),也不用自己再擼一個了,下面來介紹介紹PictureSelector
github
https://github.com/LuckSiege/PictureSelector
目前是一直在維護的,支持從相冊或拍照選擇圖片或視頻、音頻,支持動態(tài)權(quán)限獲取、裁剪(單圖or多圖裁剪)、壓縮、主題自定義配置等功能、適配android 6.0+系統(tǒng),而且你能遇到的問題,README文檔都有解決方案。
功能特點
功能齊全,且兼容性好,作者也做了兼容測試
1.適配android6.0+系統(tǒng)
2.解決部分機型裁剪閃退問題
3.解決圖片過大oom閃退問題
4.動態(tài)獲取系統(tǒng)權(quán)限,避免閃退
5.支持相片or視頻的單選和多選
6.支持裁剪比例設(shè)置,如常用的 1:1、3:4、3:2、16:9 默認為圖片大小
7.支持視頻預(yù)覽
8.支持gif圖片
9.支持.webp格式圖片
10.支持一些常用場景設(shè)置:如:是否裁剪、是否預(yù)覽圖片、是否顯示相機等
11.新增自定義主題設(shè)置
12.新增圖片勾選樣式設(shè)置
13.新增圖片裁剪寬高設(shè)置
14.新增圖片壓縮處理
15.新增錄視頻最大時間設(shè)置
16.新增視頻清晰度設(shè)置
17.新增QQ選擇風格,帶數(shù)字效果
18.新增自定義 文字顏色 背景色讓風格和項目更搭配
19.新增多圖裁剪功能
20.新增LuBan多圖壓縮
21.新增單獨拍照功能
22.新增壓縮大小設(shè)置
23.新增Luban壓縮檔次設(shè)置
24.新增圓形頭像裁剪
25.新增音頻功能查詢
主題配置
這個就想怎么改就怎么改了
<!--默認樣式 注意* 樣式只可修改,不能刪除任何一項 否則報錯-->
<style name="picture.default.style" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<!--標題欄背景色-->
<item name="colorPrimary">@color/bar_grey</item>
<!--狀態(tài)欄背景色-->
<item name="colorPrimaryDark">@color/bar_grey</item>
<!--是否改變圖片列表界面狀態(tài)欄字體顏色為黑色-->
<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>
<!--開啟圖片列表勾選數(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ù)量圓點背景色-->
<item name="picture.num.style">@drawable/num_oval</item>
<!--預(yù)覽界面標題文字顏色-->
<item name="picture.ac_preview.title.textColor">@color/white</item>
<!--預(yù)覽界面已完成文字顏色-->
<item name="picture.ac_preview.complete.textColor">@color/tab_color_true</item>
<!--預(yù)覽界面標題欄背景色-->
<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>
<!--裁剪頁面標題背景色-->
<item name="picture.crop.toolbar.bg">@color/bar_grey</item>
<!--裁剪頁面狀態(tài)欄顏色-->
<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()//主題樣式(不設(shè)置為默認樣式) 也可參考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)// 拍照保存圖片格式后綴,默認jpeg
.isZoomAnim(true)// 圖片列表點擊 縮放效果 默認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工具欄,默認不顯示 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()// 是否開啟點擊聲音 true or false
.selectionMedia()// 是否傳入已選圖片 List<LocalMedia> list
.previewEggs()// 預(yù)覽圖片時 是否增強左右滑動圖片體驗(圖片滑動一半即可看到上一張是否選中) true or false
.cropCompressQuality()// 裁剪壓縮質(zhì)量 默認90 int
.minimumCompressSize(100)// 小于100kb的圖片不壓縮
.synOrAsy(true)//同步true或異步false 壓縮 默認同步
.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ù)錄制 默認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();
//第二種方式,直接進入相冊,但是 是有拍照得按鈕的
// 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)// 圖片列表點擊 縮放效果 默認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ù)覽圖片時 是否增強左右滑動圖片體驗(圖片滑動一半即可看到上一張是否選中)
//.cropCompressQuality(90)// 裁剪壓縮質(zhì)量 默認100
//.compressMaxKB()//壓縮最大值kb compressGrade()為Luban.CUSTOM_GEAR有效
//.compressWH() // 壓縮寬高比 compressGrade()為Luban.CUSTOM_GEAR有效
//.cropWH()// 裁剪寬高比,設(shè)置如果大于圖片本身寬高則無效
.rotateEnabled(false) // 裁剪是否可旋轉(zhuǎn)圖片
//.scaleEnabled()// 裁剪是否可放大縮小圖片
//.recordVideoSecond()//錄制視頻秒數(shù) 默認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
// 如果裁剪并壓縮了,以取壓縮路徑為準,因為是先裁剪后壓縮的
adapter.setList(selectList);
adapter.notifyDataSetChanged();
}
}
}
}
Demo下載地址:點此下載
到此這篇關(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實現(xiàn)特征檢測和特征匹配方法匯總
- easycom模式開發(fā)UNI-APP組件調(diào)用必須掌握的實用技巧
- C語言MultiByteToWideChar和WideCharToMultiByte案例詳解
- Android選擇與上傳圖片之ImagePicker教程
- Android選擇與上傳圖片之Matisse教程
相關(guān)文章
android RecyclerView添加footerview詳解
大家好,本篇文章主要講的是android RecyclerView添加footerview詳解,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01
Android開發(fā)實現(xiàn)帶有反彈效果仿IOS反彈scrollview教程詳解
本文給大家分享android開發(fā)實現(xiàn)帶有反彈效果,模仿ios反彈scrollview詳細教程,本文介紹的非常詳細,具有參考借鑒價值,感興趣的朋友一起看看吧2016-09-09
Android通過命令連接wifi的方法(解決usb不能用問題)
這篇文章主要介紹了Android通過命令連接wifi的方法(解決usb不能用的情況),本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02
Android性能優(yōu)化之ViewPagers?+?Fragment緩存優(yōu)化
這篇文章主要介紹了Android性能優(yōu)化之ViewPagers+Fragment緩存優(yōu)化,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08
Android 實現(xiàn)按兩次返回鍵退出程序(兩種方法)
這篇文章主要介紹了Android 實現(xiàn)按兩次返回鍵退出程序(兩種方法)的相關(guān)資料,這里不僅實現(xiàn)還對原理進行了分析,需要的朋友可以參考下2017-07-07

