防止Recyclerview拦截滚动/触摸事件 [英] Prevent Recyclerview from intercepting scroll/touch events

查看:138
本文介绍了防止Recyclerview拦截滚动/触摸事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我到处都在寻找这个东西,而且已经被困了几个小时.我真的需要帮助!

So I looked everywhere for this and I've been stuck for a few hours; I really need the help!

因此,我在另一个滚动视图(即nestedscrollview)内有一个(固定大小的)recyclerview.我在此视图上也有CollapsingToolbarLayout.问题是,当我滚动整个视图并位于recyclerview上时,CollapsingToolbarLayout不会展开/收缩(仅当CollapsingToolbarLayout收缩后才展开/收缩,而我向下滚动并因此展开了).否则,当我在recyclerview上时,CollapsingToolbarLayout永远不会对滚动更改做出反应.我尝试拦截触摸并返回false,但没有任何效果.

So I have a (fixed size) recyclerview inside another scrollview, which is the nestedscrollview. I also have the CollapsingToolbarLayout on this view. The problem is that when I scroll the entire view and I'm on the recyclerview, the CollapsingToolbarLayout doesnt expand/contract (it only does so when the CollapsingToolbarLayout has contracted, and I'm scrolling down and so it does expand). Otherwise, CollapsingToolbarLayout never reacts to scroll changes when Im on the recyclerview. I tried intercepting the touch and returning false and it nothing works.

有什么建议吗?

更新

我想做的一个很好的例子是Whatsapp的个人资料活动,该活动具有CollapsingToolbarLayout,如果个人资料是一个组,它将显示该组中的用户列表.那正是我要在这里执行的操作,但是当我在该用户列表中滚动时,它不会滚动整个视图(循环视图正在截获..)

A good example of what I'm trying to do is Whatsapp's profile activity, where it has the CollapsingToolbarLayout and if the profile is a group, it shows the list of users in that group. That's exactly what I'm trying to do here, but when Im scrolling inside that user list, it doesnt scroll the entire view (recylcler view is intercepting .. )

推荐答案

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

/** 
This is an abstract class that all of my viewholders inherit from. 
This is a contract telling me that any subclasses that inherit from this
base class are required to write their own `public void bind(int position,
Program program);` method. 
*/
abstract class ProgramBaseViewHolder extends RecyclerView.ViewHolder {

    public ProgramBaseViewHolder(View itemView) {
        super(itemView);
    }

    public abstract void bindDataToView(int position, Program program);
}

/**`@Bind` and Butterknife.bind is part of a viewbinding library called 
Butterknife. This usage of "bind" is the equivalent of your `findViewById()` 
calls. */

/**
This is the Airtime view that holds airtimes. It is a view holder that
inherits from my base view holder and implements its own version if bind.
*/
class AirtimeViewHolder extends ProgramBaseViewHolder {
    @Bind(R.id.program_airtimes)
    TextView mProgramAirtimes;

    static final int viewType = 0;

    public AirtimeViewHolder(View itemView) {
        super(itemView);
        /**This call to butterknife can be replaced with an
        itemView.findViewById(R.id.yourview) */
        ButterKnife.bind(this, itemView);
    }

    //This is where you set your text and hide or show your views.
    @Override
    public void bindDataToView(int position, Program program) {
        List<Airtime> airtimes = program.getAirtimes();
        if (!airtimes.isEmpty()) {
            mProgramAirtimes.setText(Utils.getFriendlyAirtimes(airtimes));
        } else {
            mProgramAirtimes.setText(
                    Utils.getFriendlyAirTime(program.getAirtime()));
        }
    }
}

/**
This is the Description view that holds descriptions. It is a view holder  
that inherits from my base view holder and implements its own version if    
bind.
*/
class DescriptionViewHolder extends ProgramBaseViewHolder {
    @Bind(R.id.description_card_layout)
    TextView mProgramDescription;

    static final int viewType = 1;

