ViewHolder 中的嵌套 RecyclerView 破坏了折叠工具栏布局 [英] Nested RecyclerView in ViewHolder breaks Collapsing Toolbar Layout

本文介绍了ViewHolder 中的嵌套 RecyclerView 破坏了折叠工具栏布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 CoordinatorLayout 中托管了一个垂直的 RecyclerView,具有折叠的工具栏布局.此 RecyclerView 的 ViewHolder 包含另一个带有 GridLayoutManager 的 RecyclerView.

I have a vertical RecyclerView hosted in a CoordinatorLayout featuring a collapsing toolbar layout. The ViewHolder for this RecyclerView contains yet another RecyclerView with a GridLayoutManager.

这种嵌套的原因是内部 RecyclerView 显示的图片集合可以有 1 到 20 张图片之间的任意位置.我不知道会有多少张图片,但是Grid的跨度必须始终为3.每次绑定ViewHolder时,我都会调整RecyclerView的布局参数以容纳内容.

The reason for this nesting is that the inner RecyclerView displays a collection of pictures that can have anywhere between 1 - 20 pictures. I don't know how many pictures there will be, but the span of the Grid must always be 3. Every time I bind the ViewHolder I adjust the layout params of the RecyclerView to just accommodate the contents.

如果没有 CollapsingToolBarLayout,这很有效.但是,如果有一个折叠的 ToolBar,用我的手指在内部 RecyclerView 上滚动不会滚动折叠工具栏,但是在另一个项目上滚动.

This works great if there is no CollapsingToolBarLayout. However, if there is a collapsing ToolBar, scrolling with my finger on the inner RecyclerView does not scroll the Collapsing toolbar, scrolling on another Item however does.

再次强调,在绑定的 ViewHolder 中,如果我开始滚动除嵌套的 RecyclerView 之外的任何其他项目,滚动工作正常.但是,如果我在嵌套的 RecyclerView 上开始滚动,则会中断.

To reemphasize, in the bound ViewHolder, if I begin to scroll on any other item besides the nested RecyclerView, scrolling works fine. However, If I begin the scroll on the nested RecyclerView, then it breaks.

是否可以防止内部 RecyclerView 上的滚动拦截而只让 Parent 滚动?但是,我希望内部 RecyclerView 仍然处理点击.

Is it possible to prevent scrolling interception on the inner RecyclerView and let only the Parent scroll? I would like the inner RecyclerView to still handle clicks however.

这是该现象的 YouTube 链接:https://youtu.be/fzj7HmqskzU

Here's a YouTube link for the phenomenon: https://youtu.be/fzj7HmqskzU

这是父 RecyclerView 的 XML:

Here is the XML for the parent RecyclerView:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivityFragment">

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

<android.support.design.widget.AppBarLayout
    android:id="@+id/app_bar_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:elevation="4dp"
        app:contentScrim="?attr/colorPrimary"
        app:layout_collapseParallaxMultiplier="0.7"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <View
            android:id="@+id/header_view"
            android:layout_width="match_parent"
            android:layout_height="192dp"
            android:animateLayoutChanges="true"
            android:background="@color/primary" />

        <android.support.v7.widget.Toolbar
            android:id="@+id/action_bar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/abc_action_bar_default_height_material"
            android:elevation="4dp"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/Theme.AppCompat.NoActionBar"
            app:theme="@style/Theme.AppCompat.NoActionBar" />
    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>

这是承载嵌套 RecyclerView 的主要 ViewHolder:

Here's the primary ViewHolder that hosts the nested RecyclerView:

public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.ViewHolder> {

private static final int MODEL_OBJECT = 1;

private List<ModelObject> modelObjects;

private Context context;

private int imageSize;

public SimpleAdapter(List<ModelObject> modelObjects) {

    this.modelObjects = modelObjects;
    setHasStableIds(true);
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    context = viewGroup.getContext();

    int screenWidth= context.getResources().getDisplayMetrics().widthPixels;

    imageSize = screenWidth / 3;

    final LayoutInflater inflater = LayoutInflater.from(context);

    View itemView;

    itemView = inflater.inflate(R.layout.fragment_main_row, viewGroup, false);

    return new ViewHolder(itemView, viewType);
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {

    final ModelObject modelObject = modelObjects.get(position);

    // set text
    modelObject.setPosition(position + 1);
    viewHolder.titleTextView.setText(modelObject.getTitle());
    viewHolder.positionTextView.setText("" + (position + 1));


    adjustsizes(viewHolder.recyclerView, modelObject, imageSize);

    final NestedAdapter nestedAdapter = new NestedAdapter(modelObject.getPhotos());

    // Create and set GridLayoutManager for RecyclerView
    final GridLayoutManager recylerViewGridLayoutManager = new GridLayoutManager(context, 3);
    recylerViewGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            return 1;
        }
    });

    viewHolder.recyclerView.setAdapter(nestedAdapter);
    viewHolder.recyclerView.setLayoutManager(recylerViewGridLayoutManager);
}

@Override
public int getItemViewType(int position) {
    return MODEL_OBJECT;
}

@Override
public int getItemCount() {
    return modelObjects.size();
}

