带有TextEdit标题的ListView搞砸了

时间:2011-04-22 23:38:08

标签: android

我有一个ListView,我添加了一个标题(带有getListView(。addHeaderView),它只包含一个TextEdit小部件。

enter image description here

然后当我点击TextEdit开始写入时,键盘出现并且它弄乱了列表! enter image description here

如果我点击其他地方隐藏键盘,列表会再次混乱!

我不知道为什么会这样。我认为它与onConfigurationChanged方法有关,但在实现它之后(并在清单文件中添加相应的属性)问题仍然存在。

我该如何解决?为什么Android搞砸我的名单?

修改

我的列表使用自定义适配器,这是getView方法:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;

    if (v != null) {
        return v;
    }

    LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    v = vi.inflate(R.layout.list_row, null);

    ListTask list_item = items.get(position);

    if (list_item != null) {
        TextView item_name = (TextView) v.findViewById(R.id.item_name);
        item_name.setText(list_item.getTitle());
    }

    return v;
}

问题不是我的物品的价值,而是他们的订单。当键盘出现时,它们以不同的顺序显示,但值是正确的。

EDIT2:

好的,我已经用rekaszeru的建议改变了我的getView方法,现在它按预期工作了。但是现在我面临另一个问题:如果我的项目有两个文本视图怎么办?

假设第二个textview是可选的,“Item 1”和“Item 3”拥有它,但是“Item 2”没有,所以它被初始化为void String(length == 0)。 第一次显示列表时,它显示带有第二个文本视图的“Item1”和“Item 3”,以及没有它的“Item 2”。那是对的。但是当键盘出现时,“Item 2”将获取另一个项目的第二个textview并显示它!

这是我现在修改过的代码:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        LayoutInflater vi = (LayoutInflater) getContext().
            getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = vi.inflate(R.layout.list_row, null);
    }

    ListTask list_item = items.get(position);

    TextView item_name = (TextView) convertView.findViewById(R.id.item_name);
    TextView item_optional_text = (TextView) convertView.findViewById(R.id.item_optional_text);

    item_name.setText(list_item.getTitle());

    // if the item has defined the optional text, make some room and display it
    if (item_optional_text.isNotEmpty()) {
        LayoutParams layout_params = (LayoutParams) item_name.getLayoutParams();
        layout_params.topMargin = 10;
        layout_params.height = -2;  // -2: wrap_content
        item_name.setLayoutParams(layout_params);
        item_optional_text.setText(list_item.getOptionalText());
    }

    return convertView;
}

isNotEmpty()在Item类中执行此操作:

public boolean isNotEmpty() {
    return this.optional_text.length() > 0;
}

在书面问题中理解它可能太复杂了。如果是这样,我可以制作一个简短的视频来展示问题和我的源代码。在此先感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

你的行回收搞砸了。 Android没有改变项目的顺序,你是。

现在,如果您传递一行进行回收,则无需修改即可将其返回。这是个错误。您应该修改行的内容以反映所提供位置的数据。在这种情况下,您可以跳过的唯一逻辑是膨胀一个全新的行。

Here is a free excerpt来自我的一本经历过所有这些内容的书。

答案 1 :(得分:0)

您应该覆盖getView实现中的ListAdapter方法,并确保始终为要返回的视图分配新值(或者至少始终更新它以包含正确的数据)。

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    convertView = inflater.inflate(R.layout.list_row, parent, false);
    //set the necessary data in your TextViews, Checkboxes, etc...
    return convertView;
}

如果您没有给项目渲染器充气,那么您可以从代码中实例化它,例如:

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
        convertView = new TextView([...]);
        convertView.setText(textBasedOnYourData);
        return convertView;
}

修改
正如@CommonsWare所指出的那样,应该注意回收列表项呈示器。因此,不应每次都实例化它,而应检查它是否已经存在,然后更新基础TextView

所以我建议尝试稍微修改getView实现:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        LayoutInflater vi = (LayoutInflater) getContext().
            getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = vi.inflate(R.layout.list_row, null);
    }

    ListTask list_item = items.get(position);
    TextView item_name = (TextView) convertView.findViewById(R.id.item_name);
    //the item should never be null, but just in case: 
    item_name.setText((list_item == null) ? "" : list_item.getTitle());

    return convertView;
}