先看一张效果图:
先分析一些源码:
CoorDinatorLayout:
public class CoordinatorLayout extends ViewGroup implements NestedScrollingParent
NestedScrollingParent:
/**
* 引用此接口的条件:
* 1.继承ViewGroup或ViewGroup子类
* 2.子View中包含可以滚动的ChildView(例如:RecyclerView)
*/
public interface NestedScrollingParent {
/**
* 列表滚动时首先调用
* nestedScrollAxes用来判断滑动方向:SCROLL_AXIS_HORIZONTAL, SCROLL_AXIS_VERTICAL, SCROLL_AXIS_NONE
* @param child
* @param target
* @param nestedScrollAxes
* @return
*/
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes);
/**
* onStartNestedScroll之后调用
* @param child
* @param target
* @param nestedScrollAxes
*/
public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes);
/**
* 滚动停止调用
* @param target
*/
public void onStopNestedScroll(View target);
/**
* 滚动之前调用,一般用此方法来消耗滚动
* consumed[0]用来消耗x方法, consumed[1]用来消耗y方法.
* 如果dy或dy未被完全消耗,则传递给剩余部分给滚动View自行处理
* @param target
* @param dx
* @param dy
* @param consumed
*/
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed);
/**
*滚动中
* @param target
* @param dxConsumed
* @param dyConsumed
* @param dxUnconsumed
* @param dyUnconsumed
*/
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed);
/**
* 快速滑动前调用
* @param target
* @param velocityX
* @param velocityY
* @return
*/
public boolean onNestedPreFling(View target, float velocityX, float velocityY);
/**
* onNestedPreFling之后调用
* @param target
* @param velocityX
* @param velocityY
* @param consumed
* @return
*/
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed);
/**
* 获取当前滚动方向
* @return
*/
public int getNestedScrollAxes();
}
缓慢滑动:
08-23 10:57:13.479 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onStartNestedScroll:
08-23 10:57:13.479 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedScrollAccepted:
08-23 10:57:13.596 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.614 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.631 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.646 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.662 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.678 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.695 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.712 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.728 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.744 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.760 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.777 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.794 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.810 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.827 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.843 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.861 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.877 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.893 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:13.921 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreFling:
08-23 10:57:13.921 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedFling:
08-23 10:57:13.923 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onStopNestedScroll:
快速滑动:
08-23 10:57:56.599 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onStartNestedScroll:
08-23 10:57:56.599 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedScrollAccepted:
08-23 10:57:56.690 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:56.708 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:56.723 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:56.740 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:56.743 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedScroll:
08-23 10:57:56.757 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:56.758 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedScroll:
08-23 10:57:56.774 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreScroll:
08-23 10:57:56.776 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedScroll:
08-23 10:57:56.776 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedPreFling:
08-23 10:57:56.776 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onNestedFling:
08-23 10:57:56.778 22139-22139/com.test.git.coordinatorlayout I/ViewParent: onStopNestedScroll:
下面上Demo源码:
ViewParent:
package com.test.git.coordinatorlayout.Behavior;
import android.content.Context;
import android.support.v4.view.NestedScrollingParent;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.OverScroller;
/**
* Created by lk on 16/8/22.
*/
public class ViewParent extends FrameLayout implements NestedScrollingParent {
private final OverScroller mScroller;
private int mHeaderHeight;
private View viewHeader;
private RecyclerView mRecyclerView;
private static final String TAG = "ViewParent";
public ViewParent(Context context) {
this(context, null);
}
public ViewParent(Context context, AttributeSet attrs) {
super(context, attrs);
mScroller = new OverScroller(context);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
for(int i = 0; i < getChildCount(); i ++) {
if(i == 0) {
viewHeader = getChildAt(0);
}else {
View vchild = getChildAt(i);
if(vchild instanceof RecyclerView){
mRecyclerView = (RecyclerView)vchild;
}
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//测量分割栏的高度
getChildAt(1).measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
ViewGroup.LayoutParams params = mRecyclerView.getLayoutParams();
//设置滚动列表高度
params.height = getMeasuredHeight() - getChildAt(1).getMeasuredHeight();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//获取头部高度
mHeaderHeight = viewHeader.getMeasuredHeight();
}
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
Log.i(TAG, "onStartNestedScroll: ");
//判断是否纵向滑动
return (nestedScrollAxes & SCROLL_AXIS_VERTICAL) != 0;
}
@Override
public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
Log.i(TAG, "onNestedScrollAccepted: ");
}
@Override
public void onStopNestedScroll(View target) {
Log.i(TAG, "onStopNestedScroll: ");
}
@Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
Log.i(TAG, "onNestedScroll: ");
}
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
Log.i(TAG, "onNestedPreScroll: ");
//dy > 0 向上滑动 getScrollY() < mHeaderHeight 头部未完全隐藏
boolean hide = dy > 0 && getScrollY() < mHeaderHeight;
//dy < 0 向下滑动 getScrollY() >= 0 头部未完全显示
//ViewCompat.canScrollVertically(target, -1) -1 表示scrolling up, 如果target可以向上滑动返回true, 否则返回false.
boolean show = dy < 0 && getScrollY() >= 0 && !ViewCompat.canScrollVertically(target, -1);
if (show) {//显示
if(getScrollY() + dy < 0){
int sy = - getScrollY();
scrollBy(0, sy);
consumed[1] = sy;
}else {
scrollBy(0, dy);
consumed[1] = dy;
}
}
if(hide){//隐藏
if(dy + getScrollY() > mHeaderHeight){
int sy = mHeaderHeight - getScrollY();
scrollBy(0, sy);
consumed[1] = sy;
}else {
scrollBy(0, dy);
consumed[1] = dy;
}
}
}
@Override
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
Log.i(TAG, "onNestedFling: ");
return false;
}
@Override
public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
Log.i(TAG, "onNestedPreFling: ");
Log.i(TAG, "onNestedFling: ");
//头部隐藏,则交给滚动列表处理
if(getScrollY() >= mHeaderHeight) {
return false;
}
//滚动
mScroller.fling(0, getScrollY(), 0, (int) velocityY, 0, 0, 0, mHeaderHeight);
invalidate();
return true;
}
@Override
public int getNestedScrollAxes() {
Log.i(TAG, "getNestedScrollAxes: ");
return 0;
}
float a = 0.5f;//视差因子
@Override
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
if(y >= 0 && y <= mHeaderHeight){
viewHeader.scrollTo(0, (int) (- y * a));
}
}
@Override
public void computeScroll() {
if(mScroller.computeScrollOffset()){
scrollTo(0, mScroller.getCurrY());
invalidate();
}
}
}
xml:
<?xml version="1.0" encoding="utf-8"?>
<com.test.git.coordinatorlayout.Behavior.ViewParent xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Activity.MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@mipmap/ic_launcher"
/>
</FrameLayout>
<Button
android:id="@+id/bt_click"
android:textSize="15dp"
android:text="分割线"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginTop="200dp"
android:layout_gravity="center_horizontal"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/mRecyclerView"
android:layout_marginTop="250dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</com.test.git.coordinatorlayout.Behavior.ViewParent>
相关文章: 点击打开链接 点击打开链接
源码:点击打开链接