适配器GridImageAdapter
```clike
public class GridImageAdapter extends RecyclerView.Adapter<GridImageAdapter.ViewHolder> {
public static final int TYPE_CAMERA = 1;
public static final int TYPE_PICTURE = 2;
public static final int TYPE_MEDIA = 3;
public static final int TYPE_PATH = 4;
public static final int TYPE_EdIT = 5;
private final LayoutInflater mInflater;
private final List<LocalMedia> localMediaList = new ArrayList<>();
private final List<String> pathList = new ArrayList<>();
private int dataType = TYPE_MEDIA;
private OnItemClickListener mItemClickListener;
private OnAddPicClickListener mOnAddPicClickListener;
private OnDeletePicClickListener mOnDeletePicClickListener;
public GridImageAdapter(Context context) {
this.mInflater = LayoutInflater.from(context);
}
public GridImageAdapter(Context context, int dataType) {
this.mInflater = LayoutInflater.from(context);
this.dataType = dataType;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.gv_filter_image, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
if (getItemViewType(position) == TYPE_CAMERA) {
holder.mAddPicImg.setOnClickListener(v -> mOnAddPicClickListener.onAddPicClick());
holder.mPictureImg.setVisibility(View.INVISIBLE);
holder.mDeleteImg.setVisibility(View.INVISIBLE);
} else {
holder.mAddPicImg.setVisibility(View.INVISIBLE);
holder.mDeleteImg.setVisibility(View.VISIBLE);
holder.mDeleteImg.setOnClickListener(v -> {
int index = holder.getAdapterPosition();
// 这里有时会返回-1造成数据下标越界,具体可参考getAdapterPosition()源码,
// 通过源码分析应该是bindViewHolder()暂未绘制完成导致
if (dataType == TYPE_MEDIA) {
if (index != RecyclerView.NO_POSITION && localMediaList.size() > index) {
localMediaList.remove(index);
notifyItemRemoved(index);
notifyItemRangeChanged(index, localMediaList.size());
mOnDeletePicClickListener.onDeletePicClick();
}
} else {
if (index != RecyclerView.NO_POSITION && pathList.size() > index) {
pathList.remove(index);
notifyItemRemoved(index);
notifyItemRangeChanged(index, pathList.size());
mOnDeletePicClickListener.onDeletePicClick();
}
}
});
if (dataType == TYPE_MEDIA) {
LocalMedia media = localMediaList.get(position);
String path = getPathFromLocalMedia(media);
Glide.with(holder.itemView.getContext())
.load(PictureMimeType.isContent(path) && !media.isCut() && !media.isCompressed() ? Uri.parse(path)
: path)
.transform(new CenterCrop())
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(holder.mPictureImg);
} else {
String path = pathList.get(position);
Glide.with(holder.itemView.getContext())
// .load(Api.API_BASE + "/common/images/" + path)
.load(path)
.transform(new CenterCrop())
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(holder.mPictureImg);
}
//itemView 的点击事件
if (mItemClickListener != null) {
holder.itemView.setOnClickListener(v -> {
int adapterPosition = holder.getAdapterPosition();
mItemClickListener.onItemClick(v, adapterPosition);
});
}
}
}
/**
* 调用setData()设置数据之前,先调用该方法,告诉适配器数据类型是LocalMedia对象还是path路径。
* 如果不调用该方法,默认为LocalMedia类型
*
* @param dataType 数据类型,接收 TYPE_MEDIA 和 TYPE_PATH 类型参数
*/
public void setDataType(int dataType) {
this.dataType = dataType;
}
@Override
public int getItemCount() {
int maxSelectNum = 20;
if (dataType == TYPE_MEDIA) {
if (localMediaList.size() < maxSelectNum) {
return localMediaList.size() + 1;
} else {
return localMediaList.size();
}
} else {
if (pathList.size() < maxSelectNum) {
return pathList.size() + 1;
} else {
return pathList.size();
}
}
}
@Override
public int getItemViewType(int position) {
if (isShowAddItem(position)) {
return TYPE_CAMERA;
} else {
return TYPE_PICTURE;
}
}
private boolean isShowAddItem(int position) {
return dataType == TYPE_MEDIA ? position == localMediaList.size() : position == pathList.size();
}
/**
* 如果数据类型为 TYPE_PATH,请使用该方法获取数据集合
*
* @return 数据集合
*/
public List<LocalMedia> getData() {
return this.localMediaList;
}
/**
* 如果数据类型为 TYPE_MEDIA,请使用该方法设置数据源
*
* @param list 数据源
*/
public void setData(List<LocalMedia> list) {
this.localMediaList.addAll(list);
notifyItemRangeChanged(getItemCount() - 1, getItemCount());
}
/**
* 如果数据类型为 TYPE_PATH,请使用该方法获取数据集合
*
* @param isPath 该参数无意义,传true或false都可,只是为了区分上面的getData方法,因为方法重载需要改变参数个数或类型
* @return 数据集合
*/
public List<String> getData(boolean isPath) {
return this.pathList;
}
/**
* 如果数据类型为 TYPE_PATH,请使用该方法设置数据源
*
* @param list 数据源
* @param isPath 该参数无意义,传true或false都可,只是为了区分上面的setData方法,因为方法重载需要改变参数个数或类型
*/
public void setData(List<String> list, boolean isPath) {
this.pathList.addAll(list);
int count = getItemCount();
Log.d("VVVVVVVVVVVVVVVV", String.valueOf(count));
notifyItemRangeChanged(count - 1, count);
}
public void setOnItemClickListener(OnItemClickListener l) {
this.mItemClickListener = l;
}
public void setOnAddPicClickListener(OnAddPicClickListener l) {
this.mOnAddPicClickListener = l;
}
public void setOnDeletePicClickListener(OnDeletePicClickListener l) {
this.mOnDeletePicClickListener = l;
}
public String getPathFromLocalMedia(LocalMedia media) {
if (media == null || TextUtils.isEmpty(media.getPath())) {
return null;
}
String path;
if (media.isCut() && !media.isCompressed()) {
// 裁剪过
path = media.getCutPath();
} else if (media.isCompressed() || (media.isCut() && media.isCompressed())) {
// 压缩过,或者裁剪同时压缩过,以最终压缩过图片为准
path = media.getCompressPath();
} else {
// 原图地址
path = media.getPath();
}
return path;
}
public interface OnItemClickListener {
void onItemClick(View v, int position);
}
public interface OnAddPicClickListener {
void onAddPicClick();
}
public interface OnDeletePicClickListener {
void onDeletePicClick();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
ImageView mAddPicImg;
RoundImageView mPictureImg;
ImageView mDeleteImg;
public ViewHolder(View view) {
super(view);
mAddPicImg = view.findViewById(R.id.mAddPicImg);
mPictureImg = view.findViewById(R.id.mPictureImg);
mDeleteImg = view.findViewById(R.id.mDeleteImg);
}
}
}
layout布局:gv_filter_image
```html
<?xml version="1.0" encoding="UTF-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/mAddPicImg"
android:layout_width="96dp"
android:layout_height="96dp"
android:contentDescription="@null"
android:scaleType="centerInside"
android:src="@mipmap/add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<com.ligong.library.commonview.imageview.RoundImageView
android:id="@+id/mPictureImg"
android:layout_width="96dp"
android:layout_height="96dp"
android:contentDescription="@null"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:leftBottom_corner_radius="5dp"
app:leftTop_corner_radius="5dp"
app:rightBottom_corner_radius="5dp"
app:rightTop_corner_radius="5dp"
app:type="round" />
<ImageView
android:id="@+id/mDeleteImg"
android:layout_width="16dp"
android:layout_height="16dp"
android:contentDescription="@null"
android:src="@drawable/delete_image"
app:layout_constraintBottom_toTopOf="@id/mPictureImg"
app:layout_constraintLeft_toRightOf="@id/mPictureImg"
app:layout_constraintRight_toRightOf="@id/mPictureImg"
app:layout_constraintTop_toTopOf="@id/mPictureImg" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity中:
private GridImageAdapter mAdapter;
initAdapterView();
private void initAdapterView() {
mAdapter = new GridImageAdapter(this);
mBinding.rvChoosePics.setLayoutManager(new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false));
mBinding.rvChoosePics.setAdapter(mAdapter);
mAdapter.setOnAddPicClickListener(() -> requestPermission(1));
mAdapter.setOnDeletePicClickListener(() -> {
});
}
//此处权限可更改为其他的方式
private void requestPermission(int type) {
rxPermissions.request(Manifest.permission.WRITE_EXTERNAL_STORAGE).subscribe(granted -> {
if (granted) {
openAlbumOrTakePhotos(type);
} else {
ToastUtils.showShort("你拒绝了权限,请手动授权");
}
});
}
//酌情修改,此处两个adapter,是因为这个界面有两处传图的地方
private void openAlbumOrTakePhotos(int type) {
PictureSelector.create(this)
.openGallery(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.setLanguage(LanguageConfig.CHINESE)
.maxSelectNum(type == 1 ? maxSelectNum - mAdapter.getData().size() : maxSelectNum - mAdapter2.getData().size())
.isAndroidQTransform(true) // Android Q版本下是否需要拷贝文件至应用沙盒内
.isEnableCrop(false) // 是否开启裁剪
.freeStyleCropEnabled(false) // 裁剪框是否可拖拽
.rotateEnabled(false) // 裁剪是否可旋转图片
.scaleEnabled(false) // 裁剪是否可放大缩小图片
.isDragFrame(false) // 是否可拖动裁剪框
.isMultipleSkipCrop(false) // 多图裁剪是否支持跳过
.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) // 固定屏幕方向为竖屏
.isCamera(true)
.isCompress(true)
.compressQuality(10) // 图片压缩后输出质量 0~ 100
.minimumCompressSize(500) // 小于多少KB的图片不压缩
.forResult(new OnResultCallbackListener<LocalMedia>() {
@Override
public void onResult(List<LocalMedia> result) {
if (!CollectionUtils.isEmpty(result)) {
if (type == 1) {
mAdapter.setData(result);
} else {
mAdapter2.setData(result);
}
}
}
@Override
public void onCancel() {
}
});
}
//上传图片请求
//上传图片
@Multipart
@POST(Api.GET_UPLOADPIC)
Observable<UploadImgBean> uploadImg(@PartMap Map<String, RequestBody> map,
@Query("type") String type);
c层:
void uploadImgSuccess(UploadImgBean bean);
void uploadImg(Map<String, RequestBody> map, String type);
//此处应该根据所用框酌情修改
p层:
@Override
public void uploadImg(Map<String, RequestBody> map, String type) {
if (NetworkUtils.isConnected()) {
mRetrofitFactory.uploadImg(map, type)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseObserver<UploadImgBean>() {
@Override
public void onResponse(UploadImgBean bean) {
if (null != mView) {
mView.uploadImgSuccess(bean);
}
}
});
} else {
ToastUtils.showShort(R.string.check_network);
}
}
private void startUploadImg() {
Map<String, RequestBody> params = new HashMap<>();
for (LocalMedia localMedia : mAdapter.getData()) {
File file = new File(mAdapter.getPathFromLocalMedia(localMedia));
RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"), file);
params.put("AttachmentKey\"; filename=\"" + file.getName(), body);
}
mPresenter.uploadImg(params, "changeinfo");
}
//暂时记录如此