Android嵌套滚动的传统方法与思路
前言
Android 的嵌套滚动,实现比较方便
- 横着滚动,ViewPager2
- 竖着滚动,NestedScrollingParent
顶上,有一个头部视图 header,
中间,有一个菜单视图 menu,
下面的是,内容视图, 一个 ViewPager2,包含几个 Tab,
Tab 里面是列表 RecyclerView
本文,主要参考 hongyangAndroid/Android-StickyNavLayout
Java 实现
基于 LinearLayout ,添加 NestedScrollingParent
子 View 开始滚动时,请求父 View 是否开始接受嵌套滚动,
SCROLL_AXIS_HORIZONTAL = 1
SCROLL_AXIS_VERTICAL = 2
水平方向,返回 false, 表示不接受;
( 不接受,则水平滚动,对竖直方向的滚动,没有干涉 )
竖直方向,返回 true, 表示接受。
public class StickyNavLayout extends LinearLayout implements NestedScrollingParent { @Override public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { if (nestedScrollAxes == 1){ return false; } else{ return true; } } }
返回嵌套滚动的方向
@Override public int getNestedScrollAxes() { return ViewCompat.SCROLL_AXIS_VERTICAL; }
子视图纵向滚动,带动父视图的纵向滚动
目标视图执行嵌套滚动前的回调,
dx,dy 为产生的滚动距离,( 目标视图,就是拖动的子视图, RecyclerView )
( 纵向滚动, dx 为 0 )
consumed 为父 View 消耗的滚动距离
@Override public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { // 根据子视图的滚动偏移 dy // 和父视图的滚动偏移 getScrollY() // 确定子视图纵向滚动,带动父视图的纵向滚动 boolean hiddenTop = dy > 0 && getScrollY() < mTopViewHeight; boolean showTop = dy < 0 && getScrollY() >= 0 && !target.canScrollVertically(-1); if (hiddenTop || showTop) { scrollBy(0, dy); consumed[1] = dy; } }
效果增强, 动画
往上轻滚,就把 header 遮盖;
往下轻滚,就显示 header
private int TOP_CHILD_FLING_THRESHOLD = 3; @Override public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { //如果是 recyclerView 根据判断第一个元素是哪个位置,可以判断是否消耗 //这里判断,如果第一个元素的位置是大于 TOP_CHILD_FLING_THRESHOLD 的 //认为已经被消耗,在 animateScroll 里不会对 velocityY<0 时做处理 if (target instanceof RecyclerView && velocityY < 0) { // 对子视图为 RecyclerView, 专门处理 final RecyclerView recyclerView = (RecyclerView) target; final View firstChild = recyclerView.getChildAt(0); final int childAdapterPosition = recyclerView.getChildAdapterPosition(firstChild); consumed = childAdapterPosition > TOP_CHILD_FLING_THRESHOLD; } // 动效 animateScroll(velocityY, 700, consumed); return true; }
动画滚动
使用 ValueAnimator ,做滚动动画
private ValueAnimator mOffsetAnimator; private void animateScroll(float velocityY, final int duration,boolean consumed) { final int currentOffset = getScrollY(); final int topHeight = mTop.getHeight(); if (mOffsetAnimator == null) { // 之前不存在动画,就新建 mOffsetAnimator = new ValueAnimator(); mOffsetAnimator.setInterpolator(mInterpolator); mOffsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { if (animation.getAnimatedValue() instanceof Integer) { scrollTo(0, (Integer) animation.getAnimatedValue()); } } }); } else { // 之前存在动画,就取消 mOffsetAnimator.cancel(); } mOffsetAnimator.setDuration(Math.min(duration, 600)); if (velocityY >= 0) { // 向上滚动 // 隐藏 header mOffsetAnimator.setIntValues(currentOffset, topHeight); mOffsetAnimator.start(); }else if( !consumed ){ // 向下滚动 // 显示 header // 如果子 View 没有消耗 down 事件 那么就让自身滑到 0 位置 mOffsetAnimator.setIntValues(currentOffset, 0); mOffsetAnimator.start(); } }
总结
到此这篇关于Android嵌套滚动的传统方法与思路的文章就介绍到这了,更多相关Android嵌套滚动内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Android实现自定义Crash handler记录崩溃信息实例代码
这篇文章主要给大家介绍了Android实现自定义Crash handler记录崩溃信息的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。2018-02-02Android中解决RecyclerView各种点击事件的方法
这篇文章主要介绍了Android中解决RecyclerView各种点击事件的方法,完美解决RecyclerView点击事件、长按事件、子项点击事件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2018-05-05Android studio中生成引用.aar和.jar的方法详解
这篇文章主要是讲解.aar的生成与引用,文中的内容属于完全基础性概念,对刚学习使用Android studio的朋友们很有帮助,有需要的可以参考学习,下面来一起看看吧。2016-09-09解析:android 如何从JPEG生成BufferedImage
本篇文章是对在android中,如何从JPEG生成BufferedImage的解决方法进行了详细的分析介绍,需要的朋友参考下2013-06-06
最新评论