ScrollView 和RecyclerView都是滑动组件,因此存在滑动事件冲突问题,解决思路就是在事件分发函数中将其中下层View的滑动事件做拦截处理
布局示例代码如下:
<com.xxx.xxx.widget.ScrollInterceptScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<View
android:id="@+id/divider2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BBBBBB"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants"
app:layout_constraintTop_toBottomOf="@+id/linearLayout3">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="24dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</RelativeLayout>
</View>
</com.xxx.xxx.widget.ScrollInterceptScrollView>
注意:在布局中包裹一层RelativeLayout
,并且加上这个属性
android:descendantFocusability="blocksDescendants"
blocksDescendants
这个属性的官方解释是viewgroup会覆盖子类控件而直接获得焦点
继承ScrollView类自定义ScrollView
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.ScrollView;
public class ScrollInterceptScrollView extends ScrollView {
private int downX, downY;
private int mTouchSlop;
public ScrollInterceptScrollView(Context context) {
this(context, null);
}
public ScrollInterceptScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScrollInterceptScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ScrollInterceptScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
downX = (int) ev.getRawX();
downY = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int moveY = (int) ev.getRawY();
// 判断是否滑动,若滑动就拦截事件
if (Math.abs(moveY - downY) > mTouchSlop) {
return true;
}
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
}
ScrollView滑动加载更多
判断的思路就是当前滑动的y
坐标是否大于等于当前ScrollView 的高度
//这个标志位是为了方式加载更多重复执行
private var isLoadMore = true
//页码
private var page=0
//滑动处理,实现滑动监听方法
scrollView.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
//加载更多
if (scrollY >= scrollView.getChildAt(0)
.measuredHeight - scrollView.measuredHeight
) {
if (isLoadMore) {
Log.i("allyn", "加载更多")
isLoadMore = false;
page++
getData()
}
}
}
讲解完了,希望对遇到问题的朋友有帮助!!