0

我想以编程方式将一个 TextView 添加到 XML 文件中声明的 Linearlayout 中,该文件定义了应用于所有列表视图行的自定义行。为了做到这一点,我有以下代码:

<LinearLayout
    android:id="@+id/zv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignTop="@+id/title"
    android:layout_marginBottom="1dip"
    android:layout_marginLeft="5dip"
    android:layout_marginRight="5dip"
    android:orientation="vertical"
    android:padding="1dip" >
</LinearLayout>

class ListViewAdapter extends BaseAdapter {

(...)
public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;
        if (convertView == null)
            vi = inflater.inflate(R.layout.row, null);

        TextView tv_nz = new TextView(activity.getApplicationContext());

        LinearLayout zv = (LinearLayout)vi.findViewById(R.id.zv);

        tv_nz.setText("testing...");
        zv.addView(tv_nz);
(...)

return vi;
}

但是,TextView 在每一行中出现不止一次。我究竟做错了什么?谢谢

4

6 回答 6

5

我真正想做的是在某些条件下添加一个 Textview 和一些 ImageViews 否则我不能在 XML 文件中声明它。

您应该使用多个布局来正确执行此操作,因为在一行布局中添加和删除视图可能既昂贵又缓慢。您可以在 XML 或 Java 中创建不同的布局,但在您的适配器中,您必须覆盖getViewTypeCount()getItemViewType()告诉适配器期望多个布局以及每一行使用哪种布局。

这很简单,我写了一个例子:Reusing views in Android Listview with 2 different layouts


原来的

但是,TextView 在每一行中出现不止一次。我究竟做错了什么?

您未能考虑 ListView 回收其行的方式。这在 Google I/O 演示文稿(例如Turbo-Charge Your UI )中有详细说明。

也许您应该简单地将额外的 TextView 添加到行的 XML 布局或使用多个布局。由于您没有解释为什么要添加 TextView,因此很难给您明确的建议。


这只会为每一行添加一个 TextView:

public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        // Code here only affects new rows
        convertView = inflater.inflate(R.layout.row, null);

        TextView tv_nz = new TextView(activity.getApplicationContext());
        tv_nz.setText("testing...");
        convertView.addView(tv_nz);
    }
    else {
        // Code here affects only recycled rows
    }

    // Code here affects every row when the ListView is scrolled
    return convertView;
}
于 2013-03-05T15:43:25.343 回答
1

每次操作系统想要渲染视图时都会调用 getView。这意味着每次列表视图询问行的内容时,您都在添加一个新视图。

如果您切换到仅在 convertView 不为空时添加视图,您将实现您想要的。

public View getView(int position, View convertView, ViewGroup parent) {
    TextView tv_nz;

    // If the row does not exist, lets create it.
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.row, null); 

        // Add the text view to the new view
        tv_nz = new TextView(activity.getApplicationContext());
        tv_nz.setId(R.id.tv_nz);

        convertView.addView(tv_nz);
    } else {
        // The row already exists, lets find the TextView
        tv_nz = (TextView) findViewById(R.id.tv_nz);
    }

    if (tv_nz != null) {
        tv_nz.setText("testing...");
    }

    return convertView;
}

顺便说一句,您可以通过将 textview 添加到 R.layout.row 来消除动态添加 textview 的需要

于 2013-03-05T15:48:44.593 回答
0

您似乎无条件添加 TextView ,对吗?

问题是,如何识别必须添加的单行。也许通过position参数?只有你知道。

于 2013-03-05T15:43:38.767 回答
0

我注意到您正在添加 aTextView无论是否convertView为空。这可以解释这样一个事实,即任何一行中可能有多TextView个小部件。

但是,我确实同意以前的答案——可能有更好的方法来完成你需要的东西。

于 2013-03-05T15:48:12.103 回答
0

我的猜测是,当视图被回收时,它已经添加了 TextView,因此当您添加另一个视图时,您不会检查是否已经从前一个视图中添加了一个。这样的事情应该会有所帮助:

//after your view inflation
LinearLayout zv = (LinearLayout)vi.findViewById(R.id.zv);
TextView tv_nz;
if(zv.getChildCount() == 0) {
    tv_nz = new TextView(activity.getApplicationContext());
    zv.addView(tv_nz);
} else
    tv_nz = (TextView) zv.getChildAt(0);
tv_nz.setText("testing...");
于 2013-03-05T15:48:40.163 回答
0

这是给您的示例代码。首先,您必须决定将数据发送到适配器的格式。在我的代码中,我将它作为数组列表发送。

public class CustomArrayAdapter extends ArrayAdapter<String>
{
    ArrayList<String> list;
    Context mContext; // ADD THIS to keep a context

public CustomArrayAdapter(Context context, int textViewResourceId,
        ArrayList<String> objects)
{
    super(context, textViewResourceId, objects);
    this.mContext = context;
    // Pass the elements in the list
    list = objects;
}

只有在您拥有特定的数据顺序(如“列表”)之后,您才能在列表视图中逐行迭代数据。

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

    if (row == null)
    {

        // get reference to the activity
        LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();

        // Inflate the custom text which will replace the default text view
        //list_item is a simple lineer layout which contain textView1 in it. 
        row = inflater.inflate(R.layout.list_item, parent, false);
    }

    // Create custom text view to customize

    TextView tv = (TextView) row.findViewById(R.id.textView1);

    // TextView can be customized here or in the xml file
    tv.setText(list.get(position));

    return row;

  }
}

最后,您可以像这样调用自定义适配器;

 CustomArrayAdapter adapter = new CustomArrayAdapter(getActivity(),
            R.id.textView1,values);
于 2013-03-05T16:01:38.607 回答