效果图
实现方式,本功能使用PictureSelector 第三方库 。作者项目地址:https://github.com/LuckSiege/PictureSelector
-
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' -
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>
-
适配器,这里对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();
-
点击增加弹框布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical">
</LinearLayout><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>
-
弹框页面初始化
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);
-
弹框页面监听初始化
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(); } };
-
增加拍照回调,不加这个图片回调不成功哦。
@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();
}
}
}
本功能涉及的功能较多,用了几天的时间算集成完。欢迎点赞、转发、首次。