简体   繁体   English

防止Recyclerview拦截滚动/触摸事件

[英]Prevent Recyclerview from intercepting scroll/touch events

So I looked everywhere for this and I've been stuck for a few hours; 因此,我到处寻找它,已经被困了几个小时。 I really need the help! 我真的需要帮助!

So I have a (fixed size) recyclerview inside another scrollview, which is the nestedscrollview. 因此,我在另一个scrollview(即nestedscrollview)中有一个(固定大小的)recyclerview。 I also have the CollapsingToolbarLayout on this view. 我在此视图上也有CollapsingToolbarLayout。 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). 问题在于,当我滚动整个视图并位于recyclerview上时,CollapsingToolbarLayout不会展开/收缩(仅在CollapsingToolbarLayout收缩后才滚动/收缩,而我向下滚动并因此展开)。 Otherwise, CollapsingToolbarLayout never reacts to scroll changes when Im on the recyclerview. 否则,当在recyclerview上输入Im时,CollapsingToolbarLayout永远不会对滚动更改做出反应。 I tried intercepting the touch and returning false and it nothing works. 我尝试拦截触摸并返回false,但没有任何效果。

Any advice? 有什么建议吗?

UPDATE UPDATE

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. 我正在尝试做的一个很好的例子是Whatsapp的个人资料活动,该活动具有CollapsingToolbarLayout,如果个人资料是一个组,它将显示该组中的用户列表。 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 .. ) 那正是我要在此处执行的操作,但是当Im在该用户列表中滚动时,它不会滚动整个视图(循环视图正在截获..)

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;
}
}

This is the Airtime layout 这是通话时间布局

<?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>

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. 我的卡片视图的顶部和底部都有边距,因此,如果您在卡片视图上使用边距,我相信您可以在看起来像同一张卡片的情况下完成与WhatsApp相同类型的视图。 Its really multiple card views with 0 top and bottom margins. 它的多个卡视图实际上具有0个顶部和底部边距。 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. 在whatsApp视图中,您正在谈论它在哪里显示组的参与者参与者,添加参与者甚至ExitGroup按钮视图都属于同一回收者视图。 I doubt that it is a recycler view inside a nested scroll view they are not meant to work together. 我怀疑这是嵌套滚动视图中的回收器视图,它们不是要一起工作的。

这是使用某些数据生成的视图。 “类别”视图被切除,但是在那里。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 BottomSheet正在拦截来自RecyclerView的触摸事件 - BottomSheet is intercepting touch events from RecyclerView 防止CardView内部的RecyclerView拦截触摸 - Prevent a RecyclerView inside CardView from intercepting touch 如何防止 ScrollView 拦截其背后视图的点击/触摸事件? - How to prevent ScrollView from intercepting click/touch events of the view behind it? 防止RecyclerView吞下触摸事件而不创建自定义ViewGroup - Prevent RecyclerView from swallowing touch events without creating custom ViewGroup CoordinatorLayout:如何防止滚动事件到达RecyclerView? - CoordinatorLayout: How can I prevent scroll events from reaching RecyclerView? 禁用 RecyclerView 的触摸事件(以防止用户触摸)? - disable touch events of RecyclerView (to prevent user touches)? Drawerlayout 正在拦截所有触摸事件 - Drawerlayout is intercepting all touch events 防止RecyclerView消耗触摸事件 - Preventing RecyclerView from consuming touch events 拦截导航抽屉标题中的触摸事件以允许RecyclerView滚动? - Intercept touch events in Navigation Drawer Header to allow RecyclerView to scroll? 如何监控ViewHolders的触摸事件并控制它的RecyclerView的滚动动作? - How to monitor touch events of ViewHolders and control the scroll action of it's RecyclerView?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM