0

すべてのリストビュー行に適用されるカスタム行を定義する XML ファイルで宣言された Linearlayout に、1 つの TextView をプログラムで追加したいと考えています。これを行うために、次のコードがあります。

<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 を追加し、それ以外の場合はいくつかの ImageView を追加することです。そのため、XML ファイルで宣言できません。

これを適切に行うには、複数のレイアウトを使用する必要があります。行のレイアウトでビューを追加および削除すると、コストがかかり遅くなる可能性があるためです。XML または Java でさまざまなレイアウトを作成できますが、アダプターでオーバーライドgetViewTypeCount()getItemViewType()て、アダプターに複数のレイアウトと各行に使用するレイアウトを期待するように指示する必要があります。

とても簡単です。私はこの例を以下に書きました: Reusing views in Android Listview with 2 different layouts


オリジナル

ただし、TextView はすべての行に複数回表示されます。私は何を間違っていますか?

ListView が行をリサイクルする方法を説明できませんでした。これは、 Turbo-Charge Your UIなどの Google I/O プレゼンテーションで詳しく説明されています。

おそらく、追加の TextView を行の XML レイアウトに単純に追加するか、複数のレイアウトを使用する必要があります。TextView を追加する理由を説明していないため、決定的なアドバイスを提供することは困難です。


これにより、各行に TextView が 1 つだけ追加されます。

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は、OSがビューをレンダリングするたびに呼び出されます。これは、リストビューが行の内容を要求するたびに、新しいビューを追加していることを意味します。

convertViewがnullでない場合にのみビューを追加するように切り替えると、目的の結果が得られます。

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

ちなみに、R.layout.rowにtextviewを追加することで、textviewを動的に追加する必要をなくすことができます。

于 2013-03-05T15:48:44.593 に答える
0

nullTextViewかどうかに関係なく、追加していることに気付きました。convertViewこれは、1つの行に複数の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 に答える
0

TextView を無条件に追加しているようですね。

問題は、追加する必要がある単一の行をどのように特定できるかです。多分positionパラメータによって?あなただけが知っています。

于 2013-03-05T15:43:38.767 に答える