Android 带有文本编辑标题的ListView出错

Android 带有文本编辑标题的ListView出错,android,Android,我有一个ListView,并且添加了一个头(带有getListView().addHeaderView),它只包含一个TextEdit小部件 然后当我点击文本编辑开始写的时候,键盘出现了,它把列表搞乱了! 如果我点击其他地方隐藏键盘,列表会再次出错 我不知道为什么会这样。我认为这与onConfigurationChanged方法有关,但在实现它(并在清单文件中添加相应的属性)之后,问题仍然存在 我怎样才能修好它?为什么Android会把我的列表搞砸 编辑: 我的列表使用自定义适配器,这是ge

我有一个ListView,并且添加了一个头(带有getListView().addHeaderView),它只包含一个TextEdit小部件

然后当我点击文本编辑开始写的时候,键盘出现了,它把列表搞乱了!

如果我点击其他地方隐藏键盘,列表会再次出错

我不知道为什么会这样。我认为这与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”没有,因此它被初始化为一个空字符串(长度==0)。 第一次显示列表时,它会显示带有第二个文本视图的“Item1”和“Item3”,以及不带文本视图的“Item2”。没错。但当键盘出现时,“项目2”将获取另一个项目的第二个文本视图并显示它

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

@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;
}

也许这太复杂了,无法用书面问题来理解。如果是这样,我可以制作一个简短的视频,显示问题和我的源代码。提前感谢大家的帮助。

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

如果不膨胀项目渲染器,则可以从代码中实例化它,如:

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
        convertView = new TextView([...]);
        convertView.setText(textBasedOnYourData);
        return convertView;
}
编辑
正如@commonware所指出的,应该注意列表项渲染器的回收。因此,与其每次都实例化它,不如检查它是否已经存在,然后更新底层的
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;
}

你那排垃圾回收站搞砸了。Android不会改变物品的顺序,你会的

现在,如果向您传递了要回收的行,那么您将返回该行而不进行修改。这是一个错误。您应该修改行的内容以反映所提供位置的数据。在这种情况下,唯一可以跳过的逻辑是将一个全新的行充气


如果EditText不是列表的标题视图,这种情况还会发生吗?问题很可能是适配器和行的循环使用。假设您使用的是自定义适配器实现,请临时替换普通适配器(例如,如果您正在子类化ArrayAdapter)。如果问题消失了,肯定是自定义适配器的行回收逻辑造成的。@Commonware:是的,我使用自定义适配器,我已经用getView方法的内容编辑了我的问题。为什么Android会改变我物品的顺序?@rekaszeru:别忘了OP需要注意
convertView
参数,以便行回收。我不知道该怎么办。。。我的物品的价值没有改变,只是改变了它们的顺序。我已经用GETVIEW方法的内容向我的问题添加了更多的信息。请看我的更新,并考虑试一试。无论项目的数据是否已更改,每次需要重新绘制布局时都会调用此方法。稍微修改的
getView
与OPs有相同的问题-您不应该检查
如果(list\u item!=null)
-您应该每次都设置文本。如果
list\u item
为空,则您可能希望将该项的文本更改为
no item
或其他内容-但每次调用
getView
时,您都需要更新行用户界面。您是对的,如果
convertView
不为空,我就太注重不要立即返回它,我通过了剩下的代码。不过更新了,以我写的方法为借口。好的,我会看看你的摘录,虽然我不明白你的答案。我的行根本没有被修改…@David:如果视图不为null,则返回该视图,因此您没有将任何文本设置到
TextView
@David:2视图回收的简单规则:1)仅当
convertView
为null时充气,否则重新使用
convertView
;2)每次调用
getView
时更新视图。因此,如果
list\u item
为空,则应将文本设置为“No item”,否则该行将显示以前的文本。@David:
getView()
被多次调用,即使是您认为以前调用过的行。由于滚动或其他使
列表视图“无效”的事件而发生。因此,正如@Joseph Earl所指出的,每次调用
getView()
时都必须填充行。如果有行需要回收,您可以跳过的唯一一步是增加行数。@commonware&@Joseph:谢谢您的澄清,现在我更了解了:)不过,我面临一个新的相关问题,我已经更新了我的问题。。。我试着运用我从你那里学到的知识来解决它,但我现在无法注意到问题在哪里。。。
@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;
}