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

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

本功能涉及的功能較多,用了幾天的時間算集成完。歡迎點贊、轉發、首次。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/207127.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207127.shtml
英文地址,請注明出處:http://en.pswp.cn/news/207127.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

線性回歸實戰

3.1 使用正規方程進行求解 3.1.1 簡單線性回歸 公式 &#xff1a; y w x b y wx b ywxb 一元一次方程&#xff0c;在機器學習中一元表示一個特征&#xff0c;b表示截距&#xff0c;y表示目標值。 使用代碼進行實現&#xff1a; 導入包 import numpy as np import matp…

中綴表達式轉后綴表達式與后綴表達式計算(詳解)

**中綴表達式轉后綴表達式的一般步驟如下&#xff1a; 1&#xff1a;創建一個空的棧和一個空的輸出列表。 2&#xff1a;從左到右掃描中綴表達式的每個字符。 3&#xff1a;如果當前字符是操作數&#xff0c;則直接將其加入到輸出列表中。 4&#xff1a;如果當前字符是運算符&a…

QNX usleep測試

QNX usleep測試 結論 usleep時間在QNX上沒有ubuntu上運行準確&#xff0c;但是10ms以上誤差不大。 測試代碼 testsleep.cpp的代碼如下&#xff1a; #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <time.h>double usleep_…

sklearn 筆記:neighbors.NearestNeighbors 自定義metric

1 數據 假設我們有這樣的一個數據tst_lst&#xff0c;表示的是5條軌跡的墨卡托坐標&#xff0c;我們希望算出逐點的曼哈頓距離之和&#xff0c;作為兩條軌跡的距離 [array([[11549759.51313693, 148744.89246911],[11549751.49813359, 148732.97804463],[11549757.620705…

Linux 常用命令匯總

1 linux定時任務 查看定時任務&#xff1a;crontab -l 每晚一點半執行定時任務&#xff1a; 30 1 * * * sh /var/lib/pgsql/pg_db_backup.sh >> /var/lib/pgsql/pg_db_backup.log 2>&1 配置定時任務&#xff1a;crontab -e 2 linux 內核版本查詢 cat /etc/r…

P5744 【深基7.習9】培訓

題目描述 某培訓機構的學員有如下信息&#xff1a; 姓名&#xff08;字符串&#xff09;年齡&#xff08;周歲&#xff0c;整數&#xff09;去年 NOIP 成績&#xff08;整數&#xff0c;且保證是 5 5 5 的倍數&#xff09; 經過為期一年的培訓&#xff0c;所有同學的成績都…

學習-java多線程

線程的創建 *繼承Tread,重寫run *實現Runnable接口,重寫run() [匿名內部類] *實現callable接口(有結果返回) 線程的常用方法 調用join保證這個方法先執行完成, 線程安全 并發編程 進程&#xff1a;就相當一個程序的實例線程&#xff1a;就是指令流&#xff08;一個進程包含多…

無重復字符的最長子串-中等

leetcode地址 給定一個字符串 s &#xff0c;請你找出其中不含有重復字符的 最長子串 的長度。 示例 1:輸入: s "abcabcbb" 輸出: 3 解釋: 因為無重復字符的最長子串是 "abc"&#xff0c;所以其長度為 3。 示例 2:輸入: s "bbbbb" 輸出: 1 …

我有才打造私域流量的知識付費小程序平臺

在當今數字化時代&#xff0c;知識付費市場正在迅速崛起&#xff0c;而私域流量的概念也日益受到重視。私域流量指的是企業通過自有渠道獲取的、能夠自由支配的流量&#xff0c;這種流量具有更高的用戶粘性和轉化率。因此&#xff0c;打造一個基于私域流量的知識付費小程序平臺…

實現:切換頁面切換標題,擴展 vue-router 的類型

