It is often necessary to embed one or more RecyclerViews in a ScrollView in a project. This approach usually leads to the following problems
- Page swipe stuck
- ScrollView height is not displayed properly
- RecyclerView content is not displayed completely
This paper will use a variety of ways to solve the above problems
Sliding stuck solution
If there is only the problem of sliding stuck, the following two simple methods can be used to quickly solve the problem
The first: use the internal method of RecyclerView
recyclerView.setHasFixedSize(true); recyclerView.setNestedScrollingEnabled(false);
public void setNestedScrollingEnabled(boolean enabled) { getScrollingChildHelper().setNestedScrollingEnabled(enabled); }
public void setNestedScrollingEnabled(boolean enabled) { if (mIsNestedScrollingEnabled) { ViewCompat.stopNestedScroll(mView); } mIsNestedScrollingEnabled = enabled; }
In this way, the sliding of RecyclerView itself is limited, and the sliding of the entire page is only realized by ScrollView, which can solve the problem of sliding stuck.
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this) { @Override public boolean canScrollVertically() { return false; } };
recycler.setLayoutManager (linearLayoutManager);
Comprehensive solution
If you need to comprehensively solve the above three problems, you can use the following methods
Insert LinearLayout/RelativeLayout
Insert a layer of LinearLayout/RelativeLayout into the original layout to form the following layout
Override LayoutManager
The core idea of this method is to override the onMeasure() method in LayoutManager, that is
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
super.onMeasure(recycler, state, widthSpec, heightSpec);
}
Reimplement the calculation of the height of RecyclerView so that it can show the correct height in ScrollView. For the specific rewriting method, please refer to this article
http://www.cnblogs.com/tianzh...
Override ScrollView
The core idea of this method is to intercept the sliding event by rewriting the onInterceptTouchEvent(MotionEvent ev) method of ScrollView, so that the sliding event can be directly passed to the RecyclerView. For the specific rewriting method, please refer to the following
/**
* Created by YH on 2017/10/10.
*/
public class RecyclerScrollView extends ScrollView {
private int slop;
private int touch;
public RecyclerScrollView(Context context) {
super(context);
setSlop(context);
}
public RecyclerScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
setSlop(context);
}
public RecyclerScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setSlop(context);
}
/**
* 是否intercept当前的触摸事件
* @param ev 触摸事件
* @return true:调用onMotionEvent()方法,并完成滑动操作
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// 保存当前touch的纵坐标值
touch = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
// 滑动距离大于slop值时,返回true
if (Math.abs((int) ev.getRawY() - touch) > slop) return true;
break;
}
return super.onInterceptTouchEvent(ev);
}
/**
* 获取相应context的touch slop值(即在用户滑动之前,能够滑动的以像素为单位的距离)
* @param context ScrollView对应的context
*/
private void setSlop(Context context) {
slop = ViewConfiguration.get(context).getScaledTouchSlop();
}
}
In fact, although we can solve a series of problems caused by ScrollView nesting RecyclerView in a variety of ways, because the above solutions will make RecyclerView display all content at one time during page loading, so when there are too many items under RecyclerView , will affect the operating efficiency of the entire application. Based on this, in this case, we should try to avoid the layout of ScrollView nested RecyclerView