




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、微信朋友圈的图片上传,多图上传怎么去撸才合适?我们一起来实现吧!图片上传是非常常见的功能,而多图上传在大多数应用中也是非常常见的,比如微信的朋友圈,微博的动态,都是有九宫格图片的,那这里肯定涉及了多图上传,所以今天我们来一起撸一下,怎么去思考这个实现逻辑!这里我想到的思路是比较简单的,首先,我们有一个按钮,按钮是上传图片,点击之后弹出某个界面进行图片的选择,一般是九张图片或者十二张,选完之后就直接上传了,大致的流程应该是这个样子,那我们首先来写个按钮activity_main.xml<?xml version="1.0" encoding="utf-8&qu
2、ot;?><LinearLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp"> <Button android:id="+id/btnAddPhoto" android:layout_width="match_
3、parent" android:layout_height="wrap_content" android:text="上传图片"/></LinearLayout>他只是一个主页,我们只要实现它的点击事件就好了,点击之后跳转到我们的上传图片的ActivcityMainActivitypackage com.liuguilin.uploadphotossample;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import
4、 android.os.Bundle;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity private Button btnAddPhoto; Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /点击事件 findV
5、iewById(R.id.btnAddPhoto).setOnClickListener(new View.OnClickListener() Override public void onClick(View view) startActivity(new Intent(MainActivity.this,UploadPhotoActivity.class); ); 这些都是可以一笔带过的,真正的逻辑全部都在这个UploadPhotoActivity,我们用GridView显示图片,并且进行多选,下面有一个按钮负责显示已选图片的数量以及完成上传的功能activity_upload.xml&l
6、t;?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical"> <GridView and
7、roid:id="+id/mGradView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:numColumns="3"/> <Button android:id="+id/btnOk" android:layout_width="200dp" android:layout_height=&qu
8、ot;wrap_content" android:layout_margin="10dp" android:background="color/colorAccent" android:text="2/12 完成" android:textColor="android:color/white"/></LinearLayout>我们现在就要分析我们怎么去实现了,这个GridView肯定是要写的,但是我们首先得要拿到我们的图片,图片怎么拿?肯定是看相册的源码来分析他是怎么去拿的,这里呢,我们
9、使用的是ContentResolver内容访问者,我们查看下源码,我们主要还是看MediaProvider这个项目我们只要看他最先的一段静态块static URI_MATCHER.addURI("media", "*/images/media", IMAGES_MEDIA); URI_MATCHER.addURI("media", "*/images/media/#", IMAGES_MEDIA_ID); URI_MATCHER.addURI("media", "*/images/th
10、umbnails", IMAGES_THUMBNAILS); URI_MATCHER.addURI("media", "*/images/thumbnails/#", IMAGES_THUMBNAILS_ID); URI_MATCHER.addURI("media", "*/audio/media", AUDIO_MEDIA); URI_MATCHER.addURI("media", "*/audio/media/#", AUDIO_MEDIA_ID); URI_M
11、ATCHER.addURI("media", "*/audio/media/#/genres", AUDIO_MEDIA_ID_GENRES); URI_MATCHER.addURI("media", "*/audio/media/#/genres/#", AUDIO_MEDIA_ID_GENRES_ID); URI_MATCHER.addURI("media", "*/audio/media/#/playlists", AUDIO_MEDIA_ID_PLAYLISTS);
12、URI_MATCHER.addURI("media", "*/audio/media/#/playlists/#", AUDIO_MEDIA_ID_PLAYLISTS_ID); URI_MATCHER.addURI("media", "*/audio/genres", AUDIO_GENRES); URI_MATCHER.addURI("media", "*/audio/genres/#", AUDIO_GENRES_ID); URI_MATCHER.addURI("
13、;media", "*/audio/genres/#/members", AUDIO_GENRES_ID_MEMBERS); URI_MATCHER.addURI("media", "*/audio/genres/all/members", AUDIO_GENRES_ALL_MEMBERS); URI_MATCHER.addURI("media", "*/audio/playlists", AUDIO_PLAYLISTS); URI_MATCHER.addURI("media
14、", "*/audio/playlists/#", AUDIO_PLAYLISTS_ID); URI_MATCHER.addURI("media", "*/audio/playlists/#/members", AUDIO_PLAYLISTS_ID_MEMBERS); URI_MATCHER.addURI("media", "*/audio/playlists/#/members/#", AUDIO_PLAYLISTS_ID_MEMBERS_ID); URI_MATCHER.addUR
15、I("media", "*/audio/artists", AUDIO_ARTISTS); URI_MATCHER.addURI("media", "*/audio/artists/#", AUDIO_ARTISTS_ID); URI_MATCHER.addURI("media", "*/audio/artists/#/albums", AUDIO_ARTISTS_ID_ALBUMS); URI_MATCHER.addURI("media", "
16、*/audio/albums", AUDIO_ALBUMS); URI_MATCHER.addURI("media", "*/audio/albums/#", AUDIO_ALBUMS_ID); URI_MATCHER.addURI("media", "*/audio/albumart", AUDIO_ALBUMART); URI_MATCHER.addURI("media", "*/audio/albumart/#", AUDIO_ALBUMART_ID); UR
17、I_MATCHER.addURI("media", "*/audio/media/#/albumart", AUDIO_ALBUMART_FILE_ID); URI_MATCHER.addURI("media", "*/video/media", VIDEO_MEDIA); URI_MATCHER.addURI("media", "*/video/media/#", VIDEO_MEDIA_ID); URI_MATCHER.addURI("media",
18、"*/video/thumbnails", VIDEO_THUMBNAILS); URI_MATCHER.addURI("media", "*/video/thumbnails/#", VIDEO_THUMBNAILS_ID); URI_MATCHER.addURI("media", "*/media_scanner", MEDIA_SCANNER); URI_MATCHER.addURI("media", "*/fs_id", FS_ID); URI_M
19、ATCHER.addURI("media", "*/version", VERSION); URI_MATCHER.addURI("media", "*/mtp_connected", MTP_CONNECTED); URI_MATCHER.addURI("media", "*", VOLUMES_ID); URI_MATCHER.addURI("media", null, VOLUMES); / Used by MTP implementation UR
20、I_MATCHER.addURI("media", "*/file", FILES); URI_MATCHER.addURI("media", "*/file/#", FILES_ID); URI_MATCHER.addURI("media", "*/object", MTP_OBJECTS); URI_MATCHER.addURI("media", "*/object/#", MTP_OBJECTS_ID); URI_MATCHER.
21、addURI("media", "*/object/#/references", MTP_OBJECT_REFERENCES); /* * deprecated use the 'basic' or 'fancy' search Uris instead */ URI_MATCHER.addURI("media", "*/audio/" + SearchManager.SUGGEST_URI_PATH_QUERY, AUDIO_SEARCH_LEGACY); URI_MATCHER.
22、addURI("media", "*/audio/" + SearchManager.SUGGEST_URI_PATH_QUERY + "/*", AUDIO_SEARCH_LEGACY); / used for search suggestions URI_MATCHER.addURI("media", "*/audio/search/" + SearchManager.SUGGEST_URI_PATH_QUERY, AUDIO_SEARCH_BASIC); URI_MATCHER.addUR
23、I("media", "*/audio/search/" + SearchManager.SUGGEST_URI_PATH_QUERY + "/*", AUDIO_SEARCH_BASIC); / used by the music app's search activity URI_MATCHER.addURI("media", "*/audio/search/fancy", AUDIO_SEARCH_FANCY); URI_MATCHER.addURI("media&quo
24、t;, "*/audio/search/fancy/*", AUDIO_SEARCH_FANCY); 这段代码块就是我们访问系统数据库索要获取任意数据的URI,而我们访问图片的URI是URI_MATCHER.addURI("media", "*/images/media", IMAGES_MEDIA);11不过既然是内容提供者,google也是封装好了一些方法供我们使用 /* * 初始化数据 */ private void initData() /获取手机相册图片 访问本机数据库 ContentResolver mContentRes
25、olver = getContentResolver(); /图片数据的url(外部存储) Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; /查询 Cursor cursor = mContentResolver.query(uri,null,null,null,null); /遍历 while (cursor.moveToNext() PhotoBean bean = new PhotoBean(); /获取路径 String path = cursor.getString(cursor.getColumnIndex(Media
26、Store.Images.Media.DATA); /设置路径 bean.setPath(path); /默认fasle bean.setSelect(false); /保存 mList.add(bean); OK,当我们拿到这些相册的图片肯定是要去存储,那我们怎么去存储?一般都是用个实体对象的PhotoBeanpackage com.liuguilin.uploadphotossample;/* * 项目名: UploadPhotosSample * 包名: com.liuguilin.uploadphotossample * 文件名: PhotoBean * 创建者: LGL * 创建时间
27、: 2016/8/31 13:14 * 描述: 图片存储对象 */import android.graphics.Bitmap;public class PhotoBean /路径 private String path; /是否选择 private boolean isSelect; /位图转换 private Bitmap bitmap; public String getPath() return path; public void setPath(String path) this.path = path; public boolean isSelect() return isSele
28、ct; public void setSelect(boolean select) isSelect = select; public Bitmap getBitmap() return bitmap; public void setBitmap(Bitmap bitmap) this.bitmap = bitmap; OK,现在可以专心的来写我们的Adapter,也就是数据适配器了GridAdapterpackage com.liuguilin.uploadphotossample;/* * 项目名: UploadPhotosSample * 包名: com.liuguilin.upload
29、photossample * 文件名: GridAdapter * 创建者: LGL * 创建时间: 2016/8/31 13:32 * 描述: 数据适配器 */import android.content.Context;import android.graphics.Bitmap;import android.os.AsyncTask;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;impor
30、t android.widget.ImageView;import java.util.List;public class GridAdapter extends BaseAdapter /数据 private List<PhotoBean> mList; /布局加载器 private LayoutInflater mInflater; /实体类 private PhotoBean bean; /上下文 private Context mContext; /屏幕宽高 private int w, h; /* * param mContext * param mList */ pub
31、lic GridAdapter(Context mContext, List<PhotoBean> mList) this.mContext = mContext; this.mList = mList; /系統服務 mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); getPhoneWH(); /* * 获取手机屏幕的宽高 */ private void getPhoneWH() w = mContext.getResources().getDisplay
32、Metrics().widthPixels; h = mContext.getResources().getDisplayMetrics().heightPixels; Override public int getCount() return mList.size(); Override public Object getItem(int i) return mList.get(i); Override public long getItemId(int i) return i; Override public View getView(int i, View view, ViewGroup
33、 viewGroup) ViewHolder viewHolder = null; if (view = l) viewHolder = new ViewHolder(); view = mInflater.inflate(R.layout.list_item, null); /初始化 viewHolder.img = (ImageView) view.findViewById(R.id.img); /设置图片最小宽高 viewHolder.img.setMinimumWidth(w / 3); viewHolder.img.setMinimumHeight(h / 3); viewHolde
34、r.img_select = (ImageView) view.findViewById(R.id.img_select); view.setTag(viewHolder); else viewHolder = (ViewHolder) view.getTag(); /获取position bean = mList.get(i); /是否选中 if (bean.isSelect() viewHolder.img_select.setVisibility(View.VISIBLE); else viewHolder.img_select.setVisibility(View.INVISIBLE)
35、; /是否有图片 if (bean.getBitmap() = null) /图片加载,异步加载 new ImgTask().execute(bean.getPath(), String.valueOf(i); else /设置图片 viewHolder.img.setImageBitmap(bean.getBitmap(); return view; /* * 緩存 */ static class ViewHolder private ImageView img; private ImageView img_select; /* * 异步任务 */ private class ImgTask
36、 extends AsyncTask<String, Void, Bitmap> /* * 后台加载 * * param strings * return */ Override protected Bitmap doInBackground(String. strings) /图片路径 String path = strings0; /position int position = Integer.parseInt(strings1); /图片压缩 Bitmap bitmap = BitmapUtils.getScaleBitmapPath(mContext, path); /设
37、置图片 mList.get(position).setBitmap(bitmap); return bitmap; /* * 刷新视图 * * param bitmap */ Override protected void onPostExecute(Bitmap bitmap) super.onPostEute(bitmap); /刷新 GridAdapter.this.notifyDataSetChanged(); 我们在里面做了很多的事情,首选是ViewHolder的优化,然后就是异步加载图片了,接着获取屏幕的高宽去适配,当然,这里做了一个bitmap的工具类BitmapUtilspac
38、kage com.liuguilin.uploadphotossample;/* * 项目名: UploadPhotosSample * 包名: com.liuguilin.uploadphotossample * 文件名: BitmapUtils * 创建者: LGL * 创建时间: 2016/8/31 14:18 * 描述: 图片压缩处理 */import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;public class BitmapUtils
39、/* * 本地图片压缩处理 * * param mContext 上下文 * param path 路径 * return */ public static Bitmap getScaleBitmapPath(Context mContext, String path) Bitmap bitmap; int w; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; bitmap = BitmapFactory.decodeFile(path, option
40、s); w = options.outWidth; if (w < 50) options.inSampleSize = w / 50; options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeFile(path, options); else bitmap = BitmapFactory.decodeFile(path); return bitmap; 现在我们可以把我们的数据加载进去了 /* * 初始化View */ private void initView() btnOk = (Button) findVi
41、ewById(R.id.btnOk); btnOk.setOnClickListener(this); mGridView = (GridView) findViewById(R.id.mGridView); /设置数据 adapter = new GridAdapter(this, mList); mGridView.setAdapter(adapter); 这样,我们其实是可以看到加载的效果的,这就是相册实现的最基本原理了到这里,基本上就成功了一半了,现在开始做点击了,只要点击图片,就显示勾选,那我们就要监听他的点击事件了 /* * 点击事件 */ mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() Override p
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025建筑工地广告牌工程施工合同
- 无锡市住房租赁合同
- 中外货物买卖合同
- 2025金融科技公司贷款合同
- 幼儿大班火箭上天
- 2025年份一月份装修合同入户门防盗等级检测争议解决机制
- 主播创业合同范例
- 小学六年级语文教学计划(6篇)
- 2025农行小额存单质押贷款合同
- 借款合同范例手机
- 第五届绵阳市职业技能大赛赛项技术文件-焊工技术文件
- 询价开标流程
- 新型电力系统广义充裕性评估及规划方法研究
- T-GRM 102-2024 深色有隔内生真菌胞外代谢物应用技术规程
- 2025年池州职业技术学院单招职业适应性测试题库有答案
- 2025河北张家口崇礼区人民陪审员选任40人历年高频重点模拟试卷提升(共500题附带答案详解)
- 拉森钢板桩支护施工方案
- 2025年荆门市水务局事业单位公开招聘工作人员招聘历年高频重点模拟试卷提升(共500题附带答案详解)
- 老年人安全与环境护理
- 天车安全操作规程课件
- 2023JGJ 196建筑施工塔式起重机安装、使用、拆卸安全技术规程
评论
0/150
提交评论