android项目实战之使用框架 集成多图片、视频的上传
效果图
实现方式,本功能使用PictureSelector 第三方库 。作者项目地址:https://github.com/LuckSiege/PictureSelector
1. builder.gradle 增加
implementation 'io.github.lucksiege:pictureselector:v3.11.1'
implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.3@aar'
implementation 'io.reactivex.rxjava2:rxjava:2.0.0'
2. XML布局
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="@+id/recycler"
android:layout_alignBottom="@+id/recycler"
android:background="@color/app_color_white" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:overScrollMode="never" />
</RelativeLayout>
3. 适配器,这里对GridImageAdapter进行了改进。
public class GridImageAdapter extends RecyclerView.Adapter<GridImageAdapter.ViewHolder> {
public static final String TAG = "PictureSelector";
public static final int TYPE_CAMERA = 1;
public static final int TYPE_PICTURE = 2;
private final LayoutInflater mInflater;
private ArrayList<LocalMedia> list = new ArrayList<>();
private int selectMax = 9;
/**
* 删除
*/
public void delete(int position) {
try {
if (position != RecyclerView.NO_POSITION && list.size() > position) {
list.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, list.size());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public GridImageAdapter(Context context, List<LocalMedia> result) {
this.mInflater = LayoutInflater.from(context);
this.list.addAll(result);
}
public void setSelectMax(int selectMax) {
this.selectMax = selectMax;
}
public void setList(ArrayList<LocalMedia> list) {
this.list = list;
}
public int getSelectMax() {
return selectMax;
}
public ArrayList<LocalMedia> getData() {
return list;
}
public void remove(int position) {
if (position < list.size()) {
list.remove(position);
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
ImageView mImg;
ImageView mIvDel;
TextView tvDuration;
public ViewHolder(View view) {
super(view);
mImg = view.findViewById(R.id.fiv);
mIvDel = view.findViewById(R.id.iv_del);
tvDuration = view.findViewById(R.id.tv_duration);
}
}
@Override
public int getItemCount() {
if (list.size() < selectMax) {
return list.size() + 1;
} else {
return list.size();
}
}
@Override
public int getItemViewType(int position) {
if (isShowAddItem(position)) {
return TYPE_CAMERA;
} else {
return TYPE_PICTURE;
}
}
/**
* 创建ViewHolder
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = mInflater.inflate(R.layout.item_filter_image, viewGroup, false);
return new ViewHolder(view);
}
private boolean isShowAddItem(int position) {
int size = list.size();
return position == size;
}
/**
* 设置值
*/
@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
//少于MaxSize张,显示继续添加的图标
if (getItemViewType(position) == TYPE_CAMERA) {
viewHolder.mImg.setImageResource(R.drawable.ic_add_image);
viewHolder.mImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mItemClickListener != null) {
mItemClickListener.openPicture();
}
}
});
viewHolder.mIvDel.setVisibility(View.INVISIBLE);
} else {
viewHolder.mIvDel.setVisibility(View.VISIBLE);
viewHolder.mIvDel.setOnClickListener(view -> {
int index = viewHolder.getAbsoluteAdapterPosition();
if (index != RecyclerView.NO_POSITION && list.size() > index) {
list.remove(index);
notifyItemRemoved(index);
notifyItemRangeChanged(index, list.size());
}
});
LocalMedia media = list.get(position);
int chooseModel = media.getChooseModel();
String path = media.getAvailablePath();
long duration = media.getDuration();
viewHolder.tvDuration.setVisibility(PictureMimeType.isHasVideo(media.getMimeType())
? View.VISIBLE : View.GONE);
if (chooseModel == SelectMimeType.ofAudio()) {
viewHolder.tvDuration.setVisibility(View.VISIBLE);
viewHolder.tvDuration.setCompoundDrawablesRelativeWithIntrinsicBounds
(R.drawable.ps_ic_audio, 0, 0, 0);
} else {
viewHolder.tvDuration.setCompoundDrawablesRelativeWithIntrinsicBounds
(R.drawable.ps_ic_video, 0, 0, 0);
}
viewHolder.tvDuration.setText(DateUtils.formatDurationTime(duration));
if (chooseModel == SelectMimeType.ofAudio()) {
viewHolder.mImg.setImageResource(com.luck.picture.lib.R.drawable.ps_audio_placeholder);
} else {
RequestOptions options = RequestOptions.centerCropTransform()
.centerCrop()
.placeholder(R.color.app_color_f6)
.diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(viewHolder.itemView.getContext())
.load(PictureMimeType.isContent(path) && !media.isCut() && !media.isCompressed() ? Uri.parse(path)
: path)
.apply(options)
.into(viewHolder.mImg);
}
//itemView 的点击事件
if (mItemClickListener != null) {
viewHolder.itemView.setOnClickListener(v -> {
int adapterPosition = viewHolder.getAbsoluteAdapterPosition();
mItemClickListener.onItemClick(v, adapterPosition);
});
}
if (mItemLongClickListener != null) {
viewHolder.itemView.setOnLongClickListener(v -> {
int adapterPosition = viewHolder.getAbsoluteAdapterPosition();
mItemLongClickListener.onItemLongClick(viewHolder, adapterPosition, v);
return true;
});
}
}
}
private OnItemClickListener mItemClickListener;
public void setOnItemClickListener(OnItemClickListener l) {
this.mItemClickListener = l;
}
public interface OnItemClickListener {
/**
* Item click event
*
* @param v
* @param position
*/
void onItemClick(View v, int position);
/**
* Open PictureSelector
*/
void openPicture();
}
private OnItemLongClickListener mItemLongClickListener;
public void setItemLongClickListener(OnItemLongClickListener l) {
this.mItemLongClickListener = l;
}
}
4. 布局空间初始化
FullyGridLayoutManager manager = new FullyGridLayoutManager(mContext, 3, GridLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(manager);
adapter = new GridImageAdapter(getContext(), mData);
adapter.setSelectMax(maxSelectNum);
mRecyclerView.setAdapter(adapter);
imageEngine = GlideEngine.createGlideEngine();
5. 点击增加弹框布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_album"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_album"
android:gravity="center"
android:padding="15dp"
android:text="相册"
android:textSize="16sp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#f5f5f5"/>
<TextView
android:id="@+id/tv_camera"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_camera"
android:gravity="center"
android:padding="15dp"
android:text="拍照"
android:textSize="16sp"/>
<TextView
android:id="@+id/tv_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@drawable/shape_cancel"
android:gravity="center"
android:padding="15dp"
android:text="取消"
android:textSize="16sp"/>
</LinearLayout>
</LinearLayout>
6. 弹框页面初始化
View bottomView = View.inflate(mContext, 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 = getActivity().getWindow().getAttributes();
lp.alpha = 0.5f;
getActivity().getWindow().setAttributes(lp);
pop.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
WindowManager.LayoutParams lp = getActivity().getWindow().getAttributes();
lp.alpha = 1f;
getActivity().getWindow().setAttributes(lp);
}
});
pop.setAnimationStyle(R.style.main_menu_photo_anim);
pop.showAtLocation(getActivity().getWindow().getDecorView(), Gravity.BOTTOM, 0, 0);
7. 弹框页面监听初始化
View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.tv_album:
//相册
Log.d("打开相册","sss");
PictureSelector.create(GoodItemTitleFragment.this)
.openGallery(SelectMimeType.ofImage())
.setImageEngine(GlideEngine.createGlideEngine())
.setMaxSelectNum(maxSelectNum)
.setMinSelectNum(1)
.setImageSpanCount(4)
.forResult(new OnResultCallbackListener<LocalMedia>() {
@Override
public void onResult(ArrayList<LocalMedia> result) {
selectList.addAll(result);
//Log.d("ceshi"+RESULT_OK, String.valueOf(images));
adapter.setList(selectList);
adapter.notifyDataSetChanged();
}
@Override
public void onCancel() {
}
});
/** PictureSelector.create(GoodItemTitleFragment.this)
.openGallery(PictureMimeType.ofImage())
.maxSelectNum(maxSelectNum)
.minSelectNum(1)
.imageSpanCount(4)
.selectionMode(PictureConfig.MULTIPLE)
.forResult(PictureConfig.CHOOSE_REQUEST);**/
break;
case R.id.tv_camera:
//拍照
Log.d("打开拍照","sss");
PictureSelector.create(GoodItemTitleFragment.this)
.openCamera(SelectMimeType.ofVideo())
.forResultActivity(PictureConfig.REQUEST_CAMERA);
/**PictureSelector.create(GoodItemTitleFragment.this)
.openCamera(PictureMimeType.ofImage())
.forResult(PictureConfig.CHOOSE_REQUEST);**/
break;
case R.id.tv_cancel:
//取消
closePopupWindow();
break;
}
closePopupWindow();
}
};
8. 增加拍照回调,不加这个图片回调不成功哦。
@SuppressLint("RestrictedApi")
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("ceshi"+requestCode,"111");
Log.d("ceshi"+resultCode,"222");
//Log.d("ceshi"+RESULT_OK,"333");
List<LocalMedia> images;
if (resultCode == -1) {
//Log.d("ceshi"+RESULT_OK,"111");
if (requestCode == PictureConfig.REQUEST_CAMERA) {// 图片选择结果回调
images = PictureSelector.obtainSelectorList(data);
selectList.addAll(images);
//Log.d("ceshi"+RESULT_OK, String.valueOf(images));
adapter.setList(selectList);
adapter.notifyDataSetChanged();
}
}
}
本功能涉及的功能较多,用了几天的时间算集成完。欢迎点赞、转发、首次。