NestedScrollView和Horizo​​ntal RecyclerView平滑滚动

我有一个垂直的nestedscrollview,其中包含一堆水平布局pipe理器设置的recyclerview。 这个想法与新的谷歌播放商店看起来很相似。 我能够使其function,但它不是一帆风顺的。 以下是问题:

1)水平回收者视图项目在大部分时间都不能拦截触摸事件,即使我点击它也是如此。 滚动视图似乎优先于大部分的议案。 对我来说很难挂钩水平运动。 这个用户体验是令人沮丧的,因为我需要尝试几次才能工作。 如果您查看Play商店,则可以很好地拦截触摸事件,并且效果不错。 我在游戏商店注意到他们设置的方式是在一个垂直回收站内部进行许多水平的回收站查看。 没有滚动视图。

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" /> 

这个用户界面模式是非常基本的,很可能用在许多不同的应用程序。 我已经阅读了许多SO,在那里,ppl说把一个列表放在一个列表中是一个坏主意,但是它是一个非常常见和现代的用户界面模式,用在所有的地方。思考netflix像一系列水平滚动列表一个垂直列表。 没有一个顺利的方法来完成这个?

来自商店的示例图片:

Google Play商店

Solutions Collecting From Web of "NestedScrollView和Horizo​​ntal RecyclerView平滑滚动"

所以平滑的滚动问题现在是固定的。 这是由devise支持库(当前为23.1.1)的NestedScrollView中的一个错误引起的。

您可以阅读有关这个​​问题和简单的解决方法: https : //code.google.com/p/android/issues/detail?id=194398

简而言之,在你执行一个fling之后,nestedscrollview并没有在scroller组件上注册一个完整的,所以它需要一个额外的'ACTION_DOWN'事件来释放父嵌套scrollview来拦截(占用)后续事件。 所以发生了什么是如果你试图滚动你的孩子列表(或viewpager),一扔后,第一次触摸释放父NSV绑定和后续触摸将工作。 这使得UX非常糟糕。

基本上需要在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,并且子列表应该正确地拦截和处理触摸事件。

呃,这样的错误实际上有很多,使得我想把devise支持库完全抛弃,并在其更成熟的时候重新访问它。

我已经成功地在ViewPager的垂直滚动父级中进行水平滚动:

 <android.support.v4.widget.NestedScrollView ... <android.support.v4.view.ViewPager android:id="@+id/pager_known_for" android:layout_width="match_parent" android:layout_height="350dp" android:minHeight="350dp" android:paddingLeft="24dp" android:paddingRight="24dp" android:clipToPadding="false"/> 

公共类UniversityKnownForPagerAdapter扩展PagerAdapter {

 public UniversityKnownForPagerAdapter(Context context) { mContext = context; mInflater = LayoutInflater.from(mContext); } @Override public Object instantiateItem(ViewGroup container, int position) { View rootView = mInflater.inflate(R.layout.card_university_demographics, container, false); ... container.addView(rootView); return rootView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View)object); } @Override public int getCount() { return 4; } @Override public boolean isViewFromObject(View view, Object object) { return (view == object); } 

只有问题:你必须提供一个固定的高度视图传呼机