android - RecyclerView 中的动态线性布局
问题描述
我有一个带有卡片的 RecyclerView,如下所示:
<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/cv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
card_view:cardPreventCornerOverlap="false"
card_view:cardCornerRadius="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="48dp">
<TextView
android:id="@+id/fragment_acts_list_item_header"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@android:color/holo_red_dark"
android:gravity="center_vertical"
android:maxLines="1"
android:padding="10dp"
android:text="Header text"
android:textColor="@android:color/white"
android:textSize="20sp" />
<!--My dropdown Button -->
<RelativeLayout
android:id="@+id/button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:layout_gravity="end"
android:gravity="center">
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentEnd="false"
android:background="@drawable/ic_collapse_act" />
</RelativeLayout>
</RelativeLayout>
<!-- Contains items that are visible without expanding -->
<LinearLayout
android:id="@+id/fragment_acts_list_visible_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
/>
<!-- Contains items that are visible after expanding -->
<LinearLayout
android:id="@+id/fragment_acts_list_expandable_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:orientation="horizontal" />
</LinearLayout>
</android.support.v7.widget.CardView>
我从 API 获得了两张地图:首先包含要在屏幕上一直显示的元素(必须添加到上面代码中的fragment_acts_list_visible_layout),其他包含在用户单击展开按钮时必须显示的元素(上面代码中的按钮,必须添加到上面代码中的fragment_acts_list_expandable_layout中)。
我想用上面的布局表示两个地图的每个地图条目:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="10">
<TextView
android:id="@+id/act_row_field_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="7"
android:textAlignment="center" />
<TextView
android:id="@+id/act_row_field_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="3"
android:textAlignment="center" />
</LinearLayout>
如何以正确的方式做到这一点?
使用诸如viewHolder.visibleLayout.addView(row);
inonBindViewHolder
方法之类的代码会给我重复的可见元素和错误的可扩展布局高度,因为这就是 RecyclerView 的onBindViewHolder
工作方式(多次调用,每次调用都添加我的行)。
UPD:这是我的 bindViewHolder 方法:
@Override
public void onBindViewHolder(@NonNull final ExpandableRecyclerAdapter.ViewHolder viewHolder,
int i) {
viewHolder.setIsRecyclable(false);
Act act = acts.get(i);
ActToDisplay visibleSettings = formatActFields(act, viewSettings);
for (Map.Entry<String, String> entry : visibleSettings.getVisibleFields().entrySet()) {
LinearLayout row = (LinearLayout) LayoutInflater.from(context)
.inflate(R.layout.act_row, viewHolder.visibleLayout, false);
TextView fieldName = row.findViewById(R.id.act_row_field_name);
TextView fieldValue = row.findViewById(R.id.act_row_field_value);
fieldName.setText(entry.getKey());
fieldValue.setText(entry.getValue());
viewHolder.visibleLayout.addView(row);
}
for (Map.Entry<String, String> entry : visibleSettings.getInvisibleFields()
.entrySet()) {
LinearLayout row = (LinearLayout) LayoutInflater.from(context)
.inflate(R.layout.act_row, viewHolder.expandableLayout, false);
TextView fieldName = row.findViewById(R.id.act_row_field_name);
TextView fieldValue = row.findViewById(R.id.act_row_field_value);
fieldName.setText(entry.getKey());
fieldValue.setText(entry.getValue());
viewHolder.expandableLayout.addView(row);
}
//check if view is expanded
final boolean isExpanded = expandState.get(i);
viewHolder.expandableLayout.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
viewHolder.buttonLayout.setRotation(expandState.get(i) ? 180f : 0f);
viewHolder.buttonLayout.setOnClickListener(v -> onClickButton(viewHolder.expandableLayout, viewHolder.buttonLayout, i));
}
UPD2:
通过添加.removeAllViews() in both visible and invisible layouts in
onViewRecycled` 方法解决,但第二个问题没有消失 - 可扩展布局高度太大。
这是来自模拟器的屏幕,在单击展开后必须显示 1 个可见元素和另外一个。为什么这张卡那么大(好像把 wrap_content 算错了)?
UPD3: 可扩展布局高度的问题是我的错误 - 我已将可扩展布局方向设置为水平而不是垂直
感谢@AbuYousuf 和@pskink
解决方案
RecyclerView
重用现有视图。当您滚动时,RecyclerView
使用现有视图来显示其项目。所以清除之前添加的所有视图visibleLayout
。
viewHolder.visibleLayout.removeAllViews();
for (Map.Entry<String, String> entry : visibleSettings.getVisibleFields().entrySet()) {
LinearLayout row = (LinearLayout) LayoutInflater.from(context)
.inflate(R.layout.act_row, viewHolder.visibleLayout, false);
TextView fieldName = row.findViewById(R.id.act_row_field_name);
TextView fieldValue = row.findViewById(R.id.act_row_field_value);
fieldName.setText(entry.getKey());
fieldValue.setText(entry.getValue());
viewHolder.visibleLayout.addView(row);
}
并expandableLayout
在添加之前删除视图。
推荐阅读
- oracle - 如何增加 Oracle SQL Developer 18.1 的 GUI/字体/所有内容的大小
- python - 检查字典的变化
- python-3.x - 无法通过 Python 脚本在文本文件中写入数据
- git - 同步连接到两个远程服务器的两个本地 git 存储库
- vba - 是否有“释放”引用的 VBA 方法也会立即删除 ldb(锁定文件)?
- jquery - 传递参数的最佳方式(非常简单的 jquery/html)
- css - 媒体查询未应用于任何屏幕尺寸
- javascript - GS 中的输出准确,但在复制粘贴到任何文本编辑器时会在输出中添加多个引号
- css - 汉堡菜单按钮显示复选框
- php - Blade - 将变量打印到变量中