Android仿朋友圈照片定点放大和滑动查看(未完待续)
??? 最近公司的項目中有一個圖片加載和查看功能實現,具體是說通過列表項加載小圖片,點擊放大圖片并且可以左右翻頁,放縮等等,類似于微信朋友圈的照片墻功能。拿到這個需求后我想了想,圖片列表首選當然是RecyclerView啦,線性布局,網格布局,瀑布流布局應有盡有,針對這個需求當然是網格布局咯。網絡加載圖片庫那就多啦,從最初的Universal ImageLoader,到如今的Picasso,Fresco,Glide等等,都是很優秀的圖片加載框架。作為一個喜歡回憶,有著一絲絲文藝風的程序猿(),我還是選擇了經典卻又不失美感的Universal ImageLoader。好了,第一個頁面(列表展示頁)的構建思路有了,那么,點擊小圖放大后的頁面用什么實現呢?dialog?還是Activity?果斷Activity啦,畢竟圖片查看頁面要做的事情很多,Activity更能滿足我們的需求,下面,怎么翻頁查看?果斷ViewPager,多么好用的工具。圖片手勢縮放用什么?photoView唄,GitHub那么高的star,咱們先用著再說。好了,工具選好了,下面就是怎么實現代碼了,讓我們一步一步來。
?? 步驟一:MainActivity
?? MainActivity就是我們用來展示圖片列表頁的Activity了,布局文件只有一個RecyclerView,不再贅述。
?? 1.1 初始化universal ImageLoader
?? 這里把imageLoader的初始化放在了Application當中,沒啥可說的,如圖所示
? 1.2初始化view和數據
?????
?? 其中,定義網格布局的時候我們設置了子項之間的間距,繼承了ItemDecoration類,子類實現如下所示:
?
注釋應該已經很清楚了,除了每行第一個,其他子項的左邊和下邊都留出間距。
?? 1.3 RecyclerView adapter
?? 適配器里面沒啥好說的,我們在方法中控制子項的寬高幾乎相等
通過獲取imageView的param設置寬高就行。
?? 1.4 子項點擊事件的處理
?? 到這里,圖片列表頁的實現也沒啥要特別說明的地方。展示效果如圖所示
現在,關鍵點來了,不知道大家有沒有注意看過,朋友圈里的照片,點擊哪張照片就從哪張照片處放大,關閉大圖后又會縮小到當前的小圖。這里有兩個關鍵點:
1.點擊哪張小圖,放大效果就從點擊的小圖處放大;
2.放大后關閉大圖,就會從當前大圖縮小至對應的小圖。
比如,我點擊第1張小圖,放大效果從第1張小圖處放大,此時我左滑翻頁到第3張大圖,關閉大圖后縮小效果會縮小至第3張小圖處。因此,很明顯的情況是,當點擊事件發生的時候我們不僅需要記錄所點擊的小圖的中心點坐標,此外還需記錄其他所有小圖的中心坐標,因為我在大圖中可以隨便左右翻頁,翻到哪張大圖就要縮小到對應的小圖。因此,我們的思路很清晰了,就是要記錄所有小圖的坐標。因此,我們就會這樣寫:
for(int i=0;i<rv.getChildCount();i++)
{
?? View view=rv.getChildAt(i);//獲取所有子項View
?? int xy[]=new int[2];
?? view.getLocationOnScreen(xy);//獲取子項左上角在屏幕中的坐標
?? float[] xyf=new float[]{xy[0]*1.0f+view1.getWidth()/2,xy[1]*1.0f+view1.getHeight()/2};//獲取子項View的中心點坐標
?? xyMap.put(i, xyf);//加入到坐標集合中
}
?? 乍看起來似乎沒啥問題,運行也沒問題,但是運行后發現圖片數量少了,哪去了?因為這里的getChildCount只包含當前手機頁面可見的子項個數,并不是所有子項的個數,比如我總共有25張小圖片,當前頁面可見小圖是15張,那么getChildCount就是15,那么我們換成rv.getAdapter.getItemCount()就行了,確實此時返回的是所有子項的個數。但是此時又帶來一個新的問題,不可見的子項哪有坐標哦?是的,不可見的子項在屏幕中確實沒有坐標。大家再看朋友圈,找一條包含4張以上照片的朋友狀態,接著上下滑動頁面,使得當前手機屏幕隱藏掉部分小圖,比如就像下面這樣:
例如,我的某個朋友狀態中有9張圖,我現在使得第3行的圖不可見,此時我點擊第1張放大查看,接著在大圖中左滑到最后一張,再點擊大圖縮小,你會發現最后一張大圖縮小到了九宮格的右下角(即橫坐標屬于第3列,縱坐標屬于手機屏幕下邊界)。再來一遍,點擊大圖滑動到第8張圖,點擊縮小,縮小效果到了中間的下邊界(即橫坐標屬于第2列,縱坐標屬于手機屏幕下邊界)。同理,隱藏第1行圖片,從最后一張點擊放大,滑動到第一張大圖后縮小,會縮小至第1列,手機屏幕上邊界。此時我們明白了,朋友圈中對于不可見的子項圖片,保留了其所在列的信息,縮小至上邊界或者下邊界。因此,我們代碼可以這樣寫:
?? 代碼中注釋很清楚,首先獲取可見的第一個子項,獲取它的position,position數值代表的就是在所有子項中的索引,如果position0>0,說明當前頁面隱藏了前面的部分圖片,因此for循環將0~position0的之間的不可見的子項根據列的信息賦值坐標,即列信息和上邊界。同理,第2個for循環判斷對于position=-1的(即不可見子項)賦值列信息和下邊界,循環完畢,所有子項坐標信息獲取完成。
?? 1.5 點擊放大效果
?? MainActivity完成了,坐標也有了,怎樣點擊放大呢?在XML中定義動畫肯定不行,因為XML中的動畫中心是寫死的,我們這是活的。我們知道,Activity中包含了View樹結構,根View包含子View等等,因此我們的思路很簡單,使SecondActivity保持透明狀態,根View(即Layout)設置成黑色背景,將ScaleAnimation放大動畫作用于根View中,呈現的效果應該就是我們想要的。如下是設置Activity透明:
前提我們需要先禁用Activity自帶的切換動畫,即
overridePendingTransition(0,0);
因此,我們重寫startActivity方法,如下所示:
為什么要這樣寫,因為Activity的API中說了啊,overridePendingTransition方法在startActivity或者finish方法后立即調用,如下:
至此,MainActivity完成。
步驟二:SecondActivity
?? SecondActivity就是我們查看大圖的Activity啦。
2.1 放大效果
根據MainActivity傳來的所有子項的坐標以及當前點擊的子項position,我們這樣實現動畫
先得到當前position的坐標,動畫作用于最外層的LinearLayout,大小從0到1,動畫加載完成后初始化數據,代碼注釋很清楚。另外,這個Activity設置成全屏顯示哦,不再贅述。
2.2 加載數據
根據傳來的URL集合,我們網絡加載大圖到photoView,圖片設置為等比例縮放居中顯示,大圖中可以雙擊放縮或者手勢放縮,單擊圖片退出大圖模式。
2.3 大圖左右滑動
ViewPager有個滑動監聽,在里面更新當前的縮放中心點和當前是第幾張圖片。
2.4 重寫finish方法
上一節說道,overridePendingTransition方法也會立即調用在finish方法后,因此我們也要禁用Activity默認的退出動畫,再設置我們的縮小動畫,如下:
其中,有個注意點,大圖頁面是全屏,小圖頁面非全屏,從全屏退到非全屏頁面會產生抖動現象,因此退出前設置成非全屏模式。其他代碼注釋很清楚,無需贅述。
效果圖如下所示:
至此,全部代碼完成。其實,本代碼只是一種實現思路,大家可能有更好的更優化的思路,比如View預渲染等等,本人在這里只是提供了一種簡易的實現方法,側重于細節的實現以及各方面的注意點,后續還有很多優化的空間。因此,希望大家踴躍評論,有不當之處及時指出,技術就是不斷討論才會不斷進步,謝謝大家,未完待續~
完整源碼下載地址,我的GitHub:https://github.com/HarrisonChe/ImageObserverDemo
總結
以上是生活随笔為你收集整理的Android仿朋友圈照片定点放大和滑动查看(未完待续)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]熊绎:我看软件工程师的职业规划
- 下一篇: android adapter 组件,A