    public DescriptionViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }

    @Override
    public void bindDataToView(int position, Program program) {
        mProgramDescription.setText(Html.fromHtml(program.getFullDescription()));
    }
}
//This is another type of view with another different type of layout.
class HostsViewHolder extends ProgramBaseViewHolder {
    @Bind(R.id.card_view_host_name)
    TextView mProgramHostName;

    static final int viewType = 2;

    public HostsViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }

    @Override
    public void bindDataToView(int position, Program program) {
        mProgramHostName.setText(program.getHosts().get(position - 2).getDisplayName());
    }
}
//Again another type of view extending my base view.
class CategoriesViewHolder extends ProgramBaseViewHolder {
    @Bind(R.id.program_categories)
    TextView mProgramCategories;
    static final int viewType = 42;

    public CategoriesViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }

    @Override
    public void bindDataToView(int position, Program program) {
        List<Category> categoryList = program.getCategories();
        StringBuilder stringBuilder = new StringBuilder();
        for (Category category : categoryList) {
            stringBuilder.append(category.getTitle())
                    .append(" ");
        }
        mProgramCategories.setText(stringBuilder.toString());
    }
}

//This is where the normal looking recycler view code comes in.
private Context mContext;
private LayoutInflater mInflater;
private Program mProgramData;
private int mNextProgramId;

public ProgramRecyclerAdapter(Context context) {
    mContext = context;
    mInflater = LayoutInflater.from(mContext);
}

/**This method is where I am determining what view type each item in my list 
will be. I wanted a single airtimes view followed by a single description 
view and then X amount of hosts views and a single category view. I return 
position in the third else if because the position helps me determine which 
host name to display in the bindDataToViews call of the HostViewHolder.*/
@Override
public int getItemViewType(int position) {
    if (position == AirtimeViewHolder.viewType) {
        return AirtimeViewHolder.viewType;
    } else if (position == DescriptionViewHolder.viewType) {
        return DescriptionViewHolder.viewType;
    } else if (position > DescriptionViewHolder.viewType
            && position <= DescriptionViewHolder.viewType + getHostsNum()) {
        return position;
    } else {
        return CategoriesViewHolder.viewType;
    }
}

//This method figures out how many hosts will be displayed
private int getHostsNum() {
    if (mProgramData != null) {
        return mProgramData.getHosts().size();
    }
    return 0;
}
// This method determines if I will show a category view or not.
private int getCategoriesNum() {
    if (mProgramData != null && mProgramData.getCategories().size() > 0) {
        return 1;
    }
    return 0;
}

/**This returns haw many items will be in the list. 1 Airtime view, 1 
Description view, x amount of Host views and 0 or 1 category views */
@Override
public int getItemCount() {
    return 2 + getHostsNum() + getCategoriesNum();
}

/** This returns the appropriate View holder for the requested view type that 
was set by getItemViewType()which is determined by position. I pass the inflated parent view and the data.     
*/
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == AirtimeViewHolder.viewType) {
        return new AirtimeViewHolder(mInflater.inflate(R.layout.airtime_card_layout, parent, false));
    } else if (viewType == DescriptionViewHolder.viewType) {
        return new DescriptionViewHolder(mInflater.inflate(R.layout.description_card_layout, parent, false));
    } else if (viewType > DescriptionViewHolder.viewType
            && viewType <= DescriptionViewHolder.viewType + getHostsNum()) {
        return new HostsViewHolder(mInflater.inflate(R.layout.hosts_card_layout, parent, false));
    } else
        return new CategoriesViewHolder(mInflater.inflate(R.layout.categories_card_layout, parent, false));
}

/*This method is what ties everything together. After I ensure that the data 
is not null I call bindDataToView on a ProgramBaseViewHolder. Depending on 
which type of subclass it is will determine which overridden bindData code to 
use and what view to display. */
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    ProgramBaseViewHolder baseViewHolder = (ProgramBaseViewHolder) holder;
    if (mProgramData != null) {
        baseViewHolder.bindDataToView(position, mProgramData);
    }
}