@Override
public long getItemId(int position) {
    return modelObjects.get(position).hashCode();
}

private void adjustsizes(RecyclerView recyclerView, ModelObject modelObject, int imageSize) {
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) recyclerView.getLayoutParams();

    if (modelObject.getPhotos() != null) {

        Double numberOfRowsDouble = modelObject.getPhotos().size() / 3.0;

        int numberOfRowsInt = (numberOfRowsDouble.intValue() < numberOfRowsDouble)
                ? numberOfRowsDouble.intValue() + 1
                : numberOfRowsDouble.intValue();

        params.height = imageSize * numberOfRowsInt;
    }
}

public static class ViewHolder extends RecyclerView.ViewHolder {

    public int viewType;

    public ViewGroup mContainer;
    public View mDragHandle;
    public TextView titleTextView;
    public TextView positionTextView;
    public RecyclerView recyclerView;

    public ViewHolder(View itemView, int viewType) {
        super(itemView);
        this.viewType = viewType;
        mContainer = (ViewGroup) itemView.findViewById(R.id.container);
        mDragHandle = itemView.findViewById(R.id.drag_handle);
        titleTextView = (TextView) itemView.findViewById(R.id.title);
        positionTextView = (TextView) itemView.findViewById(R.id.position);
        recyclerView = (RecyclerView) itemView.findViewById(R.id.recycler_view);
    }
}

}

最后,这是带有图片的嵌套子级的适配器:

Finally, here's the adapter for the nested child with the picture:

public class NestedAdapter extends RecyclerView.Adapter<NestedAdapter.PhotoViewHolder> {

private static final int PHOTO = 1;

private Context context;

ArrayList<String> photos;

/**
 * Default constructor, takes no data as nothing has been recieved from the API
 */

public NestedAdapter(ArrayList<String> photos) {
    this.photos = photos;
}

@Override
public PhotoViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

    this.context = viewGroup.getContext();
    View itemView;

    switch (viewType) {
        default: // Load default Message layout as bucketLists all have the same layout
            itemView = LayoutInflater.from(context).inflate(R.layout.fragment_photo_row, viewGroup, false);
            break;
    }

    return new PhotoViewHolder(itemView, viewType);
}

@Override
public void onBindViewHolder(PhotoViewHolder viewHolder, final int position) {

    // Switch depending on the kind of View
    switch (getItemViewType(position)) {
        case PHOTO: // Subtract 1, padding has taken up a space
            final String photo = photos.get(position);

            Picasso.with(context)
                    .load(photo)
                    .placeholder(R.drawable.rocks) // Must use place holder or fit won't work!
                    .fit()
                    .centerCrop()
                    .into(viewHolder.photo);
            break;
    }
}

@Override
public int getItemViewType(int position) {
    return PHOTO;
}

@Override
public int getItemCount() {
    return photos.size();

}

// ViewHolder for actual content
public final static class PhotoViewHolder extends RecyclerView.ViewHolder {

    public int viewType;        // Used to specify the view type.

    public ImageView photo;

    public PhotoViewHolder(View itemView, int ViewType) {
        super(itemView);

        switch (ViewType) {
            case PHOTO:
                viewType = PHOTO;
                photo = (ImageView) itemView.findViewById(R.id.photo);
                break;
        }
    }
}

}

推荐答案

我在使用 RecyclerView 和 CollapsingToolbarLayout 时遇到了同样的问题,其中 RecyclerView 位于 NestedScrollView 子布局内.

I had the same issue with RecyclerView and CollapsingToolbarLayout, where the RecyclerView was inside a NestedScrollView child layout.

对我来说,解决方案是以编程方式设置:

For me the solution was to set programmatically:

mRecyclerView.setNestedScrollingEnabled(false);

注意:我尝试在 XML 中的 RecyclerView 上设置它,但它不起作用?

Note: I tried setting this on the RecyclerView in XML but it did not work?

android:nestedScrollingEnabled="false"

另一个使 CollapsingToolbarLayout 滚动的技巧是将 1000dp 的最小高度值设置为嵌套滚动视图

Another trick to make the CollapsingToolbarLayout scroll is to set a 1000dp min height value to the child of the NestedScrollView

android:minHeight="1000dp"

为什么是 1000dp?此处的 SupportDesignDemos 示例:https://android.googlesource.com/platform/development/+/e088638/samples/SupportDesignDemos/res/layout/include_appbar_scrollview.xml

why 1000dp? SupportDesignDemos example here: https://android.googlesource.com/platform/development/+/e088638/samples/SupportDesignDemos/res/layout/include_appbar_scrollview.xml

<android.support.design.widget.CoordinatorLayout>
    <android.support.design.widget.AppBarLayout>
        <android.support.design.widget.CollapsingToolbarLayout >

            <ImageView/>
            <android.support.v7.widget.Toolbar/>

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>
    <android.support.v4.widget.NestedScrollView
         app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout android:minHeight="1000dp">

            <android.support.v7.widget.RecyclerView 
                app:layout_behavior="@string/appbar_scrolling_view_behavior"
             />

        </LinearLayout>

    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

这篇关于ViewHolder 中的嵌套 RecyclerView 破坏了折叠工具栏布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