我希望将回收站视图滚动为一张,但无法达到所需的行为。 我的布局结构是:
<ScrollView
android:id="@+id/search_results_scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:isScrollContainer="false"
android:nestedScrollingEnabled="true"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
style="@style/search_results_group_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="RecyclerView 1 Title" />
<android.support.v7.widget.RecyclerView
android:id="@+id/search_results_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
style="@style/search_results_group_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="RecyclerView 1 Title" />
<android.support.v7.widget.RecyclerView
android:id="@+id/some_static_results_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false" />
</LinearLayout>
我的第一个回收商获取新的数据部分,当它滚动到最后时,我想显示其下的其余项目。
首先尝试用 NestedScrollView 制作它,但它的性能是不可接受的,所以我想坚持 ScrollView 。参数的不同变化,自定义布局管理器,无助于达到所需的行为。
据我了解,我需要坚持ScrollView scrollListener,并禁用回收器内部滚动,但在这种情况下,我只获得部分填充 recyclerView (6项而不是20项),即使 recyclerView 有android:layout_height="wrap_content"
。我使用 LinearLayoutManagers 和setAutoMeasureEnabled=true.
所以我的问题是:
- 如何在添加新项目后(超过屏幕高度)扩展recyclerView高度?
- 在这种情况下如何更好地处理滚动?
非常感谢任何帮助。
答案 0 :(得分:0)
感谢您建议的解决方案链接!
不幸的是,这些方法无法解决回收器中滚动卡顿的问题。
当新的数据部分插入第一个回收站时,一切都工作得非常慢,导致scrollView重新计算每个子项的高度,其内容正在发生变化(同样的问题出现在NestedScrollView中)。
通过在ScrollView或NestedScrollView中内联它来杀死所有RecyclerView效率。
我用另一种方式解决了这个问题:
我使用一个RecyclerView 并在其中包含部分。使用自定义ViewHolder 和自定义适配器行为实现此目的。
通过这种方法,我的回收工作非常顺畅,快速。
所以我在RecyclerView中的项目结构:
对于我声明自定义ViewHolder的标题:
protected class HeaderViewHolder extends BaseListAdapter.ViewHolder implements View.OnClickListener {
View view;
TextView textView;
protected HeaderViewHolder(View v) {
super(v);
this.view = v;
textView = this.view.findViewById(R.id.header_text);
v.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (itemClickListener != null)
itemClickListener.onItemClick(v, this.getLayoutPosition());
}
public View getView() {
return this.view;
}
// Set custom header text
public void setTitle(String title) {
textView.setText(title);
}
// Hide or show title, if items section don't have any items
public void setVisibility(int visibility) {
textView.setVisibility(visibility);
}
}
标题ViewHolder的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/search_header"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
CustomListAdapter用于填充和管理回收站部分:
public class CustomListAdapter extends BaseListAdapter<RecyclerItem> {
private static final int FOOTER_TYPE = 10;
private static final int FIRST_HEADER_TYPE = 25;
private static final int SECOND_HEADER_TYPE = 50;
private static final int SECOND_ITEMS_TYPE = 100;
private List<RecyclerItem> secondRecyclerItems = new ArrayList<>();
public CustomListAdapter(List<RecyclerItem> items, Context context) {
super(items, R.layout.first_recycler_item, context);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case FIRST_HEADER_TYPE:
case SECOND_HEADER_TYPE:
HeaderViewHolder holder = new HeaderViewHolder(View.inflate(parent.getContext(), R.layout.header_layout, null));
holder.setTitle(parent.getResources().getString(viewType == FIRST_HEADER_TYPE ? R.string.first_header_title : R.string.second_header_title));
return holder;
case FOOTER_TYPE:
return new HeaderViewHolder(View.inflate(parent.getContext(), R.layout.footer_layout, null));
default:
return super.onCreateViewHolder(parent, viewType);
}
}
@Override
public void onBindViewHolder(BaseListAdapter.ViewHolder holder, int position) {
if (holder instanceof HeaderViewHolder) {
if (position == 0) {
((HeaderViewHolder) holder).setVisibility(items.size() == 0 ? View.GONE : View.VISIBLE);
} else if (position == super.getItemCount() + 1 || position == getItemCount() - 1) {
((HeaderViewHolder) holder).setVisibility(secondRecyclerItems.size() == 0 ? View.GONE : View.VISIBLE);
}
return;
}
RecyclerItem item = position <= items.size()
? items.get(position - 1)
: secondRecyclerItems.get(position - (items.size() + 2));
// Here you populate your items with data, load images, etc...
// TextView title = holder.itemView.findViewById(R.id.first_recycler_item_title);
}
public void clearFirstRecyclerItems() {
items.clear();
notifyDataSetChanged();
}
public void clearSecondRecyclerItems() {
secondRecyclerItems.clear();
notifyDataSetChanged();
}
// Define separate collection for second recycler items. First recycler will be populated by default base adapter
public void swapSecondRecyclerItems(List<RecyclerItem> list) {
if (secondRecyclerItems != null) {
secondRecyclerItems.clear();
secondRecyclerItems.addAll(list);
} else {
secondRecyclerItems = new ArrayList<>();
secondRecyclerItems.addAll(list);
}
notifyDataSetChanged();
}
// Handle items click, and skip clicks on headers
public RecyclerItem getClickedItem(int position) {
if (position == super.getItemCount() + 1 || position == 0 || position == getItemCount() - 1)
return null;
return position <= items.size()
? items.get(position - 1)
: secondRecyclerItems.get(position - (items.size() + 2));
}
// That's the core method to split recycler items into sections, depending on their position
@Override
public int getItemViewType(int position) {
if (position == 0) {
return FIRST_HEADER_TYPE;
} else if (position == super.getItemCount() + 1) {
return SECOND_HEADER_TYPE;
} else if (position == getItemCount() - 1) {
return FOOTER_TYPE;
} else if (position > super.getItemCount() + 1) {
return SECOND_ITEMS_TYPE;
}
return super.getItemViewType(position);
}
// Redefine overall items quantity - super.getItemCount() (base recyclerAdapter items) + secondRecyclerItems + 3 (2 headers and 1 footer)
@Override
public int getItemCount() {
return super.getItemCount() + secondRecyclerItems.size() + 3;
}
public int getFirstRecyclerItemsCount() {
return super.getItemCount() + 1;
}
}
完整性BaseListAdapter:
public abstract class BaseListAdapter<T> extends RecyclerView.Adapter<BaseListAdapter.ViewHolder> {
protected List<T> items;
protected @android.support.annotation.LayoutRes int layout;
protected Context context;
protected OnItemClickListener itemClickListener;
public BaseListAdapter(List<T> items, @android.support.annotation.LayoutRes int layout, Context context) {
this.items = items;
this.layout = layout;
this.context = context;
}
public T getItem(int position) {
return items.get(position);
}
public List<T> getItems() {
return items;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.itemClickListener = onItemClickListener;
}
// Create new views (invoked by the layout manager)
@Override
public BaseListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
return new ViewHolder(v);
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return items.size();
}
/**
* Update the recycler view with a new dataset.
* */
public void swap(List<T> list){
if(items != null) {
items.clear();
items.addAll(list);
}
else {
items = new ArrayList<>();
items.addAll(list);
}
notifyDataSetChanged();
}
public void add(List<T> list){
items.addAll(list);
notifyDataSetChanged();
}
protected class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private View view;
protected ViewHolder(View v) {
super(v);
this.view = v;
v.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if(itemClickListener != null)
itemClickListener.onItemClick(v, this.getLayoutPosition());
}
public View getView() {
return this.view;
}
}
public interface OnItemClickListener
{
void onItemClick(View v, int position);
}
}
希望它可以帮助别人。