布局容器-頁面標題 網址&#xff1a;https://router.vuejs.org/zh/guide/advanced/meta 給每一個路由添加 元信息 數據 router/index.ts const router createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{ path: /login, component: () > im…

問題:數組對象去重

問題&#xff1a;數組對象去重 var arr [{name: ‘a’,id: 1}, {name: ‘a’,id: 2}, {name: ‘b’,id: 3}, {name: ‘c’,id: 4}, {name: ‘c’,id: 6}, {name: ‘b’,id: 6}, {name: ‘d’,id: 7}]; 對數組對象name進行去重處理&#xff0c; 結果顯示為&#xff1a; [{name…

第一啟富金:新添澳大利亞(ASIC)牌照

第一啟富金&#xff1a;澳大利亞證券及投資委員會&#xff08;ASIC&#xff09; GOLDWELL GLOBAL PTY LTD 是 WHOLESALE INVESTOR SERVICES PTY LTD&#xff08;CAR 編號 001304943&#xff09;的企業授權代表開發澳大利亞客戶&#xff0c;WHOLESALE INVESTOR SERVICES PTY LT…

XML是什么

XML是是什么&#xff1f; XML&#xff08;Extensible Markup Language&#xff09;&#xff0c;中文是可擴展標記語言&#xff0c;是標準通用標記語言的子集。它是一種標記語言&#xff0c;用于標記電子文檔&#xff0c;使其結構化。 XML可以用來標記數據&#xff0c;定義數據…

【軟件推薦】文本轉語音,語音轉wav,導入ue5

文字轉語音 在線免費文字轉語音 - TTSMaker官網 | 馬克配音https://ttsmaker.cn/ 文件轉換器 語音轉wav Convertio — 文件轉換器https://convertio.co/zh/

C#應用:MQTT分析——CONNECT為例子

源代碼: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net.Sockets;namespace ConsoleApp1 {class Program{static void Main(string[] args){Connect();}/// <summary>/// 向…

HarmonyOS應用程序框架——UIAbility實操

UIAbility概述 UIAbility是一種包含用戶界面的應用組件&#xff0c;主要用于和用戶進行交互。UIAbility也是系統調度的單元&#xff0c;為應用提供窗口在其中繪制界面。 每一個UIAbility實例&#xff0c;都對應于一個最近任務列表中的任務。 一個應用可以有一個UIAbility&…

Leetcode—901.股票價格跨度【中等】

2023每日刷題&#xff08;五十二&#xff09; Leetcode—901.股票價格跨度 算法思想 實現代碼 class StockSpanner { public:stack<pair<int, int>> st;int curday -1;StockSpanner() {st.emplace(-1, INT_MAX);}int next(int price) {while(price > st.top(…

油猴(Tampermonkey)瀏覽器插件簡單自定義腳本開發

介紹 瀏覽器插件&#xff0c;包括油猴插件和其他插件&#xff0c;通過它們可以實現瀏覽器網頁的定制化與功能增強。 其他插件一般只有某種具體的功能&#xff0c;且已經寫死而不能更改&#xff0c;比如Adblock插件只用于去廣告。 油猴插件是一款用于管理用戶腳本的插件&…

使用Rust 構建C 組件

協議解析&#xff0c;這不就很快了&#xff0c;而且原生的標準庫紅黑樹和avl 樹支持&#xff0c;異步tokio 這些庫&#xff0c;編寫應用組件就很快了 rust 標準庫不支持 unix 的消息隊列&#xff0c;但是支持 shm 和 uds&#xff0c;后者從多方面考慮都比&#xff0c;消息隊列更…

教育類直播介紹

教育類直播是一種在線教育形式&#xff0c;它允許學生和教師通過實時視頻通話進行互動學習。這種學習方式可以為學生提供更靈活的學習時間和地點&#xff0c;同時也可以幫助教師更好地與學生進行互動和指導。 在教育類直播中&#xff0c;學生可以通過網絡與教師和其他學生進行…