包装在 HorizontalScrollView 中的 Android Listview 高度不正确,其中列表项的高度不同
Posted
技术标签:
【中文标题】包装在 HorizontalScrollView 中的 Android Listview 高度不正确,其中列表项的高度不同【英文标题】:Incorrect height of Android Listview wrapped in HorizontalScrollView where list items have varying height 【发布时间】:2015-02-06 21:49:42 【问题描述】:我有一个 ListView 包装在 HorizontalScrollView 中,其中列表项视图根据内容具有不同的高度。列表项布局如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:baselineAligned="false"
android:orientation="horizontal"
android:weightSum="1" >
<LinearLayout
android:layout_
android:layout_
android:layout_weight=".5"
android:minHeight="50dp"
android:orientation="vertical" >
<LinearLayout
android:layout_
android:layout_ >
<TextView
android:id="@+id/nextStopType"
android:layout_
android:layout_
android:gravity="center"
android:text="P"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/dohrn_orange" />
<TextView
android:id="@+id/nextStopName"
android:layout_
android:layout_
android:gravity="center_vertical"
android:maxLines="2"
android:text="Customer Name"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
<TextView
android:id="@+id/nextstopAddress"
android:layout_
android:layout_
android:minLines="2"
android:paddingLeft="20dp"
android:text="Address"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<LinearLayout
android:layout_
android:layout_
android:layout_weight=".3"
android:orientation="vertical" >
<TextView
android:id="@+id/nextStopCount"
android:layout_
android:layout_
android:minWidth="@dimen/nextStopDetailsWidth"
android:text="Stop Count"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/nextStopTimes"
android:layout_
android:layout_
android:hint="?android:attr/textAppearanceSmall"
android:text="Open/Close Times"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/nextStopContact"
android:layout_
android:layout_
android:text="Contact Number"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<LinearLayout
android:layout_
android:layout_
android:layout_gravity="right"
android:layout_weight=".2"
android:gravity="right" >
<TextView
android:id="@+id/nextStopPieces"
android:layout_
android:layout_
android:gravity="right"
android:minWidth="@dimen/nextStopPiecesWidth"
android:text="HUs"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/nextStopWeight"
android:layout_
android:layout_
android:gravity="right"
android:minWidth="@dimen/nextStopWeightWidth"
android:text="Weight"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</LinearLayout>
如果 nextStopName 是单行,一切都很好,但如果它换成两行,则列表的高度计算错误。如果我查看 DDMS 中的视图层次结构,ListView 的高度是 111 像素,但包含列表项的 LinearLayout 的高度是 122 像素,这是包含 nextStopType 和 nextStopName 的 LinearLayout 的高度。 111 实际上是包含 nextStopCount 等的第二个 LinearLayout 的高度。人。
基本上,每当 nextStopName 换行时,我都会收到此错误。
下面是可以看到效果的屏幕截图。
下面是这个屏幕的布局。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical" >
<HorizontalScrollView
android:layout_
android:layout_
android:fillViewport="true"
android:layout_weight="1" >
<LinearLayout
android:layout_
android:layout_
android:orientation="vertical" >
<LinearLayout
android:layout_
android:layout_
android:orientation="horizontal" >
<TextView
android:layout_
android:layout_
android:layout_weight=".5"
android:gravity="center_vertical"
android:maxLines="2"
android:minWidth="@dimen/nextStopAddressWidth"
android:text="Customer Name & Address"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:layout_
android:layout_
android:layout_weight=".3"
android:hint="?android:attr/textAppearanceMedium"
android:minWidth="@dimen/nextStopDetailsWidth"
android:text="Details"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
android:layout_
android:layout_
android:layout_gravity="center_vertical"
android:layout_weight=".2"
android:gravity="right" >
<TextView
android:layout_
android:layout_
android:layout_gravity="center_vertical"
android:gravity="right"
android:minWidth="@dimen/nextStopPiecesWidth"
android:text="HUs"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:layout_
android:layout_
android:layout_gravity="center_vertical"
android:gravity="right"
android:minWidth="@dimen/nextStopWeightWidth"
android:text="Weight"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</LinearLayout>
<ListView
android:id="@android:id/list"
android:layout_
android:layout_
android:layout_weight="1" >
</ListView>
</LinearLayout>
</HorizontalScrollView>
<LinearLayout
android:id="@android:id/empty"
android:layout_
android:layout_
android:layout_weight="0"
android:orientation="vertical" >
<TextView
android:layout_
android:layout_
android:layout_marginTop="@dimen/eolMargin"
android:gravity="center"
android:text="Waiting For Stops"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="@+id/logoutButton"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/eolMargin"
android:text="Logout"
android:textAppearance="?android:attr/textAppearanceButton" />
</LinearLayout>
适配器的相关部分很简单。
public View getView(int position, View convertView, ViewGroup parent)
View row = convertView;
if (row == null)
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(rowLayout, parent, false);
StopItem stopItem = getItem(position);
TextView pdFlag = (TextView) row.findViewById(R.id.nextStopType);
pdFlag.setText(stopItem.getType());
if (isCurrentDestination(stopItem))
pdFlag.setTextColor(Color.GREEN);
else
pdFlag.setTextColor(DOHRN_ORANGE);
TextView name = (TextView) row.findViewById(R.id.nextStopName);
name.setText(stopItem.getCustomerName());
TextView address = (TextView) row.findViewById(R.id.nextstopAddress);
address.setText(stopItem.getAddress());
TextView stopCount = (TextView)row.findViewById(R.id.nextStopCount);
stopCount.setText(stopItem.getStopCount() );
TextView timesView = (TextView)row.findViewById(R.id.nextStopTimes);
String times = stopItem.getTimes("\n");
if (times.length() == 0)
timesView.setVisibility(View.GONE);
else
timesView.setText(times);
TextView phoneView = (TextView)row.findViewById(R.id.nextStopContact);
String phoneNumber = stopItem.getFormattedPhoneNumber();
if (phoneNumber.length() == 0)
phoneView.setVisibility(View.GONE);
else
phoneView.setText(phoneNumber);
TextView pieceCount = (TextView)row.findViewById(R.id.nextStopPieces);
pieceCount.setText(stopItem.getPieceCount());
TextView weight = (TextView)row.findViewById(R.id.nextStopWeight);
weight.setText(stopItem.getWeight());
return row;
我在布局上尝试了许多变体,结果都一样。奇怪的是,应用程序中还有其他 ListViews 具有不同高度的项目,它们工作正常,但它们既没有包裹在 HorizontalScroll View 中,也没有那么复杂的项目布局。
【问题讨论】:
如果你能缩小这个问题的范围,和/或发布一个重现这个问题的示例项目,我会很感兴趣。 【参考方案1】:每次getView()
调用时,您必须使用getView()
中的newLayoutParams
和requestLayout()
方法调整ScrollView
的高度。
当其中一个没有固定大小时,2 个或更多 AbsView
不能同时保持彼此。
【讨论】:
我不确定我是否理解这一点。首先,HorizontalScrollView 是 FrameLayout 而不是 AbstractListView,因此根布局中没有 2 个“AbsViews”。您是否建议使用不同的布局参数在 getView 内部的 HorizontalScrollView 上调用 requestLayout,如果是,您有什么建议?我可能弄错了,如果您草拟出您想到的代码可能会有所帮助。 更多细节:如上所述,ListVew 的高度不正确。该高度传播到 HorizontalScrollView 的高度。即使您通过对列表中项目的高度求和来计算 ListView 的高度,计算出的高度也是不正确的(111 像素)。就好像项目上的 View.measure 将项目视为未包装 nextStopName 一样。在具有正确高度(122 像素)的 ListView 上调用 requestLayout 可以解决问题,但是如何获得正确的项目高度? 您的商品必须具有固定尺寸。或者您的 ListView 高度必须是固定的。 是的,我已经尝试过了,当然它确实解决了问题。问题是:“为什么包含 nextStopName 的 TextView 上的 View.measure 返回高度,就好像 nextStopName 是一行一样?”然而,在绘制 TextView 时,它必须知道宽度并正确推断 nextStopName 必须被包装。所以测量阶段得到一个答案,而绘图阶段得到另一个答案。多么奇怪。就这个应用程序而言,我将不得不为列表项使用 2 种布局,一种用于窄屏,一种用于宽屏。【参考方案2】:我最终为不同的屏幕尺寸使用了不同的布局。对于小屏幕(默认),布局使用 HorizontalScrollView,但列表项元素的宽度具有固定宽度,如上所述。对于较大的屏幕,没有 HorizontalScrollView,列表项宽度为全屏,列表项元素的宽度由权重决定。像魅力一样工作。
我被以下建议误导了:使用 HorizontalScrollView 所要做的就是将现有布局包装在单个线性布局中,然后将其包装在 HorizontalScrollView 中。以上只是说明了这些简单的建议并不是故事的全部。
【讨论】:
以上是关于包装在 HorizontalScrollView 中的 Android Listview 高度不正确,其中列表项的高度不同的主要内容,如果未能解决你的问题,请参考以下文章
TextBlock 不包装 Silverlight 应用程序
Android:以编程方式添加Textview,而不是将文本包装到下一行
如何在Blackberry中动态增加horizo ntalfieldmanager高度?
在 HorizontalHeaderView 中显示列标题
HorizontalScrollView 以编程方式滚动而没有焦点
android - 为啥在 HorizontalPager.OnScrollListener() 接口中多次调用 onViewScrollFinished