//This is used to set the data for this program
public void setProgramData(Program program) {
    mProgramData = program;
}

public Program getProgramData() {
    return mProgramData;
}

public boolean isEmpty() {
    return mProgramData == null;
}
}

这是通话时间布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/card_margin">  
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:orientation="vertical"> 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/airtimes_label"
        android:textSize="18dp"
        android:textStyle="bold"
        android:textAppearance="@style/TextAppearance.AppCompat.Body2"
        android:layout_marginBottom="4dp"/> 
    <TextView
        android:id="@+id/program_airtimes"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textAppearance="@style/TextAppearance.AppCompat.Title" />  
</LinearLayout>

这是我的主机布局.您会注意到,我在这里没有使用大多数视图,因为这是一个正在进行的应用程序,并且相同的布局用于包含主机图片及其程序的不同活动.

This is my host layout. You will notice that I am not using most of the views here because this is an app in progress and the same layout is used for a different activity that includes the host picture and their programs.

    <?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/host_card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/card_margin"
    card_view:cardBackgroundColor="@color/white"
    card_view:cardCornerRadius="2dp">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="8dp" />
        <ImageView
            android:id="@+id/host_image"
            android:layout_width="112dp"
            android:layout_height="112dp"
            android:layout_alignParentLeft="true"
            android:visibility="gone"
            android:layout_centerVertical="true"
            android:layout_marginRight="8dp" />
        <LinearLayout
            android:id="@+id/details"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_toRightOf="@id/host_image"
            android:orientation="vertical">
            <TextView
                android:id="@+id/card_view_host_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="18sp"
                android:layout_margin="16dp"
                android:textAppearance="@style/TextAppearance.AppCompat.Body2"
                android:layout_gravity="left" />
            <TextView
                android:id="@+id/card_view_hosts_programs"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:visibility="gone"
                android:textStyle="bold"
                android:textSize="12sp"
                android:layout_marginBottom="16dp"
                android:layout_gravity="left"/>
        </LinearLayout>
    </RelativeLayout>
</android.support.v7.widget.CardView>

这是处理上述回收站适配器的活动的布局.

And here is the layout for the activity that handles the above recycler adapter.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout   
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="@dimen/detail_backdrop_height"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:background="@color/white">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:contentScrim="?attr/colorPrimary"
        app:expandedTitleMarginEnd="64dp"
        app:expandedTitleMarginStart="48dp"
        app:expandedTitleTextAppearance="@style/ExpandedAppBar"
        app:collapsedTitleTextAppearance="@style/CollapsedAppBar"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <ImageView
            android:id="@+id/program_collapsing_image_view"
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:src="@drawable/kzfr_logo"
            android:scaleType="centerCrop"
            app:layout_collapseMode="parallax" />

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_collapseMode="pin" />

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

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

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

我的卡片视图的顶部和底部都有边距,因此,如果您在卡片视图上使用边距,我相信您可以在看起来像同一张卡片的情况下完成与WhatsApp相同类型的视图.它的多个卡视图实际上具有0个顶部和底部边距.在whatsApp视图中,您正在谈论它在哪里显示组的参与者参与者,添加参与者,甚至ExitGroup按钮视图都属于同一回收者视图.我怀疑这是嵌套滚动视图中的回收器视图,它们不旨在一起工作.

My cardviews have margins on the tops and bottoms so If you play with the margins on the card views I am sure you can accomplish the same type of view as WhatsApp where it looks like the same card. Its really multiple card views with 0 top and bottom margins. In the whatsApp view you were talking about where it shows participants of a group The participants, add participants and even the ExitGroup button views are all part of the same recycler view. I doubt that it is a recycler view inside a nested scroll view they are not meant to work together.

这篇关于防止Recyclerview拦截滚动/触摸事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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