首页 文章

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

提问于
浏览
1

所以我到处寻找这个,我被困了几个小时;我真的需要帮助!

所以我在另一个scrollview里面有一个(固定大小)的recyclerview,它是nestedscrollview . 我在这个视图上也有CollapsingToolbarLayout . 问题是,当我滚动整个视图并且我在Recyclerview上时,CollapsingToolbarLayout不会扩展/收缩(它只会在CollapsingToolbarLayout缩小时执行此操作,并且我向下滚动,因此它会扩展) . 否则,当我在recyclerview上时,CollapsingToolbarLayout永远不会对滚动更改做出反应 . 我试图拦截触摸并返回false并且没有任何效果 .

有什么建议?

UPDATE

我正在尝试做的一个很好的例子是Whatsapp的 Profiles 活动,它有CollapsingToolbarLayout,如果 Profiles 是一个组,它会显示该组中的用户列表 . 这正是我在这里要做的事情,但是当我在该用户列表中滚动时,它不会滚动整个视图(recylcler视图正在拦截..)

1 回答

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

    这是Airtime布局

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

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

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

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

    <?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按钮视图都是同一回收者视图的一部分 . 我怀疑它是嵌套滚动视图中的回收器视图,它们不是一起工作的 .

    This is the view that is produced with some data. The Categories view is cut off but it is there.

相关问题