Android 超高仿微信图片选择器 图片该这么加载
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/39943731,本文出自:【張鴻洋的博客】
1、概述
關于手機圖片加載器,在當今像素隨隨便便破千萬的時代,一張圖片占據(jù)的內(nèi)存都相當可觀,作為高大尚程序猿的我們,有必要掌握圖片的壓縮,緩存等處理,以到達縱使你有萬張照片,縱使你的像素再高,我們也能正確的顯示所有的圖片。當然了,單純顯示圖片沒撒意思,我們決定高仿一下微信的圖片選擇器,在此,感謝微信!本篇博客將基于以下兩篇博客:
Android 快速開發(fā)系列 打造萬能的ListView GridView 適配器? 將使用我們打造的CommonAdapter作為我們例子中GridView以及ListView的適配器
Android Handler 異步消息處理機制的妙用 創(chuàng)建強大的圖片加載類?將使用我們自己寫的ImageLoader作為我們的圖片加載的核心類
如果你沒看過也沒關系,等看完本篇博客,可以結合以上兩篇再進行充分理解一下。
好了,首先貼一下效果圖:
動態(tài)圖實在是錄不出來,大家自己打開微信點擊發(fā)表圖片,或者聊天窗口發(fā)送圖片,大致和微信的效果一樣~
簡單描述一下:
1、默認顯示圖片最多的文件夾圖片,以及底部顯示圖片總數(shù)量;如上圖1;
2、點擊底部,彈出popupWindow,popupWindow包含所有含有圖片的文件夾,以及顯示每個文件夾中圖片數(shù)量;如上圖2;注:此時Activity變暗
3、選擇任何文件夾,進入該文件夾圖片顯示,可以點擊選擇圖片,當然了,點擊已選擇的圖片則會取消選擇;如上圖3;注:選中圖片變暗
當然了,最重要的效果一定流暢,不能動不動OOM~~
本人測試手機小米2s,圖片6802張,未出現(xiàn)OOM異常,效果也是非常流暢,堪比圖庫~
不過存在bug在所難免,大家可以留言說下自己發(fā)現(xiàn)的bug;文末會提供源碼下載。
好了,下面就可以代碼的征程了~
2、圖片的列表頁
首先對手機中圖片進行掃描,拿到圖片數(shù)量最多的,直接顯示在GridView上;并且掃描結束,得到一個所有包含圖片的文件夾信息的List;
對于文件夾信息,我們單獨創(chuàng)建了一個Bean:
[java]?view plaincopy
package?com.zhy.bean;??
??
public?class?ImageFloder??
{??
????/**?
?????*?圖片的文件夾路徑?
?????*/??
????private?String?dir;??
??
????/**?
?????*?第一張圖片的路徑?
?????*/??
????private?String?firstImagePath;??
??
????/**?
?????*?文件夾的名稱?
?????*/??
????private?String?name;??
??
????/**?
?????*?圖片的數(shù)量?
?????*/??
????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也就可以釋放內(nèi)存了??
????????????????mDirPaths?=?null;??
??
????????????????//?通知Handler掃描圖片完成??
????????????????mHandler.sendEmptyMessage(0x110);??
??
????????????}??
????????}).start();??
??
????}??
ps:運行出現(xiàn)空指針的話,在81行的位置添加判斷,if(parentFile.list()==null)continue , 切記~~~有些圖片比較詭異~~;?
initView就不看了,都是些findViewById;
getImages主要就是掃描圖片的代碼,我們開啟了一個Thread進行掃描,掃描完成以后,我們得到了圖片最多文件夾路徑(mImgDir),手機中圖片數(shù)量(totalCount);以及所有包含圖片文件夾信息(mImageFloders)
然后我們通過handler發(fā)送消息,在handleMessage里面:
1、創(chuàng)建GridView的適配器,為我們的GridView設置適配器,顯示圖片;
2、有了mImageFloders,就可以創(chuàng)建我們的popupWindow了
看一眼我們的Handler
[java]?view plaincopy
private?Handler?mHandler?=?new?Handler()??
????{??
????????public?void?handleMessage(android.os.Message?msg)??
????????{??
????????????mProgressDialog.dismiss();??
????????????//為View綁定數(shù)據(jù)??
????????????data2View();??
????????????//初始化展示文件夾的popupWindw??
????????????initListDirPopupWindw();??
????????}??
????};??
可以看到分別干了上述的兩件事:
[java]?view plaincopy
/**?
?????*?為View綁定數(shù)據(jù)?
?????*/??
????private?void?data2View()??
????{??
????????if?(mImgDir?==?null)??
????????{??
????????????Toast.makeText(getApplicationContext(),?"擦,一張圖片沒掃描到",??
????????????????????Toast.LENGTH_SHORT).show();??
????????????return;??
????????}??
??
????????mImgs?=?Arrays.asList(mImgDir.list());??
????????/**?
?????????*?可以看到文件夾的路徑和圖片的路徑分開保存,極大的減少了內(nèi)存的消耗;?
?????????*/??
????????mAdapter?=?new?MyAdapter(getApplicationContext(),?mImgs,??
????????????????R.layout.grid_item,?mImgDir.getAbsolutePath());??
????????mGirdView.setAdapter(mAdapter);??
????????mImageCount.setText(totalCount?+?"張");??
????};??
data2View就是我們當前Activity上所有的View設置數(shù)據(jù)了。
看到這里還用到了一個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)??
????????????{??
??
????????????????//?已經(jīng)選擇過該圖片??
????????????????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"));??
????????????????}??
??
????????????}??
????????});??
??
????????/**?
?????????*?已經(jīng)選擇過的圖片,顯示出選擇過的效果?
?????????*/??
????????if?(mSelectedImage.contains(mDirPath?+?"/"?+?item))??
????????{??
????????????mSelect.setImageResource(R.drawable.pictures_selected);??
????????????mImageView.setColorFilter(Color.parseColor("#77000000"));??
????????}??
??
????}??
}??
可以看到我們GridView的Adapter繼承了我們的CommonAdapter,如果不知道CommonAdapter為何物,可以去看看萬能適配器那篇博文;
我們現(xiàn)在只需要實現(xiàn)convert方法:
在convert中,我們設置圖片,設置事件等,對于圖片的變暗,我們使用的是ImageView的setColorFilter?;根據(jù)Url加載圖片的操作封裝在helper.setImageByUrl(view,url)中,內(nèi)部使用的是我們自己定義的ImageLoader,包括錯亂處理都已經(jīng)封裝了,圖片策略我們使用的是LIFO后進先出;不清楚的可以看文章一開始說明的那兩篇博文,對于CommonAdapter以及ImageLoader都有從無到有的詳細打造過程;
到此我們的第一個Activity的所有的任務就完成了~~~
3、展現(xiàn)文件夾的PopupWindow
現(xiàn)在我們要實現(xiàn),點擊底部的布局彈出我們的文件夾選擇框,并且我們彈出框后面的Activity要變暗;
不急著貼代碼,我們先考慮下PopupWindow怎么用最好,我們的PopupWindow需要設置布局文件,需要初始化View,需要初始化事件,還需要和Activity交互~~
那么肯定的,我們使用獨立的類,這個類和Activity很相似,在里面initView(),initEvent()之類的。
我們創(chuàng)建了一個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的數(shù)據(jù)集?
?????*/??
????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常用的一些設置,然后使用了類似模版方法模式,約束子類,必須實現(xiàn)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??
????}??
??
}??
好了,現(xiàn)在就是我們正在的popupWindow咯,布局文件夾主要是個ListView,所以在initView里面,我們得設置它的適配器;當然了,這里的適配器依然用我們的CommonAdapter,幾行代碼搞定~~
然后我們需要和Activity交互,當我們點擊某個文件夾的時候,外層的Activity需要改變它GridView的數(shù)據(jù)源,展示我們點擊文件夾的圖片;
關于交互,我們從Activity的角度去看彈出框,Activity想知道什么,只想知道選擇了別的文件夾來告訴我,所以我們創(chuàng)建一個接口OnImageDirSelected,對Activity設置回調(diào);
這里還可以這么寫:就是把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));??
????????????????}??
????????????}??
????????});??
????}??
如果有人設置了回調(diào),我們就調(diào)用;
到此,整個popupWindow就出爐了,接下來就看啥時候讓它展示了;
4、選擇不同的文件夾
上面說道,當掃描圖片完成,拿到包含圖片的文件夾信息列表;這個列表就是我們popupWindow所需的數(shù)據(jù),所以我們的popupWindow的初始化在handleMessage(上面貼了handler的代碼)里面:
在handleMessage里面調(diào)用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);??
????????????}??
????????});??
????????//?設置選擇文件夾的回調(diào)??
????????mListImageDirPopupWindow.setOnImageDirSelected(this);??
????}??
我們初始化我們的popupWindow,設置了關閉對話框的回調(diào),已經(jīng)設置了選擇不同文件夾的回調(diào);
這里僅僅是初始化,下面看我們合適將其彈出的,其實整個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);??
????????????}??
????????});??
????}??
可以看到,我們?yōu)榈撞坎季衷O置點擊事件;設置popupWindow的彈出與消失的動畫;已經(jīng)讓Activity背景變暗變亮,通過改變Window alpha實現(xiàn)的。變亮在彈出框消息的監(jiān)聽里面~~
動畫的文件就不貼了,大家自己看源碼;
popupWindow彈出了,用戶此時可以選擇不同的文件夾,那么現(xiàn)在該看選擇后的回調(diào)的代碼了:
我們的Activity實現(xiàn)了該接口,直接看實現(xiàn)的方法:
[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;??
????????}??
????}));??
????/**?
?????*?可以看到文件夾的路徑和圖片的路徑分開保存,極大的減少了內(nèi)存的消耗;?
?????*/??
????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的適配器,以及底部的控件上的文件夾名稱,文件數(shù)量等等;
好了,到此結束;整篇由于篇幅原因沒有貼任何布局文件,大家自己通過源碼查看;
在此希望大家可以通過該案例,能夠去其糟粕,取其精華,學習其中值得借鑒的代碼風格,不要真的當作一個例子去學習~~
源碼點擊下載 ?
ps:請真機測試,反正我的模擬器掃描不到圖片~
ps:運行出現(xiàn)空指針的話,在getImages中添加判斷,if(parentFile.list()==null)continue , 切記~~~具體位置,上面有說;?
---------------------------------------------------------------------------------------------------------
我建了一個QQ群,方便大家交流。群號:55032675
----------------------------------------------------------------------------------------------------------
博主部分視頻已經(jīng)上線,如果你不喜歡枯燥的文本,請猛戳(初錄,期待您的支持):
1、高仿微信5.2.1主界面及消息提醒
2、高仿QQ5.0側滑
轉載于:https://my.oschina.net/u/1177694/blog/510120
總結
以上是生活随笔為你收集整理的Android 超高仿微信图片选择器 图片该这么加载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样用ABBYY FineReader中
- 下一篇: JBPM入门