项目

Conflict_project

图片实例

解决几个冲突

  1. 上面RecyclerView的高度扩宽
  2. 头部和下面ViewPager的同时滑动
  3. 头部隐藏后,ViewPager中RecyclerView继续滑动

解决步骤

1. 扩宽头部RecyclerView

布局加入这个,自适应高度

android:layout_width="match_parent"android:layout_height="wrap_content" 

2. 解决冲突

public class NestedScrollLayout extends NestedScrollView {    private View topView; //头部的View    private ViewGroup contentView; // ViewPager中的ReyclerView    private static final String TAG = "NestedScrollLayout"; //TAG    public NestedScrollLayout(Context context) {        this(context, null);        init();    }    public NestedScrollLayout(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);        init();    }    public NestedScrollLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        this(context, attrs, defStyleAttr, 0);        init();    }    public NestedScrollLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr);        init();    }    private FlingHelper mFlingHelper; // veltociy和distance的转换    int totalDy = 0;    /**     * 用于判断RecyclerView是否在fling     */    boolean isStartFling = false;    /**     * 记录当前滑动的y轴加速度     */    private int velocityY = 0;    private void init() {        mFlingHelper = new FlingHelper(getContext());        setOnScrollChangeListener(new View.OnScrollChangeListener() { //监听自己(NestedScrollView)滑动            @Override            public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {                if (isStartFling) {                    totalDy = 0;                    isStartFling = false;                }                if (scrollY == 0) { // 到达顶部的时候                    Log.i(TAG, "TOP SCROLL");                   // refreshLayout.setEnabled(true);                }                // topView完全消失了,该子View处理了                if (scrollY == (getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight())) {                    Log.i(TAG, "BOTTOM SCROLL");                    dispatchChildFling();                }                //在RecyclerView fling情况下,记录当前RecyclerView在y轴的偏移                totalDy += scrollY - oldScrollY;            }        });    }    private void dispatchChildFling() {        if (velocityY != 0) { // 滑动的速度,和distance可以相互转换            // 转换成距离            Double splineFlingDistance = mFlingHelper.getSplineFlingDistance(velocityY);            if (splineFlingDistance > totalDy) {                // 转换成velocityY                childFling(mFlingHelper.getVelocityByDistance(splineFlingDistance - Double.valueOf(totalDy)));            }        }        // 处理完之后,恢复默认值        totalDy = 0;        velocityY = 0;    }    private void childFling(int velY) {        RecyclerView childRecyclerView = getChildRecyclerView(contentView); // 找到子View(RecyclerView)        if (childRecyclerView != null) {            childRecyclerView.fling(0, velY); //fling事件传出去        }    }    @Override    public void fling(int velocityY) { // 自己的fling        super.fling(velocityY);        if (velocityY <= 0) {            this.velocityY = 0;        } else {            isStartFling = true; //开始fling滑动            this.velocityY = velocityY; //滑动的速度        }    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        //顶部的View        topView = ((ViewGroup) getChildAt(0)).getChildAt(0);        //下面的RecyclerView,        contentView = (ViewGroup) ((ViewGroup) getChildAt(0)).getChildAt(1);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        // 调整contentView的高度为父容器高度,使之填充布局,避免父容器滚动后出现空白        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        ViewGroup.LayoutParams lp = contentView.getLayoutParams();        lp.height = getMeasuredHeight(); //测量的是整个父View的高度        contentView.setLayoutParams(lp);    }    @Override    public void onNestedPreScroll(@NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) {        Log.i("NestedScrollLayout", getScrollY()+"::onNestedPreScroll::"+topView.getMeasuredHeight());        // 向上滑动。若当前topview可见,需要将topview滑动至不可见        boolean hideTop = dy > 0 && getScrollY() < topView.getMeasuredHeight();        if (hideTop) {            scrollBy(0, dy); //相对滑动了多少位置            consumed[1] = dy; // 消费掉y轴的滑动事件        }    }    private RecyclerView getChildRecyclerView(ViewGroup viewGroup) {        for (int i = 0; i < viewGroup.getChildCount(); i++) {            View view = viewGroup.getChildAt(i);            if (view instanceof RecyclerView && view.getClass() == NestedLogRecyclerView.class) {                return (RecyclerView) viewGroup.getChildAt(i);            } else if (viewGroup.getChildAt(i) instanceof ViewGroup) {                ViewGroup childRecyclerView = getChildRecyclerView((ViewGroup) viewGroup.getChildAt(i));                if (childRecyclerView instanceof RecyclerView) {                    return (RecyclerView) childRecyclerView;                }            }            continue;        }        return null;    }}

工具类

FlingHelper

public class FlingHelper {    private static float DECELERATION_RATE = ((float) (Math.log(0.78d) / Math.log(0.9d)));    private static float mFlingFriction = ViewConfiguration.getScrollFriction();    private static float mPhysicalCoeff;    public FlingHelper(Context context) {        mPhysicalCoeff = context.getResources().getDisplayMetrics().density * 160.0f * 386.0878f * 0.84f;    }    private double getSplineDeceleration(int i) {        return Math.log((double) ((0.35f * ((float) Math.abs(i))) / (mFlingFriction * mPhysicalCoeff)));    }    private double getSplineDecelerationByDistance(double d) {        return ((((double) DECELERATION_RATE) - 1.0d) * Math.log(d / ((double) (mFlingFriction * mPhysicalCoeff)))) / ((double) DECELERATION_RATE);    }    public double getSplineFlingDistance(int i) {        return Math.exp(getSplineDeceleration(i) * (((double) DECELERATION_RATE) / (((double) DECELERATION_RATE) - 1.0d))) * ((double) (mFlingFriction * mPhysicalCoeff));    }    public int getVelocityByDistance(double d) {        return Math.abs((int) (((Math.exp(getSplineDecelerationByDistance(d)) * ((double) mFlingFriction)) * ((double) mPhysicalCoeff)) / 0.3499999940395355d));    }}

更多相关文章

  1. android clipChildren与clipToPadding
  2. Android下如何计算要显示的字符串所占的宽度和高度
  3. Android(安卓)自定义View 使用VelocityTracker记录滑动速度
  4. Android(安卓)之 ScrollView(垂直滑动)组件
  5. 必须知道的Android屏幕自适应解决方案
  6. 转 Android监听键盘弹出收起
  7. ListView分隔线
  8. Android事件分发机制四:学了事件分发有什么用?
  9. Android事件分发机制四:学了事件分发有什么用?

随机推荐

  1. CentOS停止维护的原因:Red Hat拒绝为其投
  2. Apache Superset成为ASF顶级项目
  3. 桌面端Firefox将抛弃PWA应用
  4. Elasticsearch改协议、AWS直呼好机会
  5. 创建你的第一个Docker应用
  6. 新的开源组织成立:道德治理,人类自由大于软
  7. WebRTC成为W3C和IETF正式标准
  8. .gitignore 不生效的解决方案
  9. JavaScript2020调查:Angular满意度低,Svelt
  10. OSI强调:SSPL并不是开源许可证