Android的布局:与滚动行为一Viewpager内垂直Recyclerview水平内Recyclerview [英] Android Layout: Horizontal Recyclerview inside a Vertical Recyclerview inside a Viewpager with Scroll Behaviors
问题描述
这是我试图建立与上述映射出的所有元素的应用程序:
This is the app I'm trying to build with all the elements mapped out below:
一切正常,但是,我想内水平面recyclerview没有捕捉到任何垂直卷轴。所有垂直滚动必须朝着外垂直recyclerview,而不是水平的,从而使垂直滚动将允许工具栏根据它scrollFlag到的视图退出出
Everything works, however, I want the inner horizontal recyclerview not to capture any of the vertical scrolls. All vertical scrolls must go towards the outer vertical recyclerview, not the horizontal one, so that the vertical scroll would allow for the toolbar to exit out of view according to it's scrollFlag.
当我把我的手指上recyclerview的草莓厂部分,滚动,滚动它从工具栏:
When I put my finger on the "StrawBerry Plant" part of the recyclerview and scroll up, it scroll out the toolbar:
如果我把我的手指上的水平滚动视图和滚动,它根本不滚动出工具栏。
If I put my finger on the horizontal scrollview and scroll up, it does not scroll out the toolbar at all.
下面是我的XML布局code为止。
The following is my xml layout code so far.
在活动 XML布局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment_container"
android:clipChildren="false">
<android.support.design.widget.CoordinatorLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/container"
>
<android.support.design.widget.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
style="@style/CustomTabLayout"
/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
</android.support.design.widget.CoordinatorLayout>
</FrameLayout>
在水果片段 XML布局(这是code的片段 - 片段标记在上面的图片):
The "Fruits" fragment xml layout (which is the code for the fragment - the fragment is labeled in the above picture):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progressBar"
android:visibility="gone"
android:layout_centerInParent="true"
android:indeterminate="true"/>
<!-- <android.support.v7.widget.RecyclerView-->
<com.example.simon.customshapes.VerticallyScrollRecyclerView
android:id="@+id/main_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
我使用了被称为VerticallyScrollRecyclerView一个自定义的类如下的处理的ViewGroup触摸事件谷歌的例子。其目的是拦截和消耗所有垂直滚动事件,以便将输入/输出工具栏滚动:<一href=\"http://developer.android.com/training/gestures/viewgroup.html\">http://developer.android.com/training/gestures/viewgroup.html
在code对于 VerticallyScrollRecyclerView 是如下:
The code for VerticallyScrollRecyclerView is below:
public class VerticallyScrollRecyclerView extends RecyclerView {
public VerticallyScrollRecyclerView(Context context) {
super(context);
}
public VerticallyScrollRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VerticallyScrollRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
ViewConfiguration vc = ViewConfiguration.get(this.getContext());
private int mTouchSlop = vc.getScaledTouchSlop();
private boolean mIsScrolling;
private float startY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
// Always handle the case of the touch gesture being complete.
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
// Release the scroll.
mIsScrolling = false;
startY = ev.getY();
return super.onInterceptTouchEvent(ev); // Do not intercept touch event, let the child handle it
}
switch (action) {
case MotionEvent.ACTION_MOVE: {
Log.e("VRecView", "its moving");
if (mIsScrolling) {
// We're currently scrolling, so yes, intercept the
// touch event!
return true;
}
// If the user has dragged her finger horizontally more than
// the touch slop, start the scroll
// left as an exercise for the reader
final float yDiff = calculateDistanceY(ev.getY());
Log.e("yDiff ", ""+yDiff);
// Touch slop should be calculated using ViewConfiguration
// constants.
if (Math.abs(yDiff) > 5) {
// Start scrolling!
Log.e("Scroll", "we are scrolling vertically");
mIsScrolling = true;
return true;
}
break;
}
}
return super.onInterceptTouchEvent(ev);
}
private float calculateDistanceY(float endY) {
return startY - endY;
}
}
在收藏布局这是垂直recyclerview内recyclerview:
The "Favourite" layout which is the recyclerview within the vertical recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/white"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Favourite"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="16dp"
android:id="@+id/header_fav"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="@+id/header_fav"
android:id="@+id/recyclerview_fav">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
这已经现在缠着我了一会儿,我没有设法拿出一个解决方案。有谁知道如何解决这个问题?
This has been bugging me for a while now and I have not managed to come up with a solution. Does anyone know how to solve this problem?
5分Griffindor为正确答案,当然,口碑那么点上。
5 points to Griffindor for the correct answer and of course, reputation points on SO.
推荐答案
测试的解决方案:
您只需要调用 mInnerRecycler.setNestedScrollingEnabled(假);
在你的内心 RecyclerView
取值
All you need is to call mInnerRecycler.setNestedScrollingEnabled(false);
on your inner RecyclerView
s
说明
RecyclerView
对通过实施 NestedScrollingChild <在
API 21
介绍嵌套的滚动支持/ code>接口。这是一个有价值的功能,当你有在另一个在同一个方向上滚动滚动视图,并要滚动内查看
集中时才会出现。
RecyclerView
has support for nested scrolling introduced in API 21
through implementing the NestedScrollingChild
interface. This is a valuable feature when you have a scrolling view inside another one that scrolls in the same direction and you want to scroll the inner View
only when focused.
在任何情况下, RecyclerView
默认调用 RecyclerView.setNestedScrollingEnabled(真);
本身时初始化。现在,回到这个问题,因为这两个你的 RecyclerView
取值都在同一 ViewPager
具有 AppBarBehavior
的 CoordinateLayout
必须决定哪些滚动回应,当你从你的内心 RecyclerView 滚动code>;当启用了你内心的
RecyclerView
的嵌套滚动,它就会滚动焦点和 CoordinateLayout
会选择响应其滚动在外部 RecyclerView
的滚动。事情是这样的,因为你的内心 RecyclerView
■不要垂直滚动,就没有垂直滚动的变化(从 CoordinateLayout
的观点),如果没有变化,则 AppBarLayout
也不改变。
In any case, RecyclerView
by default calls RecyclerView.setNestedScrollingEnabled(true);
on itself when initializing. Now, back to the problem, since both of your RecyclerView
s are within the same ViewPager
that has the AppBarBehavior
, the CoordinateLayout
has to decide which scroll to respond to when you scroll from your inner RecyclerView
; when your inner RecyclerView
's nested scrolling is enabled, it gets the scrolling focus and the CoordinateLayout
will choose to respond to its scrolling over the outer RecyclerView
's scrolling. The thing is that, since your inner RecyclerView
s don't scroll vertically, there is no vertical scroll change (from the CoordinateLayout
's point of view), and if there is no change, the AppBarLayout
doesn't change either.
在你的情况,因为你内心的 RecyclerView
,则在不同的方向滚动,你可以禁用它,从而导致 CoordinateLayout
无视它的滚动和外 RecyclerView
的滚动回应。
In your case, because your inner RecyclerView
s are scrolling in a different direction, you can disable it, thus causing the CoordinateLayout
to disregard its scrolling and respond to the outer RecyclerView
's scrolling.
的通知
XML属性的android:nestedScrollingEnabled =布尔
不能用于与 RecyclerView
,以及使用尝试使用的android:nestedScrollingEnabled =FALSE
将导致显示java.lang.NullPointerException
那么,至少现在,你将不得不做,在code。
The xml attribute android:nestedScrollingEnabled="boolean"
is not intended for use with the RecyclerView
, and an attempt to use android:nestedScrollingEnabled="false"
will result in a java.lang.NullPointerException
so, at least for now, you will have to do it in code.
这篇关于Android的布局:与滚动行为一Viewpager内垂直Recyclerview水平内Recyclerview的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!