1. 程式人生 > >UC瀏覽器主介面滑動摺疊效果 使用自定義behavior實現 難度五顆星*****

UC瀏覽器主介面滑動摺疊效果 使用自定義behavior實現 難度五顆星*****

RcycleView上的HeadScrollBehavior 思路:


1。讓recycleview居於頭部的下方
---方案:
重寫layoutDependsOn  讓當前recycleview去依賴頭部檢視
重寫onDependentViewChanged 獲取到依賴的頭部檢視的高度,給recycleview設定setTranslationY


2.處理頭部向上平移

在onNestedPreScroll 中 向上滑動是dy>0
float newTranslationY = dependency.getTranslationY() - dy;
//計算出最小平移的y距離
float minTranslationY = -(dependency.getHeight() - finalHeight);
if (newTranslationY > minTranslationY) {
dependency.setTranslationY(newTranslationY);
//在圖片摺疊的情況下,
// 1,不允許RecyclerView自身處理滾動
consumed[1] = dy;
// 2,只能和圖片一起向上平移
}


3.recycleview往上平移
onDependentViewChanged中
//讓RecyclerView在y方向上平移一段距離
child.setTranslationY(dependency.getHeight() + dependency.getTranslationY());


4.向下平移的處理
onNestedScroll方法中:
if (dyUnconsumed >= 0) {
return;
}
float newTranslationY = dependency.getTranslationY() - dyUnconsumed;
if (newTranslationY < 0) {
dependency.setTranslationY(newTranslationY);
}


5.處理圖片的縮放和漸變
onDependentViewChanged 中:


//計算圖片平移的百分比
float percent = Math.abs(dependency.getTranslationY() / (dependency.getHeight() - finalHeight));
//Log.i("test", "percent:" + percent);
//圖片的縮放和透明度處理
dependency.setScaleX(1 + percent);
dependency.setScaleY(1 + percent);
dependency.setAlpha(1 - percent);


6.手指快速滑動圖片的緩慢開啟和關閉
onNestedPreFling--快速滑翔
判斷速度,比如速度大於800 我們才認為是快速滑動了。
核心程式碼:
private boolean startExpandOrClose(float velocityY){
//獲取鬆開手瞬間,圖片已經平移的距離
float translationY = dependency.getTranslationY();
//圖片向上移動的最終Y座標位置-注意是負數
float upFinalTranslationY=-(dependency.getHeight()-finalHeight);
float downFinalTranslationY=0;
//定義boolean值確定是否是向閉合的狀態滾動
boolean isClose=false;
if(Math.abs(velocityY)<=800){
//判斷鬆開手時已經平移的位置和已經平移位置與向上平移位置的差值的絕對值進行比較
if(Math.abs(translationY) < Math.abs(translationY-upFinalTranslationY)){
isClose=false;
}else{
isClose=true;
}
}else{
//這裡代表快速滑動
if(velocityY>0){
//從鬆開手的瞬間位置自動滾動到完全閉合的位置
isClose=true;
}else{
//從鬆開手的瞬間位置自動滾動到完全展開的位置
isClose=false;
}
}
//確定滾動的目標點
float targetTranslationY=isClose?upFinalTranslationY:downFinalTranslationY;
int startY= (int) translationY;
int dy= (int) (targetTranslationY-translationY);
mScroller.startScroll(0,startY,0,dy);
handler.post(flingRunnable);
isScrolling=true;
return true;
}


private Handler handler=new Handler();


private Runnable flingRunnable=new Runnable() {
@Override
public void run() {
//Scroller滾動的原理:
//是一幀一幀向前滾動的,滾動的過程中,要不斷的計算是否滾動到目標,如果未滾動到,則繼續滾動
//判斷Scroller是否已經滾動到目標位置
//這個方法還可以判斷是否有下一個新的小目標點
if(mScroller.computeScrollOffset()){
//getCurrY:指獲取下一個新的位置
dependency.setTranslationY(mScroller.getCurrY());
handler.post(this);
}else{
isScrolling=false;
}
}
};


7.文字框的移動和背景色變化-HeadTextBeahvior

public class HeadTextBehavior extends CoordinatorLayout.Behavior<View> {


private final ArgbEvaluator argbEvaluator;


public HeadTextBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
argbEvaluator = new ArgbEvaluator();
initOffset = context.getResources().getDimension(R.dimen.initOffset);
collapsedOffset = context.getResources().getDimension(R.dimen.collapsedOffset);
finalHeight = (int) context.getResources().getDimension(R.dimen.finalHeight);
initMargin = (int) context.getResources().getDimension(R.dimen.initMargin);
finalMargin = (int) context.getResources().getDimension(R.dimen.finalMargin);
}


@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
if (dependency.getId() == R.id.iv_head) {
return true;
}
return super.layoutDependsOn(parent, child, dependency);
}


private float initOffset = 130;
private float collapsedOffset = 5;
private int finalHeight = 50;
private int initMargin=20;
private int finalMargin=5;


@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
//處理隨著圖片向上移動,當前控制元件也向上移動
float percent = Math.abs(dependency.getTranslationY() / (dependency.getHeight() - finalHeight));
//Log.i("test","percent:"+percent);
float translationY = collapsedOffset + (initOffset - collapsedOffset) * (1-percent);
child.setTranslationY(translationY);
int color= (int) argbEvaluator.evaluate(percent, Color.RED,Color.GREEN);
child.setBackgroundColor(color);
int margin= (int) (finalMargin+(initMargin-finalMargin)*(1-percent));
CoordinatorLayout.LayoutParams params= (CoordinatorLayout.LayoutParams) child.getLayoutParams();
params.setMargins(margin,0,margin,0);
child.setLayoutParams(params);
return true;
}
}


UC案例思路:
findFirstDependency:決定了你的頭部檢視是誰!
預設的是:
    @Override
        View findFirstDependency(List<View> views) {
            for (int i = 0, z = views.size(); i < z; i++) {
                View view = views.get(i);
                if (view instanceof AppBarLayout) {
                    return view;
                }
            }
            return null;
        }


getScrollRange(View v):決定你的頭部檢視滾動的範圍 !


決定了我們必須要去繼承 HeaderScrollingViewBehavior 但是由於這個類是包級的 所以需要去拷貝原始碼