我的Expandable RecyclerView
涉及滚动滞后问题。
应该注意的是,滞后是在滚动标题时发生的,而不是在滚动子项时发生的。
行布局(recycler_row_expandable.xml
):
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/blonde">
<ImageView
android:id="@+id/categoryPicture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/headerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="23sp"
android:textStyle="bold"
android:textColor="@color/black"
android:layout_marginStart="5dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/categoryPicture"
app:layout_constraintTop_toTopOf="parent"
/>
<ImageView
android:id="@+id/headerPicture"
android:src="@drawable/logo_arrow_expandable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/margin_standard"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</android.support.constraint.ConstraintLayout>
适配器:
public class ActivityRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements
ActivityRecyclerHeaderViewHolder.HeaderViewHolderCallback, ActivityRecyclerChildViewHolder.ChildViewHolderCallback {
private Context context;
private final int ACTIVITY_TYPE = 1;
private final int HEADER_TYPE = 2;
private List<String> activityHeaderList;
private List<String> activityChildList;
private Map<String, Integer> numberOfChildrenPerParentNameMap;
private SparseArray<ActivityRecyclerViewType> viewTypes;
private SparseIntArray headerExpandTracker;
public ActivityRecyclerAdapter(Context context, List<String> activityHeaderList, List<String> activityTypeList, Map<String, Integer> numberOfChildrenPerParent) {
this.context = context;
this.activityHeaderList = activityHeaderList;
this.activityChildList = activityTypeList;
this.numberOfChildrenPerParentNameMap = numberOfChildrenPerParent;
headerExpandTracker = new SparseIntArray(activityHeaderList.size());
viewTypes = new SparseArray<>(activityHeaderList.size() + activityTypeList.size());
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case ACTIVITY_TYPE:
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_row_child, parent, false);
return new ActivityRecyclerChildViewHolder(view, this);
case HEADER_TYPE:
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_row_expandable, parent, false);
return new ActivityRecyclerHeaderViewHolder(view, this);
default:
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_row_child, parent, false);
return new ActivityRecyclerChildViewHolder(view, this);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int itemViewType = getItemViewType(position);
ActivityRecyclerViewType viewType = viewTypes.get(position);
if (itemViewType == ACTIVITY_TYPE) {
bindChildViewHolder(holder, viewType);
} else {
bindHeaderViewHolder(holder, position, viewType);
}
}
private void bindHeaderViewHolder(RecyclerView.ViewHolder holder, int position, ActivityRecyclerViewType viewType) {
int dataIndex = viewType.getDataIndex();
ActivityRecyclerHeaderViewHolder headerViewHolder = (ActivityRecyclerHeaderViewHolder) holder;
headerViewHolder.sectionTitle.setText(activityHeaderList.get(dataIndex));
if (position < ChooseCategoryActivity.allImagesNames.length) {
headerViewHolder.categoryImage.setImageDrawable(context.getResources().getDrawable(ChooseCategoryActivity.allImagesNames[position]));
}
if (isExpanded(position)) {
headerViewHolder.sectionTitle
.setCompoundDrawablesWithIntrinsicBounds(null, null, null/*headerViewHolder.arrowUp*/, null);
} else {
headerViewHolder.sectionTitle
.setCompoundDrawablesWithIntrinsicBounds(null, null, null /*headerViewHolder.arrowDown*/, null);
}
}
private void bindChildViewHolder(RecyclerView.ViewHolder holder, ActivityRecyclerViewType viewType) {
int dataIndex = viewType.getDataIndex();
((ActivityRecyclerChildViewHolder) holder).name.setText(activityChildList.get(dataIndex));
}
@Override
public int getItemCount() {
int count = 0;
if (activityChildList != null && activityHeaderList != null && headerExpandTracker != null) {
viewTypes.clear();
int collapsedCount = 0;
for (int i = 0; i < activityHeaderList.size(); i++) {
viewTypes.put(count, new ActivityRecyclerViewType(i, HEADER_TYPE));
count += 1;
String userType = activityHeaderList.get(i);
int childCount = numberOfChildrenPerParentNameMap.get(userType);
if (headerExpandTracker.get(i) != 0) {
// Expanded State
for (int j = 0; j < childCount; j++) {
viewTypes.put(count, new ActivityRecyclerViewType(count - (i + 1) + collapsedCount, ACTIVITY_TYPE));
count += 1;
}
} else {
// Collapsed
collapsedCount += childCount;
}
}
}
return count;
}
@Override
public int getItemViewType(int position) {
if (viewTypes.get(position).getType() == HEADER_TYPE) {
return HEADER_TYPE;
} else {
return ACTIVITY_TYPE;
}
}
@Override
public void onHeaderClick(int position) {
ActivityRecyclerViewType viewType = viewTypes.get(position);
int dataIndex = viewType.getDataIndex();
String userType = activityHeaderList.get(dataIndex);
int childCount = numberOfChildrenPerParentNameMap.get(userType);
if (headerExpandTracker.get(dataIndex) == 0) {
// Collapsed. Now expand it
headerExpandTracker.put(dataIndex, 1);
notifyItemRangeInserted(position + 1, childCount);
ChooseCategoryActivity.HEADER_EXPANDED_NUMBER = position;
} else {
// Expanded. Now collapse it
headerExpandTracker.put(dataIndex, 0);
notifyItemRangeRemoved(position + 1, childCount);
ChooseCategoryActivity.HEADER_EXPANDED_NUMBER = -1;
}
}
@Override
public boolean isExpanded(int position) {
int dataIndex = viewTypes.get(position).getDataIndex();
return headerExpandTracker.get(dataIndex) == 1;
}
@Override
public void onChildClick(String name) {
if (context instanceof ChooseCategoryActivity) {
((ChooseCategoryActivity) context).finishChoosingActivity(name);
}
}
}
我尝试过使用recyclerView.setHasFixedSize(true)
,
recyclerView.setItemViewCacheSize(20)
,
recyclerView.setDrawingCacheEnabled(true)
,
recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH)
和adapter.setHasStableIds(true)
对性能没有影响。
必要时可以发布其他组件。