项目中需要一个类似网易考拉海购的搜索界面的滑动效果,于是网上看了鸿洋大神的文章,在他的基础上做了一下修改实现了想要的效果,第一次使用了NestedScrolling的嵌套滑动,顺便做个简单的NestedScrolling使用记录。原贴:http://blog.csdn.net/lmj623565791/article/details/52204039
NestedScrolling主要的4个类
NestedScrollingChild
NestedScrollingChildHelper
NestedScrollingParent
NestedScrollingParentHelper
NestedScrolling事件传递机制:
1.onStartNestedScroll方法表示parent能否接收child的滑动参数,一般return true。
2.onNestedPreScroll方法首先接收到滚动事件dx、dy(x、y方向滑动的距离),int[] consumed 存放parent要消耗掉的child的dx和dy,如设置consumed[0] = 0 , consumed[1] = 0 表示parent不消耗child的dx、dy。
3.onNestedPreFling方法返回parent是否要拦截掉child的惯性滑动。
具体实现
布局:
<com.zhy.stickynavlayout.view.StickyNavLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/view_top_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_purple">
<TextView
android:layout_width="match_parent"
android:layout_height="180dp"
android:gravity="center"
android:text="header view"
android:textSize="30sp"
android:textColor="@android:color/white"
android:textStyle="bold"/>
</RelativeLayout>
<LinearLayout
android:id="@+id/view_sticky_view"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@android:color/holo_red_light"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="sticky view"
android:textSize="20sp"
android:textColor="@android:color/white"
android:textStyle="bold"/>
</LinearLayout>
<com.zhy.stickynavlayout.view.NestedListView
android:id="@+id/view_content_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</com.zhy.stickynavlayout.view.NestedListView>
</com.zhy.stickynavlayout.view.StickyNavLayout>
StickyNavLayout:
public class StickyNavLayout extends LinearLayout implements NestedScrollingParent {
private static final String TAG = "StickyNavLayout";
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
Log.e(TAG, "onStartNestedScroll");
return true;
}
@Override
public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
Log.e(TAG, "onNestedScrollAccepted");
}
@Override
public void onStopNestedScroll(View target) {
Log.e(TAG, "onStopNestedScroll");
}
@Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
Log.e(TAG, "onNestedScroll");
}
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
Log.e(TAG, "onNestedPreScroll" + " dy:" + dy + " scrollY:" + getScrollY() + " mTopViewHeight:" + mTopViewHeight);
if (getScrollY() > 0 && getScrollY() < mTopViewHeight) {
scrollBy(0, dy);
consumed[1] = dy;
} else if (getScrollY() == mTopViewHeight) {
if (dy < 0) {
scrollBy(0, dy);
consumed[1] = dy;
}
} else if (getScrollY() == 0 && dy > 0) {
scrollBy(0, dy);
consumed[1] = dy;
} else if (getScrollY() == 0 && dy < 0) {
onStopNestedScroll(target);
}
}
@Override
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
Log.e(TAG, "onNestedFling");
return false;
}
@Override
public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
Log.e(TAG, "onNestedPreFling");
//down - //up+
if (getScrollY() >= mTopViewHeight) return false;
if (getScrollY() == 0) return false;
fling((int) velocityY);
return true;
}
@Override
public int getNestedScrollAxes() {
Log.e(TAG, "getNestedScrollAxes");
return 0;
}
private View mTop;
private View mNav;
private NestedListView mViewPager;
private int mTopViewHeight;
private OverScroller mScroller;
public StickyNavLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.VERTICAL);
mScroller = new OverScroller(context);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mTop = findViewById(R.id.view_top_view);
mNav = findViewById(R.id.view_sticky_view);
mViewPager = (NestedListView) findViewById(R.id.view_content_view);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//不限制顶部的高度
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
getChildAt(0).measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
ViewGroup.LayoutParams params = mViewPager.getLayoutParams();
params.height = getMeasuredHeight() - mNav.getMeasuredHeight();
setMeasuredDimension(getMeasuredWidth(), mTop.getMeasuredHeight() + mNav.getMeasuredHeight() + mViewPager.getMeasuredHeight());
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mTopViewHeight = mTop.getMeasuredHeight();
}
public void fling(int velocityY) {
mScroller.fling(0, getScrollY(), 0, velocityY, 0, 0, 0, mTopViewHeight);
invalidate();
}
@Override
public void scrollTo(int x, int y) {
if (y < 0) {
y = 0;
}
if (y > mTopViewHeight) {
y = mTopViewHeight;
}
if (y != getScrollY()) {
super.scrollTo(x, y);
}
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(0, mScroller.getCurrY());
invalidate();
}
}
}
NestedListView:
public class NestedListView extends ListView implements NestedScrollingChild{
private NestedScrollingChildHelper mChildHelper;
public NestedListView(Context context) {
super(context);
init();
}
public NestedListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public NestedListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
mChildHelper = new NestedScrollingChildHelper(this);
setNestedScrollingEnabled(true);
}
@Override
public void setNestedScrollingEnabled(boolean enabled) {
super.setNestedScrollingEnabled(enabled);
mChildHelper.setNestedScrollingEnabled(enabled);
}
@Override
public boolean isNestedScrollingEnabled() {
return mChildHelper.isNestedScrollingEnabled();
}
@Override
public boolean startNestedScroll(int axes) {
return mChildHelper.startNestedScroll(axes);
}
@Override
public void stopNestedScroll() {
mChildHelper.stopNestedScroll();
}
@Override
public boolean hasNestedScrollingParent() {
return mChildHelper.hasNestedScrollingParent();
}
@Override
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
}
@Override
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
}
@Override
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
}
@Override
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
}
}