日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 超高仿微信图片选择器 图片该这么加载

發布時間:2025/3/19 Android 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 超高仿微信图片选择器 图片该这么加载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/39943731,本文出自:【張鴻洋的博客】

1、概述

關于手機圖片加載器,在當今像素隨隨便便破千萬的時代,一張圖片占據的內存都相當可觀,作為高大尚程序猿的我們,有必要掌握圖片的壓縮,緩存等處理,以到達縱使你有萬張照片,縱使你的像素再高,我們也能正確的顯示所有的圖片。當然了,單純顯示圖片沒撒意思,我們決定高仿一下微信的圖片選擇器,在此,感謝微信!本篇博客將基于以下兩篇博客:

Android 快速開發系列 打造萬能的ListView GridView 適配器? 將使用我們打造的CommonAdapter作為我們例子中GridView以及ListView的適配器

Android Handler 異步消息處理機制的妙用 創建強大的圖片加載類?將使用我們自己寫的ImageLoader作為我們的圖片加載的核心類

如果你沒看過也沒關系,等看完本篇博客,可以結合以上兩篇再進行充分理解一下。

好了,首先貼一下效果圖:




動態圖實在是錄不出來,大家自己打開微信點擊發表圖片,或者聊天窗口發送圖片,大致和微信的效果一樣~

簡單描述一下:

1、默認顯示圖片最多的文件夾圖片,以及底部顯示圖片總數量;如上圖1;

2、點擊底部,彈出popupWindow,popupWindow包含所有含有圖片的文件夾,以及顯示每個文件夾中圖片數量;如上圖2;注:此時Activity變暗

3、選擇任何文件夾,進入該文件夾圖片顯示,可以點擊選擇圖片,當然了,點擊已選擇的圖片則會取消選擇;如上圖3;注:選中圖片變暗

當然了,最重要的效果一定流暢,不能動不動OOM~~

本人測試手機小米2s,圖片6802張,未出現OOM異常,效果也是非常流暢,堪比圖庫~

不過存在bug在所難免,大家可以留言說下自己發現的bug;文末會提供源碼下載。

好了,下面就可以代碼的征程了~

2、圖片的列表頁

首先對手機中圖片進行掃描,拿到圖片數量最多的,直接顯示在GridView上;并且掃描結束,得到一個所有包含圖片的文件夾信息的List;

對于文件夾信息,我們單獨創建了一個Bean:

