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

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

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

相关推荐
selt79133 分钟前
Redisson之RedissonLock源码完全解析
android·java·javascript
Yao_YongChao1 小时前
Android MVI处理副作用(Side Effect)
android·mvi·mvi副作用
非凡ghost2 小时前
JRiver Media Center(媒体管理软件)
android·学习·智能手机·媒体·软件需求
席卷全城2 小时前
Android 推箱子实现(引流文章)
android
齊家治國平天下2 小时前
Android 14 系统中 Tombstone 深度分析与解决指南
android·crash·系统服务·tombstone·android 14
maycho1234 小时前
MATLAB环境下基于双向长短时记忆网络的时间序列预测探索
android
思成不止于此5 小时前
【MySQL 零基础入门】MySQL 函数精讲(二):日期函数与流程控制函数篇
android·数据库·笔记·sql·学习·mysql
brave_zhao5 小时前
达梦数据库(DM8)支持全文索引功能,但并不直接兼容 MySQL 的 FULLTEXT 索引语法
android·adb
sheji34165 小时前
【开题答辩全过程】以 基于Android的网上订餐系统为例,包含答辩的问题和答案
android
easyboot6 小时前
C#使用SqlSugar操作mysql数据库
android·sqlsugar