web-dev-qa-db-ja.com

膨らませたレイアウト内で同じIDを持つレイアウトの複数のインスタンスを膨らませる方法

多くのネストされたLinearLayoutsとTextViewssを持つLinearLayoutがあります

私の主な活動は、メインのLinearLayoutを膨らませます。

次に、サーバーからデータをロードし、受信したデータに基づいて、プレースホルダーに複数のレイアウトを追加します(LinearLayout)

これは単純なニュースページで、ニュースに関連付けられた画像を読み込み、最初は空のLinearLayout内に配置します。

各画像には次の情報があります:Title(TextView)、Date(TextView)、Image(ImageView)なので、実際に行うことは次のとおりです。

* これは、すべてのtry-> catch ... if/else .... etcを要素化した質問でコーディングされた必須の要素にすぎないことに注意してください

public void addImages(JSONArray images){
      ViewGroup vg = (ViewGroup) findViewById(R.id.imagesPlaceHolder);


      // loop on images
      for(int i =0;i<images.length;i++){

          View v = getLayoutInflater().inflate(R.layout.image_preview,vg);
          // then 
          I think that here is the problem 
          ImageView imv = (ImageView) v.findViewById(R.id.imagePreview);
          TextView dt = (TextView) v.findViewById(R.id.dateHolder);
          TextView ttl = (TextView) v.findViewById(R.id.title);
          // then 
          dt.setText("blablabla");
          ttl.setText("another blablabla");
          // I think the problem is here too, since it's referring to a single image
          imv.setTag( images.getJSONObject(i).getString("image_path").toString() );
          // then Image Loader From Server or Cache to the Image View

      }
}

上記のコードは、単一の画像に適しています

しかし、複数の画像の場合、イメージローダーは機能しません。これは、すべてのImageView(複数回インフレート)が同じIDを持っているためだと思います。

24
Shehabic

レイアウトXMLのImageViewにIDが必要な理由はありますか? image_preview.xmlレイアウトからAndroid:id属性を消去してから、膨張したLinearLayoutの子を単純に反復処理できますか?例えば:

ViewGroup v = (ViewGroup)getLayoutInflater().inflate(R.layout.image_preview,vg);
ImageView imv = (ImageView) v.getChildAt(0);    
TextView dt = (TextView) v.getChildAt(1);
TextView ttl = (TextView) v.getChildAt(2);
9
user697495

親として使用するViewGroupを指定すると、inflate()によって返されるビューはこの親(この場合はvg)であり、新しく作成されたビューではありません。したがって、vは新しく作成されたビューではなくViewGroupvgを指し、すべての子は同じid、同じサブビュー(imvdtttl)が毎回返されます。

2つの解決策。 1つ目は、それらを使い終わった直後、次の反復の前に、それらのidを変更することです。したがって、次の反復の開始時の次の作成時に、新しく作成されたビューは、Rで定義された古い定数を引き続き使用するため、古いビューとは異なるIDを持ちます。

もう1つの解決策は、inflate()の呼び出しにパラメーターfalseを追加して、新しく作成されたビューがViewGroupにアタッチされず、ViewGroupではなくinflate()関数によって返されるようにすることです。コードの残りの部分は、反復の最後にViewGroupにアタッチする必要があることを除いて、出席したとおりに機能します。

LayoutParamsの値を決定するために使用されるため、ViewGroupを提供する必要があることに注意してください。

33
SylvainL

私は同じ問題を抱えていました、そして@SylvainLからの答えに基づいて、ここに実用的な解決策があります:

// myContext is, e.g. the Activity.
// my_item_layout has a TextView with id='text'
// content is the parent view (e.g. your LinearLayoutView)
// false means don't add direct to the root
View inflated = LayoutInflater.from(myContext).inflate(R.layout.my_item_layout, content, false);

// Now, before we attach the view, find the TextView inside the layout.
TextView tv = (TextView) inflated.findViewById(R.id.text);
tv.setText(str);

// now add to the LinearLayoutView.
content.addView(inflated);
21
Ben Clayton