Android: 使 Recyclerview 表现得像 LinearLayout
Android: make Recyclerview behave like LinearLayout
我有这样的布局:
<LinearLayout>
<TextView/>
<LinearLayout> <-- needs to be a dynamic list
<JohnDoeView/>
<JohnDoeView/>
</LinearLayout>
<TextView/>
<LinearLayout> <-- needs to be a another dynamic list
<JohnDoeView/>
<JohnDoeView/>
<JohnDoeView/>
</LinearLayout>
</LinearLayout>
这会产生下图,我可以一起滚动 WHOLE 布局。
但是当我尝试用 RecyclerView
替换那些 LinearLayout
时,我得到 两个 单独的滚动区域,就像两个固定的滚动框独立.
<LinearLayout>
<TextView/>
<RecyclerView/>
<TextView/>
<RecyclerView/>
</LinearLayout>
如何获得与 LinearLayout
相同的效果,但具有 Dynamic 内容??
我看到两个解决方案。
- 将整个布局插入
ScrollView
。
- 使用单个
RecyclerView
.
解决方案 1
为此,您需要使 RecyclerView
包装其内容。遗憾的是,您不能只输入 android:layout_height="wrap_content"
,因为 RecyclerView
不支持它。幸运的是,有定制的解决方案。我一直在用,效果很好。
例如,有 this 自定义 LinearLayoutManager
,您可以将其分配给两个 RecyclerView
。只需按照我链接的页面中的说明进行操作即可。
解决方案 2
您可以使用一个 RecyclerView
。这可能需要更努力的工作,因为您必须:
- 将您的适配器合并为一个;
- 将您的分隔符分配到某个位置(
TextView
、Switch
或其他)。
这当然是可能的,只需看一下 RecyclerView
上有多个子类型的(许多)示例之一。
LinearLayout
可以处理动态变化。如果您使用 android:animateLayoutChanges
属性,它甚至可以为它们设置动画。 ListView
或 Recycler
当项目数量很大时(即远远超过屏幕可以显示的数量)很有趣,以避免有很多不可见的视图。
如果你真的想使用一个 RecyclerView
你可以只使用一个,多个 view types,例如一份用于 TextView
,一份用于 JohnDoeView
尝试使用这种布局结构,
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
您不需要嵌套 RecyclerView
或 ListView
或任何其他滚动视图。您只需要外部视图是 RecyclerView
。内部列表可以通过非常简单的 ListLayout
class 进行管理,每个子列表都有一个适配器。
public class ListLayout extends LinearLayout {
private Adapter mAdapter;
private Observer mObserver = new Observer();
public ListLayout(Context context) {
super(context);
}
public ListLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public Adapter getAdapter()
{
return mAdapter;
}
public void setAdapter(Adapter adapter) {
if (mAdapter != null)
mAdapter.unregisterDataSetObserver(mObserver);
mAdapter = adapter;
adapter.registerDataSetObserver(mObserver);
mObserver.onChanged();
}
private class Observer extends DataSetObserver {
@Override
public void onChanged() {
final List<View> oldViews = new ArrayList<View>(getChildCount());
for (int i = 0; i < getChildCount(); i++)
oldViews.add(getChildAt(i));
final Iterator<View> iter = oldViews.iterator();
removeAllViews();
for (int i = 0; i < mAdapter.getCount(); i++) {
View convertView = iter.hasNext() ? iter.next() : null;
View newView = mAdapter.getView(i, convertView, ListLayout.this);
addView(newView);
}
super.onChanged();
}
@Override
public void onInvalidated() {
removeAllViews();
super.onInvalidated();
}
}
}
我有这样的布局:
<LinearLayout>
<TextView/>
<LinearLayout> <-- needs to be a dynamic list
<JohnDoeView/>
<JohnDoeView/>
</LinearLayout>
<TextView/>
<LinearLayout> <-- needs to be a another dynamic list
<JohnDoeView/>
<JohnDoeView/>
<JohnDoeView/>
</LinearLayout>
</LinearLayout>
这会产生下图,我可以一起滚动 WHOLE 布局。
但是当我尝试用 RecyclerView
替换那些 LinearLayout
时,我得到 两个 单独的滚动区域,就像两个固定的滚动框独立.
<LinearLayout>
<TextView/>
<RecyclerView/>
<TextView/>
<RecyclerView/>
</LinearLayout>
如何获得与 LinearLayout
相同的效果,但具有 Dynamic 内容??
我看到两个解决方案。
- 将整个布局插入
ScrollView
。 - 使用单个
RecyclerView
.
解决方案 1
为此,您需要使 RecyclerView
包装其内容。遗憾的是,您不能只输入 android:layout_height="wrap_content"
,因为 RecyclerView
不支持它。幸运的是,有定制的解决方案。我一直在用,效果很好。
例如,有 this 自定义 LinearLayoutManager
,您可以将其分配给两个 RecyclerView
。只需按照我链接的页面中的说明进行操作即可。
解决方案 2
您可以使用一个 RecyclerView
。这可能需要更努力的工作,因为您必须:
- 将您的适配器合并为一个;
- 将您的分隔符分配到某个位置(
TextView
、Switch
或其他)。
这当然是可能的,只需看一下 RecyclerView
上有多个子类型的(许多)示例之一。
LinearLayout
可以处理动态变化。如果您使用 android:animateLayoutChanges
属性,它甚至可以为它们设置动画。 ListView
或 Recycler
当项目数量很大时(即远远超过屏幕可以显示的数量)很有趣,以避免有很多不可见的视图。
如果你真的想使用一个 RecyclerView
你可以只使用一个,多个 view types,例如一份用于 TextView
,一份用于 JohnDoeView
尝试使用这种布局结构,
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
您不需要嵌套 RecyclerView
或 ListView
或任何其他滚动视图。您只需要外部视图是 RecyclerView
。内部列表可以通过非常简单的 ListLayout
class 进行管理,每个子列表都有一个适配器。
public class ListLayout extends LinearLayout {
private Adapter mAdapter;
private Observer mObserver = new Observer();
public ListLayout(Context context) {
super(context);
}
public ListLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public Adapter getAdapter()
{
return mAdapter;
}
public void setAdapter(Adapter adapter) {
if (mAdapter != null)
mAdapter.unregisterDataSetObserver(mObserver);
mAdapter = adapter;
adapter.registerDataSetObserver(mObserver);
mObserver.onChanged();
}
private class Observer extends DataSetObserver {
@Override
public void onChanged() {
final List<View> oldViews = new ArrayList<View>(getChildCount());
for (int i = 0; i < getChildCount(); i++)
oldViews.add(getChildAt(i));
final Iterator<View> iter = oldViews.iterator();
removeAllViews();
for (int i = 0; i < mAdapter.getCount(); i++) {
View convertView = iter.hasNext() ? iter.next() : null;
View newView = mAdapter.getView(i, convertView, ListLayout.this);
addView(newView);
}
super.onChanged();
}
@Override
public void onInvalidated() {
removeAllViews();
super.onInvalidated();
}
}
}