CoordinatorLayout实现自定义头条卡住的解决方案

废话不多说,直接上代码,xml布局如下:



    
    

        

            
            

            
            
                
                

                
                

                

                    
                    

                    
                

                

                    

                    

                    
                

                
                
            

            
            

                

                    

                    

                    
                
            
        

        
        

            

            
        
    

    
    
    

    

效果图如下:


CoordinatorLayout实现自定义头条卡住的解决方案_第1张图片
展开状态.jpg

CoordinatorLayout实现自定义头条卡住的解决方案_第2张图片
收起状态.jpg

需要针对RecyclerView添加滚动监听器,当RecyclerView停下来的时候判定它距离屏幕顶部的高度,然后让appBarLayout执行展开或者收起,这样就能够规避掉RecyclerView和CoordinatorLayout组合发生抖动之后卡住不动的问题,具体代码如下:

// 添加顶部滑动监听器
if (appBarOffsetListener == null) {
    appBarOffsetListener = new AppBarLayout.OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            if (llTitleContent != null && tvTitle != null) {
                if (verticalOffset <= -llTitleContent.getHeight() / 2) {
                    tvTitle.setText("互动课程详情");
                } else {
                    tvTitle.setText("");
                }
            }
        }
    };
}
// 头条发生拖动时,需要变换主标题
appBarLayout.addOnOffsetChangedListener(appBarOffsetListener);
// 设置内容滚动监听器
if (scrollListener == null) {
    scrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            // 如果当前处于空闲状态,那么可以执行判定操作
            if (newState == RecyclerView.SCROLL_STATE_IDLE && rvContentList != null) {
                int[] location = new int[2];
                rvContentList.getLocationInWindow(location);
                // 两个标题栏的高度(一级标题和二级标题的高度) 加上 状态栏的高度就是recyclerView距离屏幕顶部可能到达最近的距离
                float minY = titleHeight * 2 + statusHeight;
                // 如果当前recyclerView距离最高位置小于5个像素,那么认为应该关闭,否则打开
                if (location[1] - minY <= 5) {
                    if (appBarLayout != null) {
                        appBarLayout.setExpanded(false, true);
                    }
                }
                // 否则打开整体布局
                else if (appBarLayout != null) {
                    appBarLayout.setExpanded(true, true);
                }
            }
        }
    };
}
// 添加滚动监听器,防止卡顿的发生
rvContentList.addOnScrollListener(scrollListener);

下面这个FlingBehavior 主要用于解决RecyclerView滑动之后,第一次点击发生失效的问题

import android.content.Context;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;

/**
 * 用于解决CoordinatorLayout与RecyclerView之间发生的点击问题
 */
public class FlingBehavior extends AppBarLayout.Behavior {

    public FlingBehavior() {
    }

    public FlingBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
        stopNestedScrollIfNeeded(dyUnconsumed, child, target, type);
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
        stopNestedScrollIfNeeded(dy, child, target, type);
    }

    private void stopNestedScrollIfNeeded(int dy, AppBarLayout child, View target, int type) {
        if (type == ViewCompat.TYPE_NON_TOUCH) {
            final int currOffset = getTopAndBottomOffset();
            if ((dy < 0 && currOffset == 0) || (dy > 0 && currOffset == -child.getTotalScrollRange())) {
                ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH);
            }
        }
    }
}

你可能感兴趣的:(CoordinatorLayout实现自定义头条卡住的解决方案)