我有一个垂直的nestedscrollview,其中包含一堆带有水平布局管理器设置的recyclerview.这个想法非常类似于新的谷歌游戏商店的外观.我能够使它起作用,但它根本不光滑.以下是问题:
1)水平回收视图项目大多数时间都无法拦截触摸事件,即使我点击它也是如此.滚动视图似乎优先于大多数动作.我很难在水平运动上找到钩子.这个用户体验令人沮丧,因为我需要在它工作之前尝试几次.如果你检查游戏商店,它能够很好地拦截触摸事件,它只是运作良好.我注意到在游戏商店中他们设置的方式是在一个垂直的回收者视图中的许多水平回收视图.没有滚动视图.
2)水平回收视图的高度必须手动设置,并且没有简单的方法来计运算符元素的高度.
这是我正在使用的布局:
<android.support.v4.widget.NestedScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:background="@color/dark_bgd"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/main_content_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
tools:visibility="gone"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/starring_list"
android:paddingLeft="@dimen/spacing_major"
android:paddingRight="@dimen/spacing_major"
android:layout_width="match_parent"
android:layout_height="180dp" />
此UI模式非常基本,很可能在许多不同的应用程序中使用.我已经阅读了许多SO,其中ppl说将列表放在列表中是一个坏主意,但它是一个非常普遍和现代的UI模式在整个地方使用.想看netflix就像界面里面有一系列水平滚动列表垂直清单.有没有一个顺利的方法来实现这一目标?
来自商店的示例图片:
解决方法:
所以现在修复了平滑滚动问题.它是由设计支持库(目前为23.1.1)中的NestedScrollView中的错误引起的.
您可以在此处阅读有关问题和简单修复的信息:
https://code.google.com/p/android/issues/detail?id=194398
简而言之,在执行fling之后,nestedscrollview没有在滚动条组件上注册完成,因此它需要一个额外的“ACTION_DOWN”事件来释放父nestedscrollview来拦截(吃掉)后续事件.所以发生的事情是如果你尝试滚动你的子列表(或viewpager),在一次投掷之后,第一次触摸释放父NSV绑定并且后续触摸将起作用.这使得用户体验非常糟糕.
基本上需要在NSV的ACTION_DOWN事件上添加这一行:
computeScroll();
这是我正在使用的:
public class MyNestedScrollView extends NestedScrollView {
private int slop;
private float mInitialMotionX;
private float mInitialMotionY;
public MyNestedScrollView(Context context) {
super(context);
init(context);
}
private void init(Context context) {
ViewConfiguration config = ViewConfiguration.get(context);
slop = config.getScaledEdgeSlop();
}
public MyNestedScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private float xDistance, yDistance, lastX, lastY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final float x = ev.getX();
final float y = ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
lastX = ev.getX();
lastY = ev.getY();
// This is very important line that fixes
computeScroll();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - lastX);
yDistance += Math.abs(curY - lastY);
lastX = curX;
lastY = curY;
if (xDistance > yDistance) {
return false;
}
}
return super.onInterceptTouchEvent(ev);
}
}
使用此类代替xml文件中的nestedscrollview,子列表应该正确拦截和处理触摸事件.
Phew,实际上有很多这样的错误让我想要完全放弃设计支持库,并在它更成熟时重新审视它.