[英]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.