項(xiàng)目開(kāi)發(fā)中碰到了類似微信的圖片選擇肝劲、圖片壓縮及上傳突雪,一開(kāi)始利用一些第三方的進(jìn)行修改闪唆,但是很容就出現(xiàn)內(nèi)存溢出,而有些比較優(yōu)秀的第三方的多半是采用遠(yuǎn)程依賴的方式集成開(kāi)發(fā)的柜与,很難對(duì)源碼進(jìn)行改動(dòng)而達(dá)到自己的需求巧勤,后面在跟大牛的學(xué)習(xí)過(guò)程中,就寫了一個(gè)簡(jiǎn)單的圖片選擇弄匕,已用于項(xiàng)目開(kāi)發(fā)颅悉,并沒(méi)有出現(xiàn)內(nèi)存溢出。
簡(jiǎn)單的對(duì)實(shí)現(xiàn)做一個(gè)說(shuō)明:
1粘茄、圖片壓縮采用的是第三方的魯班圖片壓縮;
魯班圖片壓縮地址:
github:[https://github.com/Curzibn/Luban](https://github.com/Curzibn/Luban)
2秕脓、圖片加載采用的是glide柒瓣;
compile 'com.github.bumptech.glide:glide:3.7.0'
3、圖片展示列表用的是recyclerview實(shí)現(xiàn)的吠架;
compile 'com.android.support:recyclerview-v7:25.3.1'
4芙贫、實(shí)現(xiàn)了多選(可以隨便控制圖片選擇的數(shù)量)、單選傍药、隱藏拍照磺平、刪除、預(yù)覽等功能拐辽;
5拣挪、已對(duì)android6.0讀取和寫入sd權(quán)限做了適配,android7.0訪問(wèn)相機(jī)權(quán)限做了適配俱诸;
效果如下:
圖片壓縮效果:
拍照的原圖(大小是2.59M):
壓縮的效果(75.33kb):
主要代碼實(shí)現(xiàn):
public class MainActivity extends AppCompatActivity {
private static final int PHOTO_CAMERA = 1000;
private static final int DELETE_CODE = 1002;
private final int SELECT_IMAGE_REQUEST = 0x0011;
private ArrayList<String> mImageList = new ArrayList<>();
private ArrayList<String> mRuquestList = new ArrayList<>();
@ViewById(R.id.image_list_rv)
private RecyclerView imageListRv;
private RequestAdapter adapter;
private int maxChoice = 9;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewUtils.inject(this);
adapter = new RequestAdapter(this, mImageList, maxChoice);
imageListRv.setLayoutManager(new GridLayoutManager(MainActivity.this, 4));
imageListRv.setAdapter(adapter);
//設(shè)置分割線
imageListRv.addItemDecoration(new DividerGridItemDecoration(MainActivity.this, R.drawable.item_dirver_02));
adapter.setOnItemClickListener(new ItemClickListener() {
@Override
public void onItemClick(Object obj, int position) {
Log.e("position", "position---->" + position);
if (mImageList.size() == position) {
//動(dòng)態(tài)申請(qǐng)權(quán)限
PermissionHelper.with(MainActivity.this).
requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}).
requestCode(PHOTO_CAMERA).
request();
} else {
//跳轉(zhuǎn)至刪除或者預(yù)覽頁(yè)面
Intent intent = new Intent(MainActivity.this, PreViewActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("choicePosition", position);
bundle.putSerializable("choiceList", mImageList);
intent.putExtras(bundle);
startActivity(intent);
}
}
});
adapter.setOnDeleteClickListener(new DeleteListener() {
@Override
public void onDeleteClick(Object obj, int position) {
removeList(position);
}
});
}
/**
* 刪除圖片
*
* @param position
*/
private void removeList(int position) {
mImageList.remove(position);
adapter.nodfiyData(mImageList);
}
@PermissionSuccess(requestCode = PHOTO_CAMERA)
private void toSelectImageActivity() {
ImageSelector
.create()
.multi()
.count(maxChoice)
.showCamera(true)
.origin(mImageList)
.start(this, SELECT_IMAGE_REQUEST);
}
/**
* 圖片壓縮 這里放在網(wǎng)絡(luò)請(qǐng)求之前做好些菠劝,放在onActivityResult里面每次圖片改動(dòng)都要調(diào)用
* 這里沒(méi)有網(wǎng)絡(luò)請(qǐng)求環(huán)境就放在onActivityResult里面了
*/
private void compressImg() {
if (mRuquestList.size() != 0) {
mRuquestList.clear();
}
// 把選擇好的圖片做了一下壓縮
for (String path : mImageList) {
// 做優(yōu)化 第一個(gè)decodeFile有可能會(huì)內(nèi)存移除
// 一般后臺(tái)會(huì)規(guī)定尺寸 800 小米 規(guī)定了寬度 720
// 上傳的時(shí)候可能會(huì)多張 for循環(huán) 最好用線程池 (2-3)
Bitmap bitmap = ImageUtil.decodeFile(960, path);
// 調(diào)用寫好的native方法
//壓縮存儲(chǔ)的路徑
String imageViewUrl = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +
new File(path).getName();
// 用Bitmap.compress壓縮1/10
ImageUtil.compressBitmap(bitmap, 75, imageViewUrl);
mRuquestList.add(imageViewUrl);
}
adapter.nodfiyData(mImageList);
Log.e("mRuquestList", "mRuquestList----->" + mRuquestList.size());
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_IMAGE_REQUEST && data != null) {
mImageList = (ArrayList<String>) data.getSerializableExtra(SelectImageActivity.EXTRA_DEFAULT_SELECTED_LIST);
adapter.nodfiyData(mImageList);
}
}
}
/**
* 壓縮點(diǎn)擊事件
*
* @param view
*/
public void tvCompress(View view) {
compressImageView();
}
/**
* 使用魯班壓縮圖片
* 在子線程中開(kāi)啟圖片壓縮
*/
private void compressImageView() {
new Thread(new Runnable() {
@Override
public void run() {
if (mRuquestList.size() != 0) {
mRuquestList.clear();
}
for (String s : mImageList) {
if (s == null) {
s = "";
}
File file = new File(s);
Luban.with(MainActivity.this)
.load(file)//傳入要壓縮的圖片 這里采用的是單張壓縮 也可以采用多張壓縮
.ignoreBy(100) // 忽略不壓縮圖片的大小 如果原圖片小于100kb不會(huì)進(jìn)行壓縮
// .putGear(Luban.Builder.)//設(shè)定壓縮檔次,默認(rèn)三擋
.setCompressListener(new OnCompressListener() { //設(shè)置回調(diào)
@Override
public void onStart() {
// TODO 壓縮開(kāi)始前調(diào)用睁搭,可以在方法內(nèi)啟動(dòng) loading UI
}
@Override
public void onSuccess(File file) {
// TODO 壓縮成功后調(diào)用赶诊,返回壓縮后的圖片文件
String absolutePath = file.getAbsolutePath();
mRuquestList.add(absolutePath);
}
@Override
public void onError(Throwable e) {
// TODO 當(dāng)壓縮過(guò)程出現(xiàn)問(wèn)題時(shí)調(diào)用
}
}).launch(); //啟動(dòng)壓縮
}
}
}).start();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionHelper.requestPermissionsResult(this, requestCode, permissions, grantResults);
}
}
MainActivity類中主要是讀取和寫入sd卡權(quán)限的申請(qǐng)笼平、選擇圖片的入口函數(shù)、選擇圖片后的展示舔痪、圖片刪除寓调、圖片預(yù)覽入口、圖片壓縮等锄码。
public class RequestAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<String> mRequestList;
private int mMaxNumber;
private Context mContext;
public RequestAdapter(Context context,ArrayList<String> requestList,int maxNumber){
this.mContext=context;
this.mMaxNumber=maxNumber;
this.mRequestList = new ArrayList<String>();
if(mRequestList!=null)
{
this.mRequestList.addAll(requestList);
}
}
public void nodfiyData(List<String> list){
if(list!=null)
{
this.mRequestList.clear();
this.mRequestList.addAll(list);
}
notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.request_chooser_item, parent, false);
return new Holder(view);
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
Holder holder = (Holder) viewHolder;
if(position==mRequestList.size()){
holder.ivDelete.setVisibility(View.GONE);
int resourceId = R.drawable.icon_addpic_unfocused;
//顯示圖片 利用Glide centerCrop()
Glide.with(mContext).load(resourceId).centerCrop().into(holder.image);
if(position==mMaxNumber){
holder.image.setVisibility(View.GONE);
}
}else{
holder.ivDelete.setVisibility(View.VISIBLE);
//顯示圖片 利用Glide centerCrop()
Glide.with(mContext).load(mRequestList.get(position)).centerCrop().into(holder.image);
}
//條目點(diǎn)擊事件
if(mItemClickListener!=null){
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(position==mMaxNumber){
return;
}
if(mRequestList.size()==position){
mItemClickListener.onItemClick("",position);
}else {
mItemClickListener.onItemClick(mRequestList.get(position), position);
}
}
});
}
if(mItemDeleteListener!=null){
holder.ivDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemDeleteListener.onDeleteClick(mRequestList.get(position), position);
}
});
}
}
@Override
public int getItemCount() {
return mRequestList.size()+1;
}
class Holder extends RecyclerView.ViewHolder{
SquareImageView image;
ImageView ivDelete;
public Holder(View itemView) {
super(itemView);
image = (SquareImageView) itemView.findViewById(R.id.image_show);
ivDelete= (ImageView) itemView.findViewById(R.id.iv_delete);
}
}
//使用接口回調(diào)點(diǎn)擊事件
private ItemClickListener mItemClickListener;
public void setOnItemClickListener(ItemClickListener itemClickListener){
this.mItemClickListener=itemClickListener;
}
//使用接口回調(diào)點(diǎn)擊事件
private DeleteListener mItemDeleteListener;
public void setOnDeleteClickListener(DeleteListener itemDeleteListener){
this.mItemDeleteListener=itemDeleteListener;
}
}
RequestAdapter是MainActivity類中RecyclerView的列表適配器夺英,主要是根據(jù)position和選擇圖片的數(shù)量來(lái)顯示圖片和“+”選擇更多、刪除圖片巍耗、圖片點(diǎn)擊的一些回調(diào)秋麸。
public class SelectImageActivity extends AppCompatActivity implements View.OnClickListener{
//相機(jī)
public static final String EXTRA_SHOW_CAMERA = "EXTRA_SHOW_CAMERA";
//選擇張數(shù)
public static final String EXTRA_SELECT_COUNT = "EXTRA_SELECT_COUNT";
//原始的圖片路徑
public static final String EXTRA_DEFAULT_SELECTED_LIST = "EXTRA_DEFAULT_SELECTED_LIST";
//選擇的模式
public static final String EXTRA_SELECT_MODE = "EXTRA_SELECT_MODE";
//返回選擇圖片的列表
public static final String EXTRA_RESULT = "EXTRA_RESULT";
//多選
public static final int MODE_MULTI = 0x0011;
//單選
public static final int MODE_SINGLE = 0x0012;
private static final int LOADER_TYPE = 0x0021;
private static final int REQUEST_CAMERA = 0x0022;
private static final int PHOTO_CAMERA = 1002;
private static final int PREVIEW_CODE = 1003;
//單選或多選
private int mMode = MODE_MULTI;
//選擇圖片的張數(shù)
private int mMaxCount = 9;
//是否顯示拍照按鈕
private boolean mShowCamera = true;
//選擇圖片的list
private ArrayList<String> mResultList;
@ViewById(R.id.btn_back)
private ImageView btnBack;
@ViewById(R.id.image_list_rv)
private RecyclerView imageListRv;
//預(yù)覽
@ViewById(R.id.select_preview)
private TextView selectPreview;
@ViewById(R.id.select_num)
private TextView selectNum;
@ViewById(R.id.select_finshi)
private TextView selectFinshi;
private File mTempFile;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_image);
ViewUtils.inject(this);
initData();
}
/**
* 初始化本地?cái)?shù)據(jù)
*/
private void initImageList() {
//獲取本地圖片 耗時(shí)操作
getLoaderManager().initLoader(LOADER_TYPE, null, mLoaderCallBack);
}
private LoaderManager.LoaderCallbacks<Cursor> mLoaderCallBack = new LoaderManager.LoaderCallbacks<Cursor>() {
private final String[] IMAGE_PROJECTION = {
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media._ID,
};
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
CursorLoader cursorLoader = new CursorLoader(SelectImageActivity.this,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
IMAGE_PROJECTION, IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[3] + "=? OR "
+ IMAGE_PROJECTION[3] + "=? ",
new String[]{"image/jpeg", "image/png"},
IMAGE_PROJECTION[2] + " DESC");
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
//如果有數(shù)據(jù)變化
if (data != null && data.getCount() > 0) {
ArrayList<String> images = new ArrayList<>();
//如果需要顯示拍照就添加一條空數(shù)據(jù)
if (mShowCamera) {
//封裝數(shù)據(jù)對(duì)象
// ImageEntity photoImage = new ImageEntity("", "", 0);
images.add("");
}
//不斷遍歷循環(huán)
while (data.moveToNext()) {
String path = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
// String name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
// long dateTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));
// Log.e("TAG", path + " " + name + " " + dateTime);
// //判斷文件是否存在
// if (!pathExist(path)) {
// continue;
// }
// Log.e("TAG", path + " " + name + " " + dateTime);
//封裝數(shù)據(jù)對(duì)象
// ImageEntity image = new ImageEntity(path, name, dateTime);
images.add(path);
}
//顯示列表數(shù)據(jù)
showListData(images);
}
}
/**
* 判斷文件是否存在
*
* @param path
* @return
*/
private boolean pathExist(String path) {
if (!TextUtils.isEmpty(path)) {
return new File(path).exists();
}
return false;
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
};
/**
* 顯示列表數(shù)據(jù)
*
* @param images
*/
private void showListData(ArrayList<String> images) {
SelectImageAdapter adapter = new SelectImageAdapter(SelectImageActivity.this, images, mResultList,mMaxCount, R.layout.media_chooser_item);
imageListRv.setLayoutManager(new GridLayoutManager(SelectImageActivity.this, 4));
imageListRv.setAdapter(adapter);
//設(shè)置分割線
imageListRv.addItemDecoration(new DividerGridItemDecoration(SelectImageActivity.this,R.drawable.item_dirver_01));
adapter.setOnSelectImageListener(new SelectImageListener() {
@Override
public void select(int number) {
exchangViewShow(number);
}
});
//拍照回調(diào)
adapter.setTakePhotoListener(new TakePhotoListener() {
@Override
public void takePhoto() {
//動(dòng)態(tài)申請(qǐng)權(quán)限
PermissionHelper.with(SelectImageActivity.this).
requestPermission(new String[]{Manifest.permission.CAMERA}).
requestCode(PHOTO_CAMERA).
request();
}
});
}
/**
* 拍照這里要做Android6.0以下 Android6.0和Android7.0以上的適配
*/
@PermissionSuccess(requestCode = PHOTO_CAMERA)
private void takePhoto(){
mTempFile=new File(getInnerSDCardPath(), "imagephoto" + SystemClock.currentThreadTimeMillis() + ".jpg");
if (!mTempFile.getParentFile().exists()){
mTempFile.getParentFile().mkdirs();
}
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
//Android7.0 com.picchoice替換成自己的包名
Uri imageUri = FileProvider.getUriForFile(SelectImageActivity.this, "com.picchoice.fileprovider", mTempFile);//通過(guò)FileProvider創(chuàng)建一個(gè)content類型的Uri
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加這一句表示對(duì)目標(biāo)應(yīng)用臨時(shí)授權(quán)該Uri所代表的文件
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//設(shè)置Action為拍照
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//將拍取的照片保存到指定URI
startActivityForResult(intent,REQUEST_CAMERA);
}else {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile));
startActivityForResult(intent, REQUEST_CAMERA);
}
// File file=new File(Environment.getExternalStorageDirectory(), "/temp/"+System.currentTimeMillis() + ".jpg");
}
/**
* 獲取內(nèi)置SD卡路徑
* @return
*/
public String getInnerSDCardPath() {
return Environment.getExternalStorageDirectory().getPath();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionHelper.requestPermissionsResult(this,requestCode,permissions,grantResults);
}
@Click({R.id.btn_back,R.id.select_finshi})
private void Click(View view) {
switch (view.getId()) {
case R.id.btn_back:
finish();
break;
case R.id.select_finshi://確定
Intent intent=new Intent();
Bundle bundle=new Bundle();
bundle.putSerializable(SelectImageActivity.EXTRA_DEFAULT_SELECTED_LIST,mResultList);
intent.putExtras(bundle);
setResult(RESULT_OK,intent);
finish();
break;
}
}
/**
* 獲取傳遞過(guò)來(lái)的參數(shù)
*/
private void initData() {
Intent intent = getIntent();
mMode = intent.getIntExtra(EXTRA_SELECT_MODE, mMode);
mMaxCount = intent.getIntExtra(EXTRA_SELECT_COUNT, mMaxCount);
mShowCamera = intent.getBooleanExtra(EXTRA_SHOW_CAMERA, mShowCamera);
mResultList = (ArrayList<String>) intent.getSerializableExtra(EXTRA_DEFAULT_SELECTED_LIST);
if (mResultList == null) {
mResultList = new ArrayList<>();
}
//初始化本地?cái)?shù)據(jù)
initImageList();
//改變顯示
exchangViewShow(mResultList.size());
}
/**
* 改變顯示
*/
private void exchangViewShow(int numder) {
if (numder> 0) {
selectPreview.setTextColor(Color.parseColor("#FF4081"));
selectFinshi.setTextColor(Color.parseColor("#FF4081"));
selectPreview.setEnabled(true);
selectPreview.setOnClickListener(this);
} else {
selectPreview.setTextColor(Color.parseColor("#ffffff"));
selectFinshi.setTextColor(Color.parseColor("#ffffff"));
selectPreview.setEnabled(false);
selectPreview.setOnClickListener(null);
}
selectNum.setText(numder + "/" + mMaxCount);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.select_preview://預(yù)覽
//跳轉(zhuǎn)至刪除或者預(yù)覽頁(yè)面
Intent intent=new Intent(SelectImageActivity.this,PreViewActivity.class);
Bundle bundle=new Bundle();
bundle.putInt("choicePosition",0);
bundle.putSerializable("choiceList",mResultList);
intent.putExtras(bundle);
startActivity(intent);
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//第一個(gè)要把圖片添加到集合
//調(diào)用Click方法
//通知系統(tǒng)本地有圖片改變了 下次進(jìn)來(lái)可以找到這張圖片
if(resultCode==RESULT_OK){
if(requestCode==REQUEST_CAMERA){
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(mTempFile)));
mResultList.add(mTempFile.getAbsolutePath());
setResult();
}
}
}
/**
* 設(shè)置返回結(jié)果
*/
private void setResult(){
Intent intent=new Intent();
Bundle bundle=new Bundle();
// bundle.putSerializable(EXTRA_RESULT,mResultList);//EXTRA_DEFAULT_SELECTED_LIST
bundle.putSerializable(EXTRA_DEFAULT_SELECTED_LIST,mResultList);
intent.putExtras(bundle);
setResult(RESULT_OK,intent);
//關(guān)閉當(dāng)前頁(yè)面
finish();
}
}
SelectImageActivity類主要是獲取系統(tǒng)sd里面的圖片并展示跌榔、android7.0訪問(wèn)相機(jī)適配催跪、相機(jī)拍照后圖片的刷新和保存等疾层。
public class SelectImageAdapter extends RecyclerCommonAdapter<String> {
private Context mContext;
private List<String> imageList;
private int mMaxCount;
public SelectImageAdapter(Context context, List<String> data, List<String> choice, int maxCount, int layoutId) {
super(context, data, layoutId);
this.mContext = context;
this.imageList = choice;
this.mMaxCount = maxCount;
}
@Override
protected void bindData(ViewHolder holder, final String mPath, final int position) {
if (TextUtils.isEmpty(mPath)) {
//顯示拍照
holder.setViewVisibility(R.id.camear_ll, View.VISIBLE);
holder.setViewVisibility(R.id.media_selected_indicator, View.INVISIBLE);
holder.setViewVisibility(R.id.image_show, View.INVISIBLE);
//拍照
holder.getView(R.id.camear_ll).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//調(diào)用拍照
if(takePhotoListener!=null){
takePhotoListener.takePhoto();
}
}
});
} else {
//顯示圖片
holder.setViewVisibility(R.id.camear_ll, View.INVISIBLE);
holder.setViewVisibility(R.id.media_selected_indicator, View.VISIBLE);
holder.setViewVisibility(R.id.image_show, View.VISIBLE);
SquareImageView image = holder.getView(R.id.image_show);
//顯示圖片 利用Glide centerCrop()
Glide.with(mContext).load(mPath).centerCrop().into(image);
ImageView selectImageView = holder.getView(R.id.media_selected_indicator);
if (imageList.contains(mPath)) {
//設(shè)置勾選圖片
selectImageView.setSelected(true);
} else {
selectImageView.setSelected(false);
}
//給條目添加點(diǎn)擊事件
image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//沒(méi)有就加入集合
if (!imageList.contains(mPath)) {
if (imageList.size() >= mMaxCount) {
Toast.makeText(mContext, "最多只能選擇" + mMaxCount + "張圖片", Toast.LENGTH_LONG).show();
return;
}
imageList.add(mPath);
} else {
//有就移除
imageList.remove(mPath);
}
//刷新數(shù)據(jù)
notifyDataSetChanged();
//通知顯示布局
if (selectImageListener != null) {
selectImageListener.select(imageList.size());
}
}
});
}
}
private SelectImageListener selectImageListener;
public void setOnSelectImageListener(SelectImageListener listener) {
this.selectImageListener = listener;
}
private TakePhotoListener takePhotoListener;
public void setTakePhotoListener(TakePhotoListener listener) {
this.takePhotoListener = listener;
}
}
SelectImageAdapter類是SelectImageActivity類中RecyclerView的適配器趾诗,展示系統(tǒng)sd獲取的圖片卒稳、控制圖片選擇的數(shù)量等粘姜。
public class PreViewActivity extends AppCompatActivity implements View.OnClickListener {
@ViewById(R.id.btn_back)
private ImageView btnBack;
@ViewById(R.id.viewpager)
private ViewPager viewpager;
private List<String> choiceList;
private DeleteAdapter adapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_delete);
ViewUtils.inject(this);
choiceList = (List<String>) getIntent().getSerializableExtra("choiceList");
if(choiceList==null){
choiceList=new ArrayList<>();
}
adapter=new DeleteAdapter(getSupportFragmentManager());
viewpager.setAdapter(adapter);
btnBack.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_back:
finish();
break;
}
}
class DeleteAdapter extends FragmentPagerAdapter{
public DeleteAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return ImageViewFragment.newInstance(choiceList.get(position));
}
@Override
public int getCount() {
return choiceList.size();
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
}
}
public class ImageViewFragment extends Fragment{
public static ImageViewFragment newInstance(String item){
ImageViewFragment fragment=new ImageViewFragment();
Bundle bundle=new Bundle();
bundle.putString("url",item);
fragment.setArguments(bundle);
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_imageview, container, false);
ImageView image = (ImageView) view.findViewById(R.id.image);
Bundle bundle = getArguments();
String url = bundle.getString("url");
if(url==null){
url="";
}
int screenWidth = getW(getActivity());
Bitmap diskBitmap = getDiskBitmap(url);
if(diskBitmap!=null){
//獲取Bitmap的寬高
int width = diskBitmap.getWidth();
int height = diskBitmap.getHeight();
//根據(jù)Bitmap的寬高和屏幕的寬高重新設(shè)置imageview顯示的大小
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) image.getLayoutParams();
layoutParams.width=screenWidth;
layoutParams.height=screenWidth*height/width;
image.setLayoutParams(layoutParams);
}
//顯示圖片 利用Glide centerCrop()
Glide.with(this).load(url).centerCrop().into(image);
return view;
}
/**
* 根據(jù)url獲取一個(gè)bitmap對(duì)象
* @param pathString 圖片路徑
* @return 返回對(duì)應(yīng)的Bitmap對(duì)象
*/
private Bitmap getDiskBitmap(String pathString) {
Bitmap bitmap = null;
try
{
File file = new File(pathString);
if(file.exists()) {
bitmap = BitmapFactory.decodeFile(pathString);
}
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
/*
* 獲取屏幕的寬度
*/
private int getW(Context context){
DisplayMetrics dm = new DisplayMetrics();
WindowManager windowMgr = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
windowMgr.getDefaultDisplay().getMetrics(dm);
return dm.widthPixels;
}
}
PreViewActivity類和ImageViewFragment類是圖片預(yù)覽宰翅,這里的圖片預(yù)覽效果做的不是很好穴墅,可以根據(jù)自己的需要進(jìn)行修改霎迫。
public class ImageSelector {
//選擇圖片張數(shù)
private int mMaxCount = 9;
//選擇圖片的模式
private int mMode = SelectImageActivity.MODE_MULTI;
//是否顯示拍照的相機(jī)
private boolean mShowCamera = true;
//原始的圖片
private ArrayList<String> mOriginData;
private ImageSelector() {
}
public static ImageSelector create() {
return new ImageSelector();
}
/**
* 單選模式
*
* @return
*/
public ImageSelector single() {
mMode = SelectImageActivity.MODE_SINGLE;
return this;
}
/**
* 多選模式
*
* @return
*/
public ImageSelector multi() {
mMode = SelectImageActivity.MODE_MULTI;
return this;
}
/**
* 設(shè)置可以選擇的圖片張數(shù)
*
* @param count
* @return
*/
public ImageSelector count(int count) {
mMaxCount = count;
return this;
}
/**
* 是否顯示相機(jī)
*
* @param showCamera
* @return
*/
public ImageSelector showCamera(boolean showCamera) {
mShowCamera = showCamera;
return this;
}
/**
* 選擇好的圖片
*
* @param originList
* @return
*/
public ImageSelector origin(ArrayList<String> originList) {
this.mOriginData = originList;
return this;
}
/**
* 啟動(dòng)requestCode
*
* @param activity
* @param requestCode
*/
public void start(Activity activity, int requestCode) {
Intent intent = new Intent(activity, SelectImageActivity.class);
addParmasByIntent(intent);
activity.startActivityForResult(intent, requestCode);
}
/**
* 啟動(dòng)requestCode
*
* @param fragment
* @param requestCode
*/
public void start(Fragment fragment, int requestCode) {
Intent intent = new Intent(fragment.getContext(), SelectImageActivity.class);
addParmasByIntent(intent);
fragment.startActivityForResult(intent, requestCode);
}
/**
* 設(shè)置參數(shù)
*
* @param intent
*/
private void addParmasByIntent(Intent intent) {
Bundle bundle = new Bundle();
bundle.putInt(SelectImageActivity.EXTRA_SELECT_COUNT, mMaxCount);
bundle.putInt(SelectImageActivity.EXTRA_SELECT_MODE, mMode);
bundle.putBoolean(SelectImageActivity.EXTRA_SHOW_CAMERA, mShowCamera);
if (mOriginData != null && mMode == SelectImageActivity.MODE_MULTI) {
bundle.putSerializable(SelectImageActivity.EXTRA_DEFAULT_SELECTED_LIST, mOriginData);
}
intent.putExtras(bundle);
}
}
ImageSelector類是一個(gè)工具類斋枢,里面提供了設(shè)置圖片多選還是單選,選擇圖片的數(shù)量知给,是否顯示相機(jī)等瓤帚。
上面這些就是實(shí)現(xiàn)的主要代碼,下面會(huì)提供源碼涩赢,可以根據(jù)自己的需要對(duì)源碼進(jìn)行修改戈次。