适配器;
public class GridImageAdapter1 extends RecyclerView.Adapter<GridImageAdapter1.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 GridImageAdapter1(Context context) {
this.mInflater = LayoutInflater.from(context);
}
public GridImageAdapter1(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 if (!TextUtils.isEmpty(media.getRealPath())){
//适配Android10,Android10以上需要获取真实路径,path返回的是uri
path = media.getRealPath();
}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);
}
}
}
activity:
private GridImageAdapter1 adapterAccident;
initAdapterAccident();
private void initAdapterAccident() {
adapterAccident = new GridImageAdapter1(this, GridImageAdapter1.TYPE_PATH);
mBinding.fragmentCommon.rvFragmentCommonAccident.setLayoutManager(new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false));
mBinding.fragmentCommon.rvFragmentCommonAccident.setAdapter(adapterAccident);
adapterAccident.setOnAddPicClickListener(() -> requestPermission(1));
adapterAccident.setOnDeletePicClickListener(() -> {
});
}
//json解析后台返回的图片,并将图片加载到布局上
String pic = jsonObject.getString("accidentBillPic");
List<String> picImgs = new ArrayList<>();
if (!TextUtils.isEmpty(pic)) {
String[] s = pic.split(",");
for (String s1 : s) {
picImgs.add(Api.API_BASE + "/common/images/" + s1);
}
}
adapterAccident.setData(picImgs, true);
//上传图片
private void startOneImg() {
List<String> data = adapterAccident.getData(true);
if (data == null || data.isEmpty()) {
return;
}
Map<String, RequestBody> params = new HashMap<>();
for (String localMedia : data) {
if (localMedia.contains("http://") || localMedia.contains("https://")) continue;
File file = new File(localMedia);
RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"), file);
params.put("AttachmentKey\"; filename=\"" + file.getName(), body);
}
if (params.isEmpty()) {
canNextCount++;
startTwoImg();
return;
}
mPresenter.uploadImg(params, "claims");
}
//拼接图片地址
private String getPushStr(List<String> pathList, int type) {
String urlStr = "";
if (pathList != null && !pathList.isEmpty()) {
for (String str : pathList) {
if (str.contains("http://") || str.contains("https://")) {
urlStr += str.replace("图片地址", "") + ",";
}
}
}
if (!imgs.isEmpty()) {
for (ImageBean bean : imgs) {
int beanType = bean.getType();
if (beanType == type) {
urlStr = urlStr + bean.getUrl(); // bean.getUrl() 新增圖片
}
}
}
if (!urlStr.isEmpty() && urlStr.length() >= 2) {
urlStr = urlStr.endsWith(",") ? urlStr.substring(0, urlStr.length() - 1) : urlStr;
}
return urlStr;
}
//使用时:此处应该根据后台要求传值: 此处使用了body传参,图片转为了gson,在 submitForm();方法中
if (canNextCount == 1) {
return;
}
JSONObject obj = new JSONObject();
String lossStr = getPushStr(adapterLoss.getData(true), 2);
String accidentStr = getPushStr(adapterAccident.getData(true), 1);
String otherStr = getPushStr(adapterInvoce.getData(true), 3);
try {
obj.put("claimAmount", damages);
obj.put("reportNo", report);
obj.put("accidentBillPic", accidentStr.trim());
//传值的时候,拼接新获取的url+经过增删的旧url
obj.put("insuranceLossBillPic", lossStr.trim());
obj.put("repairInvoicePic", otherStr.trim());
body.setInsuranceContent(obj.toString());
canNextCount = 1;
mPresenter.getReSubmit(body);
} catch (JSONException e) {
e.printStackTrace();
}
另,这个activity多处传图,采用的方法是循环上传:即在第一组图上传成功后,再上传下一组,因此在传图成功的回调里:
private int canNextCount = 1;//默认上传图片为一次
if (canNextCount < 4) {
ImageBean imageBean = new ImageBean();
imageBean.setType(canNextCount);
imageBean.setUrl(bean.getData());
imgs.add(imageBean);
canNextCount++;
}
if (canNextCount == 2) {
startTwoImg();
}
if (canNextCount == 3) {
startThreeImg();
}
if (canNextCount == 4) {
submitForm();
}
另外图片选择的回调以及权限:
private void openAlbumOrTakePhotos(int type) {
int max = 0;
switch (type) {
case 1:
max = maxSelectNum - adapterAccident.getData(true).size();
break;
case 2:
max = maxSelectNum - adapterLoss.getData(true).size();
break;
case 3:
max = maxSelectNum - adapterInvoce.getData(true).size();
break;
}
PictureSelector.create(this)
.openGallery(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.setLanguage(LanguageConfig.CHINESE)
.maxSelectNum(max)
.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)) {
List<String> path = new ArrayList<>();
switch (type) {
case 1:
for (LocalMedia localMedia : result) {
path.add(adapterAccident.getPathFromLocalMedia(localMedia));
}
adapterAccident.setData(path, true);
break;
case 2:
for (LocalMedia localMedia : result) {
path.add(adapterLoss.getPathFromLocalMedia(localMedia));
}
adapterLoss.setData(path, true);
break;
case 3:
for (LocalMedia localMedia : result) {
path.add(adapterInvoce.getPathFromLocalMedia(localMedia));
}
adapterInvoce.setData(path, true);
break;
}
}
}
@Override
public void onCancel() {
}
});
}
private void requestPermission(int type) {
rxPermissions.request(Manifest.permission.WRITE_EXTERNAL_STORAGE).subscribe(granted -> {
if (granted) {
openAlbumOrTakePhotos(type);
} else {
ToastUtils.showShort("你拒绝了权限,请手动授权");
}
});
}
//保存图片的bean类
```handlebars
private final int maxSelectNum = 20;//最大图片选择数量
List<ImageBean> imgs = new ArrayList();//拿到的图片列表
public class ImageBean {
private int type;
private String url;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}