在 ListView 中修改文本大小时更新项目高度
Posted
技术标签:
【中文标题】在 ListView 中修改文本大小时更新项目高度【英文标题】:Update item height when modifying text size in ListView 【发布时间】:2012-09-24 23:47:26 【问题描述】:我有一个ListView
和一个ArrayAdapter
,它使用类似于simple_list_item_1 的XML 布局来扩充其内容。我在应用程序菜单中有两个选项来增加/减小文本大小。我设法通过覆盖ArrayAdapter
的getView
函数来修改ListView
中TextViews
的文本大小。像这样的:
adapter = new ArrayAdapter<Line>(MyActivity.this, R.layout.line_list, lines)
@Override
public View getView(int position, View convertView, ViewGroup parent)
TextView textView = (TextView) super.getView(position, convertView, parent);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, fontSizeDp + zoom);
return textView;
;
listView.setAdapter(adapter);
菜单选项更改缩放值并调用adapter.notifyDataSetChanged();
以使适配器更改文本大小。
在那之前一切正常。
问题是当我将文本大小减小太多时,每个 TextView 的高度都没有包裹其内容。 也就是说,ListView 项目太高了。当我增加文本大小时,项目高度没有问题。
如果我调用 super.getView(position, convertView, parent);在 convertView 为空的情况下,我使适配器始终膨胀。在这种情况下,由于高度被换行,因此减小文本大小可以正常工作。但是,我导致工作量过大,我不希望这样。
我尝试使列表视图和/或文本视图无效或强制布局,但没有成功。
感谢任何帮助
编辑:这是 line_list 布局:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_
android:layout_
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="@dimen/lineTextSize"
android:gravity="center"
android:paddingLeft="6dip"
android:paddingRight="6dip" />
lineTextSize 默认为 22dp,大为 40dp
编辑 2: 看起来像这样
而不是这个屏幕:
【问题讨论】:
你能发布R.layout.line_list
文件吗?
我之前测试过你的代码,它的工作原理应该是这样,TextView
正在包装TextView
的内容,无论我如何修改大小。在我的测试中,fontSizeDp
是一个常数,比如 17,我只是在onOptionsItemSelected
回调中增加/减少了zoom
变量,然后在适配器上调用notifyDataSetChanged
。怎么修改大小?
是的,就这样。在 onOptionsItemSelected 我更改缩放值,然后调用 adapter.notifyDataSetChanged()。我在平板电脑上测试 fontSizeDp 的初始值为 40。当我在某个点缩小时,线条的高度不再更新并且仍然太高
如果将dp
单位替换为sp
单位(就像您从一开始就应该做的那样)字体大小,您会看到相同的行为吗?
是的,我刚刚测试过,但行为是一样的
【参考方案1】:
我发现 here 这是 Android 3.1+ 的一个已知错误
解决办法是像这样添加一个字符串
String ZERO_WIDTH_SPACE = "\u200b";
到 TextViews 的文本。所以,适配器正确的getView
函数是:
@Override
public View getView(int position, View convertView, ViewGroup parent)
TextView textView = (TextView) super.getView(position, convertView, parent);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, fontSizeDp + zoom);
textView.setText(textView.getText() + ZERO_WIDTH_SPACE);
return textView;
【讨论】:
【参考方案2】:我设法测试了代码,似乎ListView
不想在Honeycomb
及更高版本中更新行高(减小字体大小时)。解决您的问题的一个简单方法是实现适配器的 getView
方法,如果您的字体减少和/或回收的视图不适合当前字体大小,它将重新创建行视图.这是基于您的观察,将 convertView
设置为 null
的强制 super.getView()
方法有效,因为 ListView
将始终从头开始构建新行。我的代码正在做类似的事情,但性能要好得多:
public class CustomAdapter extends ArrayAdapter<String>
private LayoutInflater mInflater;
private int mResource;
public CustomAdapter(Context context, int resource, String[] objects)
super(context, resource, objects);
mInflater = LayoutInflater.from(context);
mResource = resource;
@Override
public View getView(int position, View convertView, ViewGroup parent)
if (convertView == null)
convertView = mInflater.inflate(mResource, parent, false);
else
if (mZoom - mOldZoom < 0)
Integer cacheZoom = (Integer) convertView.getTag();
if (cacheZoom == null || cacheZoom.intValue() != mZoom)
convertView = mInflater.inflate(mResource, parent, false);
convertView.setTag(mZoom);
((TextView) convertView).setTextSize(
TypedValue.COMPLEX_UNIT_DIP, 40 + mZoom);
((TextView) convertView).setText(getItem(position));
return convertView;
mZoom
、mOldZoom
是用于查看字体前进方向的新旧缩放值的变量:
@Override
public boolean onOptionsItemSelected(MenuItem item)
switch (item.getItemId())
case R.id.item1:
mOldZoom = mZoom;
mZoom += 2;
mAdapter.notifyDataSetChanged();
break;
case R.id.item2:
mOldZoom = mZoom;
mZoom -= 2;
mAdapter.notifyDataSetChanged();
break;
return super.onOptionsItemSelected(item);
【讨论】:
什么是 R.layout.adapters_fontchange?如果与 R.layout.line_list 的布局相同,则问题仍然存在(我正在 ICS 上测试)。 @IvanR.layout.adapters_fontchange
是我为您的布局文件命名的(布局相同)。我已经在ICS
上进行了测试,实际上它不起作用,因为我的初始逻辑不正确。我从我的答案中编辑了代码,当我在 2.2 设备和两个模拟器上用Honeycomb
(API 13) + ICS
(API 14) 测试它时,它应该可以工作。看看它的表现。
它有效,谢谢!只有一个错误,但可以通过删除 'if (mZoom != 0)' 来修复,因为如果在 mZoom 为 0 时减少一然后增加一,则未设置大小并且文本行为磨损,因为在文本大小之间发生冲突38 和 40。
@Ivan 你是对的,当我测试时,我在不止一个步骤中增加/减少了字体并且没有注意到它。以上是关于在 ListView 中修改文本大小时更新项目高度的主要内容,如果未能解决你的问题,请参考以下文章
Textview 文本大小应为 editText 文本大小并显示在 listview 中