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布局


    复制代码
                 <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 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();
  1. 点击增加弹框布局

    复制代码
     <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>
  2. 弹框页面初始化

    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);
  3. 弹框页面监听初始化

    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() {

    复制代码
                                                @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();
             }
         };
  4. 增加拍照回调,不加这个图片回调不成功哦。

    @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 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();
    }
    }
    }

本功能涉及的功能较多,用了几天的时间算集成完。欢迎点赞、转发、首次。

相关推荐
执明wa1 分钟前
Android 开发中的设计模式入门:六大设计原则
android·设计模式
松仔log13 小时前
Java中级——组合和继承
android·java·开发语言
我命由我1234516 小时前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
lilian23317 小时前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos
2601_9557596217 小时前
ClaudeAPI成本中心与业务标签设计指南
android·java·数据库
余衫马18 小时前
2026最新版!Android Studio 极速安装与配置指南
android·ide·android studio
AFinalStone18 小时前
Android 7系统异常问题排查(五)Framework层(下)—System Server崩溃
android·tombstone·系统异常
AFinalStone18 小时前
Android 7系统异常问题排查(八)系统追踪—Trace机制与性能诊断
android·系统异常
极客猴子1 天前
Android录音转写频繁卡顿?多款APP长时间会议场景稳定性实测
android·人工智能·智能手机·飞书
Kapaseker1 天前
Boolean 变量到底该怎么命名?
android·kotlin