效果图
实现方式,本功能使用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布局
<RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><Viewandroid: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.RecyclerViewandroid: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);}}@Overridepublic int getItemCount() {if (list.size() < selectMax) {return list.size() + 1;} else {return list.size();}}@Overridepublic int getItemViewType(int position) {if (isShowAddItem(position)) {return TYPE_CAMERA;} else {return TYPE_PICTURE;}}/*** 创建ViewHolder*/@Overridepublic 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;}/*** 设置值*/@Overridepublic 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() {@Overridepublic 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"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:orientation="vertical"><TextViewandroid: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"/><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="#f5f5f5"/><TextViewandroid: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"/><TextViewandroid: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() {@Overridepublic 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() {@Overridepublic 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>() {@Overridepublic void onResult(ArrayList<LocalMedia> result) {selectList.addAll(result);//Log.d("ceshi"+RESULT_OK, String.valueOf(images));adapter.setList(selectList);adapter.notifyDataSetChanged();}@Overridepublic 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")@Overridepublic 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();}}}
本功能涉及的功能较多,用了几天的时间算集成完。欢迎点赞、转发、首次。