【问题标题】:Different "visibility" values in each row in a ListViewListView 中每一行的不同“可见性”值
【发布时间】:2011-04-25 15:05:49
【问题描述】:

我开发了一个非常简单的应用程序,它使用一个自定义适配器用于 ListView。

每一行有两个TextView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView android:id="@+id/text1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium" />
    <TextView android:id="@+id/text2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:visibility="gone" />
</LinearLayout>

第一个 TextView 被命名为“text1”,第二个被命名为“text2”。 如您所见,text2 已隐藏 (visibility="gone")。

此外,该列表的标题仅包含一个 EditText 小部件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <EditText android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

每一行都由一个名为“Item”的非常简单的对象表示,该对象具有 2 个属性(text1 和 text2)及其 getter/setter。此外,它还有一个“hasText2”方法,只检查对象是否具有 text2 属性值的长度 > 0:

public class Item {
    private String text1;
    private String text2;

    public String getText1() {
        return text1;
    }
    public void setText1(String text1) {
        this.text1 = text1;
    }
    public boolean hasText2() {
        return text2.length() > 0;
    }
    public String getText2() {
        return text2;
    }
    public void setText2(String text2) {
        this.text2 = text2;
    }
}

好的,我将在我的主应用文件中仅使用 2 项初始化列表:

Item item1 = new Item();
item1.setText1("Item 1");
item1.setText2("optional 1");
Item item2 = new Item();
item2.setText1("Item 2");
item2.setText2("");

getListView().addHeaderView(getLayoutInflater().inflate(R.layout.list_header, null), false, false);

m_items = new ArrayList<Item>();
m_adapter = new CustomListAdapter(this, R.layout.list_row, m_items);
setListAdapter(m_adapter);

m_items.add(item1);
m_items.add(item2);
m_adapter.notifyDataSetChanged();

这是我的自定义适配器(扩展 ArrayAdapter)的 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);
    }

    // get the two text widgets of this row layout
    TextView text1 = (TextView) convertView.findViewById(R.id.text1);
    TextView text2 = (TextView) convertView.findViewById(R.id.text2);

    // get the Item object of this row
    Item list_item = items.get(position);

    // we set the text1 property of this Item to the text1 widget
    text1.setText(list_item.getText1());

    // if this Item has a text2 (value length > 0), then set it to the text2 widget and make it visible 
    if (list_item.hasText2()) {
        text2.setText(list_item.getText2());
        text2.setVisibility(0);
    }

    return convertView;
}

所以,我想要仅在 Item 对象已定义(值的长度 > 0)时才显示 text2 小部件。

这是应用运行后的结果:

太好了,效果和我预期的一样!! :)

但是如果我点击列表标题的 EditText 会怎样? (所以我强制更新列表):

这里发生了什么?这不可能。第二行没有定义 text2,Android 只是从第一行获取了 text2!为什么??

我能想象的唯一原因是我不能使用具有不同可见性的行......但是,为什么 Android 让我在运行应用程序时这样做?似乎只有在键盘出现时才会失败(列表更新)。

【问题讨论】:

  • 这与回收getView中的视图有关,以及您为getViewTypeCount定义的视图数量和视图类型getItemViewType
  • 所以我必须定义两个行布局?我在哪里可以找到一些说明?我不明白为什么只有在更新列表时才会发生这种情况,而不是在创建列表时发生(第一个屏幕截图)。

标签: android


【解决方案1】:

这有一个问题,原因与我在上一个问题的注释中描述的完全相同。该视图正在被回收,因此在子句if (list_item.hasText2()) { 中执行的定制将永久设置在该视图上;即使再循环到该子句不正确的视图。

在这种情况下,以下修改可能会解决问题:

 if (list_item.hasText2()) {
    text2.setText(list_item.getText2());
    text2.setVisibility(View.VISIBLE);
 } else {
    text2.setVisibility(View.GONE);
 }

【讨论】:

  • 嗨,Jim,感谢您的帮助,是的,这解决了问题,但我不明白为什么“if”的自定义是永久设置的。有这方面的一些文件吗?我找不到任何东西,我很高兴知道这到底是如何工作的...... :)
  • 当您return convertView; 时,系统会返回完全相同的对象,即您创建和自定义的相同对象,但不同 位置,作为public View getView(int position, View convertView, ViewGroup parent) { 的第二个参数,一旦您的原始视图离开屏幕。
  • @JimBlackler 如果您想坚持有效的视图回收,这真的是实现这一目标的唯一方法吗?我有很多条件可以更改行的布局。这意味着,if-block 中的每次更改都需要相应的 else-block 来重置值,以防该行被重用。这变得非常冗长,getView() 方法变得相当混乱。
猜你喜欢
  • 1970-01-01
  • 2015-02-17
  • 1970-01-01
  • 1970-01-01
  • 2015-06-13
  • 2017-06-23
  • 1970-01-01
  • 2019-05-29
  • 2017-07-25
相关资源
最近更新 更多