[java]?view plaincopy

  • package?com.zhy.bean;??

  • ??

  • public?class?ImageFloder??

  • {??

  • ????/**?

  • ?????*?圖片的文件夾路徑?

  • ?????*/??

  • ????private?String?dir;??

  • ??

  • ????/**?

  • ?????*?第一張圖片的路徑?

  • ?????*/??

  • ????private?String?firstImagePath;??

  • ??

  • ????/**?

  • ?????*?文件夾的名稱?

  • ?????*/??

  • ????private?String?name;??

  • ??

  • ????/**?

  • ?????*?圖片的數量?

  • ?????*/??

  • ????private?int?count;??

  • ??

  • ????public?String?getDir()??

  • ????{??

  • ????????return?dir;??

  • ????}??

  • ??

  • ????public?void?setDir(String?dir)??

  • ????{??

  • ????????this.dir?=?dir;??

  • ????????int?lastIndexOf?=?this.dir.lastIndexOf("/");??

  • ????????this.name?=?this.dir.substring(lastIndexOf);??

  • ????}??

  • ??

  • ????public?String?getFirstImagePath()??

  • ????{??

  • ????????return?firstImagePath;??

  • ????}??

  • ??

  • ????public?void?setFirstImagePath(String?firstImagePath)??

  • ????{??

  • ????????this.firstImagePath?=?firstImagePath;??

  • ????}??

  • ??

  • ????public?String?getName()??

  • ????{??

  • ????????return?name;??

  • ????}??

  • ????public?int?getCount()??

  • ????{??

  • ????????return?count;??

  • ????}??

  • ??

  • ????public?void?setCount(int?count)??

  • ????{??

  • ????????this.count?=?count;??

  • ????}??

  • ??

  • ??????

  • ??

  • }??


  • 用來存儲當前文件夾的路徑,當前文件夾包含多少張圖片,以及第一張圖片路徑用于做文件夾的圖標;注:文件夾的名稱,我們在set文件夾的路徑的時候,自動提取,仔細看下setDir這個方法。

    接下來就是掃描手機圖片的代碼了:

    [java]?view plaincopy

  • @Override??

  • ????protected?void?onCreate(Bundle?savedInstanceState)??

  • ????{??

  • ????????super.onCreate(savedInstanceState);??

  • ????????setContentView(R.layout.activity_main);??

  • ??

  • ????????DisplayMetrics?outMetrics?=?new?DisplayMetrics();??

  • ????????getWindowManager().getDefaultDisplay().getMetrics(outMetrics);??

  • ????????mScreenHeight?=?outMetrics.heightPixels;??

  • ??

  • ????????initView();??

  • ????????getImages();??

  • ????????initEvent();??

  • ??

  • ????}??

  • ??

  • ??????

  • ??

  • ????/**?

  • ?????*?利用ContentProvider掃描手機中的圖片,此方法在運行在子線程中?完成圖片的掃描,最終獲得jpg最多的那個文件夾?

  • ?????*/??

  • ????private?void?getImages()??

  • ????{??

  • ????????if?(!Environment.getExternalStorageState().equals(??

  • ????????????????Environment.MEDIA_MOUNTED))??

  • ????????{??

  • ????????????Toast.makeText(this,?"暫無外部存儲",?Toast.LENGTH_SHORT).show();??

  • ????????????return;??

  • ????????}??

  • ????????//?顯示進度條??

  • ????????mProgressDialog?=?ProgressDialog.show(this,?null,?"正在加載...");??

  • ??

  • ????????new?Thread(new?Runnable()??

  • ????????{??

  • ????????????@Override??

  • ????????????public?void?run()??

  • ????????????{??

  • ??

  • ????????????????String?firstImage?=?null;??

  • ??

  • ????????????????Uri?mImageUri?=?MediaStore.Images.Media.EXTERNAL_CONTENT_URI;??

  • ????????????????ContentResolver?mContentResolver?=?MainActivity.this??

  • ????????????????????????.getContentResolver();??

  • ??

  • ????????????????//?只查詢jpeg和png的圖片??

  • ????????????????Cursor?mCursor?=?mContentResolver.query(mImageUri,?null,??

  • ????????????????????????MediaStore.Images.Media.MIME_TYPE?+?"=??or?"??

  • ????????????????????????????????+?MediaStore.Images.Media.MIME_TYPE?+?"=?",??

  • ????????????????????????new?String[]?{?"image/jpeg",?"image/png"?},??

  • ????????????????????????MediaStore.Images.Media.DATE_MODIFIED);??

  • ??

  • ????????????????Log.e("TAG",?mCursor.getCount()?+?"");??

  • ????????????????while?(mCursor.moveToNext())??

  • ????????????????{??

  • ????????????????????//?獲取圖片的路徑??

  • ????????????????????String?path?=?mCursor.getString(mCursor??

  • ????????????????????????????.getColumnIndex(MediaStore.Images.Media.DATA));??

  • ??

  • ????????????????????Log.e("TAG",?path);??

  • ????????????????????//?拿到第一張圖片的路徑??

  • ????????????????????if?(firstImage?==?null)??

  • ????????????????????????firstImage?=?path;??

  • ????????????????????//?獲取該圖片的父路徑名??

  • ????????????????????File?parentFile?=?new?File(path).getParentFile();??

  • ????????????????????if?(parentFile?==?null)??

  • ????????????????????????continue;??

  • ????????????????????String?dirPath?=?parentFile.getAbsolutePath();??

  • ????????????????????ImageFloder?imageFloder?=?null;??

  • ????????????????????//?利用一個HashSet防止多次掃描同一個文件夾(不加這個判斷,圖片多起來還是相當恐怖的~~)??

  • ????????????????????if?(mDirPaths.contains(dirPath))??

  • ????????????????????{??

  • ????????????????????????continue;??

  • ????????????????????}?else??

  • ????????????????????{??

  • ????????????????????????mDirPaths.add(dirPath);??

  • ????????????????????????//?初始化imageFloder??

  • ????????????????????????imageFloder?=?new?ImageFloder();??

  • ????????????????????????imageFloder.setDir(dirPath);??

  • ????????????????????????imageFloder.setFirstImagePath(path);??

  • ????????????????????}??

  • ??

  • ????????????????????int?picSize?=?parentFile.list(new?FilenameFilter()??

  • ????????????????????{??

  • ????????????????????????@Override??

  • ????????????????????????public?boolean?accept(File?dir,?String?filename)??

  • ????????????????????????{??

  • ????????????????????????????if?(filename.endsWith(".jpg")??

  • ????????????????????????????????????||?filename.endsWith(".png")??

  • ????????????????????????????????????||?filename.endsWith(".jpeg"))??

  • ????????????????????????????????return?true;??

  • ????????????????????????????return?false;??

  • ????????????????????????}??

  • ????????????????????}).length;??

  • ????????????????????totalCount?+=?picSize;??

  • ??

  • ????????????????????imageFloder.setCount(picSize);??

  • ????????????????????mImageFloders.add(imageFloder);??

  • ??

  • ????????????????????if?(picSize?>?mPicsSize)??

  • ????????????????????{??

  • ????????????????????????mPicsSize?=?picSize;??

  • ????????????????????????mImgDir?=?parentFile;??

  • ????????????????????}??

  • ????????????????}??

  • ????????????????mCursor.close();??

  • ??

  • ????????????????//?掃描完成,輔助的HashSet也就可以釋放內存了??

  • ????????????????mDirPaths?=?null;??

  • ??

  • ????????????????//?通知Handler掃描圖片完成??

  • ????????????????mHandler.sendEmptyMessage(0x110);??

  • ??

  • ????????????}??

  • ????????}).start();??

  • ??

  • ????}??


  • ps:運行出現空指針的話,在81行的位置添加判斷,if(parentFile.list()==null)continue , 切記~~~有些圖片比較詭異~~;?

    initView就不看了,都是些findViewById;

    getImages主要就是掃描圖片的代碼,我們開啟了一個Thread進行掃描,掃描完成以后,我們得到了圖片最多文件夾路徑(mImgDir),手機中圖片數量(totalCount);以及所有包含圖片文件夾信息(mImageFloders)

    然后我們通過handler發送消息,在handleMessage里面:

    1、創建GridView的適配器,為我們的GridView設置適配器,顯示圖片;

    2、有了mImageFloders,就可以創建我們的popupWindow了

    看一眼我們的Handler

    [java]?view plaincopy

  • private?Handler?mHandler?=?new?Handler()??

  • ????{??

  • ????????public?void?handleMessage(android.os.Message?msg)??

  • ????????{??

  • ????????????mProgressDialog.dismiss();??

  • ????????????//為View綁定數據??

  • ????????????data2View();??

  • ????????????//初始化展示文件夾的popupWindw??

  • ????????????initListDirPopupWindw();??

  • ????????}??

  • ????};??


  • 可以看到分別干了上述的兩件事:

    [java]?view plaincopy

  • /**?

  • ?????*?為View綁定數據?

  • ?????*/??

  • ????private?void?data2View()??

  • ????{??

  • ????????if?(mImgDir?==?null)??

  • ????????{??

  • ????????????Toast.makeText(getApplicationContext(),?"擦,一張圖片沒掃描到",??

  • ????????????????????Toast.LENGTH_SHORT).show();??

  • ????????????return;??

  • ????????}??

  • ??

  • ????????mImgs?=?Arrays.asList(mImgDir.list());??

  • ????????/**?

  • ?????????*?可以看到文件夾的路徑和圖片的路徑分開保存,極大的減少了內存的消耗;?

  • ?????????*/??

  • ????????mAdapter?=?new?MyAdapter(getApplicationContext(),?mImgs,??

  • ????????????????R.layout.grid_item,?mImgDir.getAbsolutePath());??

  • ????????mGirdView.setAdapter(mAdapter);??

  • ????????mImageCount.setText(totalCount?+?"張");??

  • ????};??


  • data2View就是我們當前Activity上所有的View設置數據了。

    看到這里還用到了一個Adapter,我們GridView的:

    [java]?view plaincopy

  • package?com.zhy.imageloader;??

  • ??

  • import?java.util.LinkedList;??

  • import?java.util.List;??

  • ??

  • import?android.content.Context;??

  • import?android.graphics.Color;??

  • import?android.view.View;??

  • import?android.view.View.OnClickListener;??

  • import?android.widget.ImageView;??

  • ??

  • import?com.zhy.utils.CommonAdapter;??

  • ??

  • public?class?MyAdapter?extends?CommonAdapter<String>??

  • {??

  • ??

  • ????/**?

  • ?????*?用戶選擇的圖片,存儲為圖片的完整路徑?

  • ?????*/??

  • ????public?static?List<String>?mSelectedImage?=?new?LinkedList<String>();??

  • ??

  • ????/**?

  • ?????*?文件夾路徑?

  • ?????*/??

  • ????private?String?mDirPath;??

  • ??

  • ????public?MyAdapter(Context?context,?List<String>?mDatas,?int?itemLayoutId,??

  • ????????????String?dirPath)??

  • ????{??

  • ????????super(context,?mDatas,?itemLayoutId);??

  • ????????this.mDirPath?=?dirPath;??

  • ????}??

  • ??

  • ????@Override??

  • ????public?void?convert(final?com.zhy.utils.ViewHolder?helper,?final?String?item)??

  • ????{??

  • ????????//?設置no_pic??

  • ????????helper.setImageResource(R.id.id_item_image,?R.drawable.pictures_no);??

  • ????????//?設置no_selected??

  • ????????helper.setImageResource(R.id.id_item_select,??

  • ????????????????R.drawable.picture_unselected);??

  • ????????//?設置圖片??

  • ????????helper.setImageByUrl(R.id.id_item_image,?mDirPath?+?"/"?+?item);??

  • ??

  • ????????final?ImageView?mImageView?=?helper.getView(R.id.id_item_image);??

  • ????????final?ImageView?mSelect?=?helper.getView(R.id.id_item_select);??

  • ??

  • ????????mImageView.setColorFilter(null);??

  • ????????//?設置ImageView的點擊事件??

  • ????????mImageView.setOnClickListener(new?OnClickListener()??

  • ????????{??

  • ????????????//?選擇,則將圖片變暗,反之則反之??

  • ????????????@Override??

  • ????????????public?void?onClick(View?v)??

  • ????????????{??

  • ??

  • ????????????????//?已經選擇過該圖片??

  • ????????????????if?(mSelectedImage.contains(mDirPath?+?"/"?+?item))??

  • ????????????????{??

  • ????????????????????mSelectedImage.remove(mDirPath?+?"/"?+?item);??

  • ????????????????????mSelect.setImageResource(R.drawable.picture_unselected);??

  • ????????????????????mImageView.setColorFilter(null);??

  • ????????????????}?else??

  • ????????????????//?未選擇該圖片??

  • ????????????????{??

  • ????????????????????mSelectedImage.add(mDirPath?+?"/"?+?item);??

  • ????????????????????mSelect.setImageResource(R.drawable.pictures_selected);??

  • ????????????????????mImageView.setColorFilter(Color.parseColor("#77000000"));??

  • ????????????????}??

  • ??

  • ????????????}??

  • ????????});??

  • ??

  • ????????/**?

  • ?????????*?已經選擇過的圖片,顯示出選擇過的效果?

  • ?????????*/??

  • ????????if?(mSelectedImage.contains(mDirPath?+?"/"?+?item))??

  • ????????{??

  • ????????????mSelect.setImageResource(R.drawable.pictures_selected);??

  • ????????????mImageView.setColorFilter(Color.parseColor("#77000000"));??

  • ????????}??

  • ??

  • ????}??

  • }??


  • 可以看到我們GridView的Adapter繼承了我們的CommonAdapter,如果不知道CommonAdapter為何物,可以去看看萬能適配器那篇博文;

    我們現在只需要實現convert方法:

    在convert中,我們設置圖片,設置事件等,對于圖片的變暗,我們使用的是ImageView的setColorFilter?;根據Url加載圖片的操作封裝在helper.setImageByUrl(view,url)中,內部使用的是我們自己定義的ImageLoader,包括錯亂處理都已經封裝了,圖片策略我們使用的是LIFO后進先出;不清楚的可以看文章一開始說明的那兩篇博文,對于CommonAdapter以及ImageLoader都有從無到有的詳細打造過程;

    到此我們的第一個Activity的所有的任務就完成了~~~


    3、展現文件夾的PopupWindow

    現在我們要實現,點擊底部的布局彈出我們的文件夾選擇框,并且我們彈出框后面的Activity要變暗;

    不急著貼代碼,我們先考慮下PopupWindow怎么用最好,我們的PopupWindow需要設置布局文件,需要初始化View,需要初始化事件,還需要和Activity交互~~

    那么肯定的,我們使用獨立的類,這個類和Activity很相似,在里面initView(),initEvent()之類的。

    我們創建了一個popupWindow使用的超類:

    [java]?view plaincopy

  • package?com.zhy.utils;??

  • ??

  • import?java.util.List;??

  • ??

  • import?android.content.Context;??

  • import?android.graphics.drawable.BitmapDrawable;??

  • import?android.view.MotionEvent;??

  • import?android.view.View;??

  • import?android.view.View.OnTouchListener;??

  • import?android.widget.PopupWindow;??

  • ??

  • public?abstract?class?BasePopupWindowForListView<T>?extends?PopupWindow??

  • {??

  • ????/**?

  • ?????*?布局文件的最外層View?

  • ?????*/??

  • ????protected?View?mContentView;??

  • ????protected?Context?context;??

  • ????/**?

  • ?????*?ListView的數據集?

  • ?????*/??

  • ????protected?List<T>?mDatas;??

  • ??

  • ????public?BasePopupWindowForListView(View?contentView,?int?width,?int?height,??

  • ????????????boolean?focusable)??

  • ????{??

  • ????????this(contentView,?width,?height,?focusable,?null);??

  • ????}??

  • ??

  • ????public?BasePopupWindowForListView(View?contentView,?int?width,?int?height,??

  • ????????????boolean?focusable,?List<T>?mDatas)??

  • ????{??

  • ????????this(contentView,?width,?height,?focusable,?mDatas,?new?Object[0]);??

  • ??

  • ????}??

  • ??

  • ????public?BasePopupWindowForListView(View?contentView,?int?width,?int?height,??

  • ????????????boolean?focusable,?List<T>?mDatas,?Object...?params)??

  • ????{??

  • ????????super(contentView,?width,?height,?focusable);??

  • ????????this.mContentView?=?contentView;??

  • ????????context?=?contentView.getContext();??

  • ????????if?(mDatas?!=?null)??

  • ????????????this.mDatas?=?mDatas;??

  • ??

  • ????????if?(params?!=?null?&&?params.length?>?0)??

  • ????????{??

  • ????????????beforeInitWeNeedSomeParams(params);??

  • ????????}??

  • ??

  • ????????setBackgroundDrawable(new?BitmapDrawable());??

  • ????????setTouchable(true);??

  • ????????setOutsideTouchable(true);??

  • ????????setTouchInterceptor(new?OnTouchListener()??

  • ????????{??

  • ????????????@Override??

  • ????????????public?boolean?onTouch(View?v,?MotionEvent?event)??

  • ????????????{??

  • ????????????????if?(event.getAction()?==?MotionEvent.ACTION_OUTSIDE)??

  • ????????????????{??

  • ????????????????????dismiss();??

  • ????????????????????return?true;??

  • ????????????????}??

  • ????????????????return?false;??

  • ????????????}??

  • ????????});??

  • ????????initViews();??

  • ????????initEvents();??

  • ????????init();??

  • ????}??

  • ??

  • ????protected?abstract?void?beforeInitWeNeedSomeParams(Object...?params);??

  • ??

  • ????public?abstract?void?initViews();??

  • ??

  • ????public?abstract?void?initEvents();??

  • ??

  • ????public?abstract?void?init();??

  • ??

  • ????public?View?findViewById(int?id)??

  • ????{??

  • ????????return?mContentView.findViewById(id);??

  • ????}??

  • ??

  • ????protected?static?int?dpToPx(Context?context,?int?dp)??

  • ????{??

  • ????????return?(int)?(context.getResources().getDisplayMetrics().density?*?dp?+?0.5f);??

  • ????}??

  • ??

  • }??


  • 也就是封裝了一下popupWindow常用的一些設置,然后使用了類似模版方法模式,約束子類,必須實現initView,initEvent,init等方法

    [java]?view plaincopy

  • package?com.zhy.imageloader;??

  • ??

  • import?java.util.List;??

  • ??

  • import?android.view.View;??

  • import?android.widget.AdapterView;??

  • import?android.widget.AdapterView.OnItemClickListener;??

  • import?android.widget.ListView;??

  • ??

  • import?com.zhy.bean.ImageFloder;??

  • import?com.zhy.utils.BasePopupWindowForListView;??

  • import?com.zhy.utils.CommonAdapter;??

  • import?com.zhy.utils.ViewHolder;??

  • ??

  • public?class?ListImageDirPopupWindow?extends?BasePopupWindowForListView<ImageFloder>??

  • {??

  • ????private?ListView?mListDir;??

  • ??

  • ????public?ListImageDirPopupWindow(int?width,?int?height,??

  • ????????????List<ImageFloder>?datas,?View?convertView)??

  • ????{??

  • ????????super(convertView,?width,?height,?true,?datas);??

  • ????}??

  • ??

  • ????@Override??

  • ????public?void?initViews()??

  • ????{??

  • ????????mListDir?=?(ListView)?findViewById(R.id.id_list_dir);??

  • ????????mListDir.setAdapter(new?CommonAdapter<ImageFloder>(context,?mDatas,??

  • ????????????????R.layout.list_dir_item)??

  • ????????{??

  • ????????????@Override??

  • ????????????public?void?convert(ViewHolder?helper,?ImageFloder?item)??

  • ????????????{??

  • ????????????????helper.setText(R.id.id_dir_item_name,?item.getName());??

  • ????????????????helper.setImageByUrl(R.id.id_dir_item_image,??

  • ????????????????????????item.getFirstImagePath());??

  • ????????????????helper.setText(R.id.id_dir_item_count,?item.getCount()?+?"張");??

  • ????????????}??

  • ????????});??

  • ????}??

  • ??

  • ????public?interface?OnImageDirSelected??

  • ????{??

  • ????????void?selected(ImageFloder?floder);??

  • ????}??

  • ??

  • ????private?OnImageDirSelected?mImageDirSelected;??

  • ??

  • ????public?void?setOnImageDirSelected(OnImageDirSelected?mImageDirSelected)??

  • ????{??

  • ????????this.mImageDirSelected?=?mImageDirSelected;??

  • ????}??

  • ??

  • ????@Override??

  • ????public?void?initEvents()??

  • ????{??

  • ????????mListDir.setOnItemClickListener(new?OnItemClickListener()??

  • ????????{??

  • ????????????@Override??

  • ????????????public?void?onItemClick(AdapterView<?>?parent,?View?view,??

  • ????????????????????int?position,?long?id)??

  • ????????????{??

  • ??

  • ????????????????if?(mImageDirSelected?!=?null)??

  • ????????????????{??

  • ????????????????????mImageDirSelected.selected(mDatas.get(position));??

  • ????????????????}??

  • ????????????}??

  • ????????});??

  • ????}??

  • ??

  • ????@Override??

  • ????public?void?init()??

  • ????{??

  • ????????//?TODO?Auto-generated?method?stub??

  • ??

  • ????}??

  • ??

  • ????@Override??

  • ????protected?void?beforeInitWeNeedSomeParams(Object...?params)??

  • ????{??

  • ????????//?TODO?Auto-generated?method?stub??

  • ????}??

  • ??

  • }??

  • 好了,現在就是我們正在的popupWindow咯,布局文件夾主要是個ListView,所以在initView里面,我們得設置它的適配器;當然了,這里的適配器依然用我們的CommonAdapter,幾行代碼搞定~~

    然后我們需要和Activity交互,當我們點擊某個文件夾的時候,外層的Activity需要改變它GridView的數據源,展示我們點擊文件夾的圖片;

    關于交互,我們從Activity的角度去看彈出框,Activity想知道什么,只想知道選擇了別的文件夾來告訴我,所以我們創建一個接口OnImageDirSelected,對Activity設置回調;

    這里還可以這么寫:就是把popupWindow的ListView公布出去,然后在Activity里面使用popupWindow.getListView(),setOnItemClickListener,這么做,個人覺得不好,耦合度太高,客戶簡單改下需求“這個文件夾展示,給我們換了,換成GridView”,呵呵,此時,你需要到處去修改Activity里面的代碼,因為你Activity里面竟然還有個popupWindow.getListView。

    好了,扯多了,初始化事件的代碼:

    [java]?view plaincopy

  • @Override??

  • ????public?void?initEvents()??

  • ????{??

  • ????????mListDir.setOnItemClickListener(new?OnItemClickListener()??

  • ????????{??

  • ????????????@Override??

  • ????????????public?void?onItemClick(AdapterView<?>?parent,?View?view,??

  • ????????????????????int?position,?long?id)??

  • ????????????{??

  • ??

  • ????????????????if?(mImageDirSelected?!=?null)??

  • ????????????????{??

  • ????????????????????mImageDirSelected.selected(mDatas.get(position));??

  • ????????????????}??

  • ????????????}??

  • ????????});??

  • ????}??


  • 如果有人設置了回調,我們就調用;

    到此,整個popupWindow就出爐了,接下來就看啥時候讓它展示了;

    4、選擇不同的文件夾

    上面說道,當掃描圖片完成,拿到包含圖片的文件夾信息列表;這個列表就是我們popupWindow所需的數據,所以我們的popupWindow的初始化在handleMessage(上面貼了handler的代碼)里面:

    在handleMessage里面調用initListDirPopupWindw

    [java]?view plaincopy

  • /**?

  • ?????*?初始化展示文件夾的popupWindw?

  • ?????*/??

  • ????private?void?initListDirPopupWindw()??

  • ????{??

  • ????????mListImageDirPopupWindow?=?new?ListImageDirPopupWindow(??

  • ????????????????LayoutParams.MATCH_PARENT,?(int)?(mScreenHeight?*?0.7),??

  • ????????????????mImageFloders,?LayoutInflater.from(getApplicationContext())??

  • ????????????????????????.inflate(R.layout.list_dir,?null));??

  • ??

  • ????????mListImageDirPopupWindow.setOnDismissListener(new?OnDismissListener()??

  • ????????{??

  • ??

  • ????????????@Override??

  • ????????????public?void?onDismiss()??

  • ????????????{??

  • ????????????????//?設置背景顏色變暗??

  • ????????????????WindowManager.LayoutParams?lp?=?getWindow().getAttributes();??

  • ????????????????lp.alpha?=?1.0f;??

  • ????????????????getWindow().setAttributes(lp);??

  • ????????????}??

  • ????????});??

  • ????????//?設置選擇文件夾的回調??

  • ????????mListImageDirPopupWindow.setOnImageDirSelected(this);??

  • ????}??

  • 我們初始化我們的popupWindow,設置了關閉對話框的回調,已經設置了選擇不同文件夾的回調;
    這里僅僅是初始化,下面看我們合適將其彈出的,其實整個Activity也就一個事件,點擊彈出該對話框,所以看Activity的initEvents方法:

    [java]?view plaincopy

  • private?void?initEvent()??

  • ????{??

  • ????????/**?

  • ?????????*?為底部的布局設置點擊事件,彈出popupWindow?

  • ?????????*/??

  • ????????mBottomLy.setOnClickListener(new?OnClickListener()??

  • ????????{??

  • ????????????@Override??

  • ????????????public?void?onClick(View?v)??

  • ????????????{??

  • ????????????????mListImageDirPopupWindow??

  • ????????????????????????.setAnimationStyle(R.style.anim_popup_dir);??

  • ????????????????mListImageDirPopupWindow.showAsDropDown(mBottomLy,?0,?0);??

  • ??

  • ????????????????//?設置背景顏色變暗??

  • ????????????????WindowManager.LayoutParams?lp?=?getWindow().getAttributes();??

  • ????????????????lp.alpha?=?.3f;??

  • ????????????????getWindow().setAttributes(lp);??

  • ????????????}??

  • ????????});??

  • ????}??


  • 可以看到,我們為底部布局設置點擊事件;設置popupWindow的彈出與消失的動畫;已經讓Activity背景變暗變亮,通過改變Window alpha實現的。變亮在彈出框消息的監聽里面~~

    動畫的文件就不貼了,大家自己看源碼;

    popupWindow彈出了,用戶此時可以選擇不同的文件夾,那么現在該看選擇后的回調的代碼了:

    我們的Activity實現了該接口,直接看實現的方法:

    [java]?view plaincopy

  • @Override??

  • public?void?selected(ImageFloder?floder)??

  • {??

  • ??

  • ????mImgDir?=?new?File(floder.getDir());??

  • ????mImgs?=?Arrays.asList(mImgDir.list(new?FilenameFilter()??

  • ????{??

  • ????????@Override??

  • ????????public?boolean?accept(File?dir,?String?filename)??

  • ????????{??

  • ????????????if?(filename.endsWith(".jpg")?||?filename.endsWith(".png")??

  • ????????????????????||?filename.endsWith(".jpeg"))??

  • ????????????????return?true;??

  • ????????????return?false;??

  • ????????}??

  • ????}));??

  • ????/**?

  • ?????*?可以看到文件夾的路徑和圖片的路徑分開保存,極大的減少了內存的消耗;?

  • ?????*/??

  • ????mAdapter?=?new?MyAdapter(getApplicationContext(),?mImgs,??

  • ????????????R.layout.grid_item,?mImgDir.getAbsolutePath());??

  • ????mGirdView.setAdapter(mAdapter);??

  • ????//?mAdapter.notifyDataSetChanged();??

  • ????mImageCount.setText(floder.getCount()?+?"張");??

  • ????mChooseDir.setText(floder.getName());??

  • ????mListImageDirPopupWindow.dismiss();??

  • ??

  • }??


  • 我們改變了GridView的適配器,以及底部的控件上的文件夾名稱,文件數量等等;

    好了,到此結束;整篇由于篇幅原因沒有貼任何布局文件,大家自己通過源碼查看;

    在此希望大家可以通過該案例,能夠去其糟粕,取其精華,學習其中值得借鑒的代碼風格,不要真的當作一個例子去學習~~



    源碼點擊下載 ?

    ps:請真機測試,反正我的模擬器掃描不到圖片~

    ps:運行出現空指針的話,在getImages中添加判斷,if(parentFile.list()==null)continue , 切記~~~具體位置,上面有說;?





    ---------------------------------------------------------------------------------------------------------

    建了一個QQ群,方便大家交流。群號:55032675



    ----------------------------------------------------------------------------------------------------------

    博主部分視頻已經上線,如果你不喜歡枯燥的文本,請猛戳(初錄,期待您的支持):

    1、高仿微信5.2.1主界面及消息提醒

    2、高仿QQ5.0側滑

















    轉載于:https://my.oschina.net/u/1177694/blog/510120

    總結

    以上是生活随笔為你收集整理的Android 超高仿微信图片选择器 图片该这么加载的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。