Android開源-ZoomHeader:神交互,模仿餓了么詳情頁
zoomheaderview
先吐槽下餓了么。不提示左右可以滑動。我還是無意中發現的。不提示我怎么知道可以滑動??
這是一個模仿餓了么詳情頁的例子。 并非一個庫,并非拿來就可以用,主要講解思路以及如何實現,可能有一些細節沒有處理。 講述了如何實現。具體祥見源碼。
他是一個Activity還是兩個?
相信你肯定有這樣的疑問,答案是一個。所以這 不是 用共享元素實現的,使用共享元素會導致圖片無法跟隨手指移動。
你看到的中間imageview是viewpager。在Viewpager上面是一個透明的View。當然,這個Activity的背景也是透明的。
實現思路
我使用CoordinatorLayout+Behavior實現的。說實話,Behavior真心強大。。
viewpager+頭部
整個實現的思路是這樣的。整體布局從上到下依次是:
- 透明View
- viewpager
- RecyclerView
其中透明View和Viewpager 合并成一個自定義的Header。當這個Header上移的時候,圖片放大,并且RecyclerView聯動上衣,從透明轉向并且不透明。
所以首先要定制一個透明的可移動的HeaderView。
在onTouchEvent處理一下手勢。。
@Override public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_MOVE:
if(上下移動到閥值){
展開為詳情()
}else if(上下滑動到閥值,恢復viewpager){
}else if(下滑,則關閉Activity)
將header分為三種狀態:
- 上移。則展開為詳情頁。
- 下移,則恢復為viewpager。
- 再下移,則finish Activity。
在上移的過程中,遇到了一點小挑戰,這里分享下:
上移的過程中,圖片需要放大。但是在做的過程中,不能使用LayoutParams實現。這里就關系到一些動畫的小細節。
動畫使用LayoutParams實現是一個禁忌。他會導致不停requestLayout,從而影響UI性能。
所以這里我的一個解法就是,我放大圖片,不是真正的改變ImageView大小,而是去Scale圖片。即使看起來變大了,他的View真正大小也不會變。
所以,有一句話叫做 真亦是假、假亦是真 真真假假,你又何必當真呢?動畫效果只要遵循這句話,基本上都是可以實現的。你所看到的效果都是假的。都是障眼法。View變大不是真正的變大。View懸浮不是真正的懸浮(有可能是顯隱)。就像變魔術一樣。。其實很簡單。
接下來又遇到問題了。圖片放大了,文字如何對齊? 文字的位置當然也不能真正改變。所以這里使用TranslationX實現。在圖片放大的過程中,使用scale的系數,與兩個端點值進行一個線性變化計算。主要文字對齊代碼如下:
bottom.offsetLeftAndRight(
(int) (target.getWidth() / 2 - target.getWidth() * (1 + progress) / 2
+ MarginConfig.MARGIN_LEFT_RIGHT - bottom.getX()));</code></pre>
第二個點。就是在圖片放大過程中,底部文字和按鈕左右padding不能變。這也是我沒有封裝成一個拿來就用的View的原因(其實還是水平不夠)。因為這些空間需要全部按照上方的方法進行動態計算。。所以也是比較坑爹的。。
ViewPager
拿了網上一個畫廊的效果。直接
setPageTransformer(true, new ZoomOutPageTransformer());
這里注意,需要改變一下view的繪制順序,保證當前view是最后繪制處于最上層
/改變系統繪制順序
@Override protected int getChildDrawingOrder(int childCount, int i) {
int position = getCurrentItem();
if(position<0){
return i;
}else{
if(i == childCount - 1){//這是最后一個需要刷新的item
if(position>i){
position=i;
}
return position;
}
if(i == position){//這是原本要在最后一個刷新的item
return childCount - 1;
}
}
return i;
}
}
RecyclerView
RecyclerView最開始是完全透明的。并且跟隨HeaderView上移而上移,在上移的過程中漸漸顯示出來。 需要監聽RecyclerView滾動,當RecyclerView滾動到頂部的時候。告知Header,該恢復最初原樣了。
@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target,
float velocityX, float velocityY, boolean consumed) {
//向下Fling并且到頂部
if (velocityY < 0 && ((RecyclerView) target).getChildAt(0).getY() == 0) {
mDependency.restore(mDependency.getY());
}
return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target,
int dx, int dy, int[] consumed) {
//如果在頂部
if (((RecyclerView) target).getChildAt(0).getY() == 0) {
//向下滑動
if (dy < 0) {
mDependency.setY(mDependency.getY() - dy);
//小于閥值
if (mDependency.getY() < 500) {
mDependency.restore(mDependency.getY());
}
}
}
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
}
}
Behavior
讓header和RecyclerView關聯起來的就是Behavior了。Behavior之前寫過幾篇介紹過了,這里就不再啰嗦。
denpendcy為HeaderView。并且監聽RecyclerView的滑動。
具體的細節還是看源碼吧~
如果你覺得還不錯,歡迎Star
歡迎加入我的qq群: 425983695
License
Copyright 2016 androidwing1992
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.