Android:ListViewから子ビューにアクセスする


108

を使用して表示されたリスト内の1つの要素のピクセル位置を確認する必要がありますListViewTextViewの 1つを取得してからを使用する必要があるようですgetTop()が、の子ビューを取得する方法がわかりませんListView

更新:の子はViewGroup、リストの項目と1対1で対応していませんListView。代わりに、ViewGroupの子は、現在表示されているビューのみに対応しています。したがってgetChildAt()、の内部にあるインデックスを操作し、ViewGroup必ずしもがListView使用するリスト内の位置とは関係ありません。

回答:


215

参照:Android ListView:表示されているアイテムのデータインデックスを取得し 、上記のFeetの回答の一部と組み合わせると、次のような結果が得られます。

int wantedPosition = 10; // Whatever position you're looking for
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); // This is the same as child #0
int wantedChild = wantedPosition - firstPosition;
// Say, first visible position is 8, you want position 10, wantedChild will now be 2
// So that means your view is child #2 in the ViewGroup:
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) {
  Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
  return;
}
// Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead.
View wantedView = listView.getChildAt(wantedChild);

利点は、ListViewの子を繰り返し処理しないため、パフォーマンスが低下する可能性があることです。


10
すばらしい回答ですが、リストにヘッダービューがある場合はうまくいきません。割り当てはするfirstPositionべきであるint firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount();。この問題を解決します。
pospi 2011年

@pospi:ありがとう、良い点!私はそれを説明するために私の答えを更新しました。
Joe、

良い答えであり、ほとんどの場合に機能しますが、子ビューが子ビューの配列にある順序で表示されると思われる理由がわかりません。ビューは再利用できるので、最初のビューが最後に表示されるビューを表していないことをどのように確認できますか?
Victor Denisov 2013年

2
@VictorDenisov:これはUIスレッドでのみ発生します。したがって、このコードの実行中はUIスレッドがブロックされるため、子ビューは固定され、変更されません。 ListViewすでに古いリサイクル後の周りの子ビューを「移動」処理しているconvertViewあなたはので、など、Sをできることが保証されListView.getChildAt(0) ている実際には、アダプタからの最初の添付眺め。完全に表示されない場合があります(またListView、ビューをリサイクルする前の「表示」のしきい値によっては、「スクロールされて表示されない」と見なされる場合もあります)
Joe

1
@MatheusはAndroid ListViewの動作方法ではありません。リスト項目が画面外である場合は、そのビューがすでに他のリスト項目のいずれかのリサイクルおよび再利用されています画面上に。要件がある場合は、ListViewの使用方法を再考する必要があります。
Joe

17

このコードは使いやすいです:

 View rowView = listView.getChildAt(viewIndex);//The item number in the List View
    if(rowView != null)
        {
           // Your code here
        }

9
常に機能するとは限りません。getChildAtは、データの先頭ではなく、最初に表示される行から数えます。
SteelBytes、

13
ViewID引数は紛らわしいです。それはインデックス(または位置)です。ビューIDは、aaptツールによって生成される完全に任意の整数です。
ヨハンペルグリム

6

ListViewクラスのドキュメントのクイック検索により、ViewGroupから継承されたgetChildCount()メソッドとgetChildAt()メソッドが見つかりました。これらを使用してそれらを反復できますか?よくわかりませんが、試してみる価値はあります。

ここで見つけ


1
私は選択をするためにこれを試しました。通常は機能しますが、ときどき1つずれたエラーが発生し、信頼できません。私はそれをお勧めしません。
Timmmm 2012

Timmmmに感謝します。実際には試していませんでした。ドキュメントで見つけました。
フィート

5
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
        View v;
        int count = parent.getChildCount();
        v = parent.getChildAt(position);
        parent.requestChildFocus(v, view);
        v.setBackground(res.getDrawable(R.drawable.transparent_button));
        for (int i = 0; i < count; i++) {
            if (i != position) {
                v = parent.getChildAt(i);
                v.setBackground(res.getDrawable(R.drawable.not_clicked));
            }
        }
    }
});

基本的に、2つのDrawableを作成します-1つは透明で、もう1つは目的の色です。クリックした位置(int position定義どおり)にフォーカスを要求し、その行の色を変更します。次に、親をウォークスルーし、ListViewそれに応じて他のすべての行を変更します。これは、ユーザーがlistview複数回クリックしたときに発生します。これは、の各行のカスタムレイアウトで行われListViewます。(非常に簡単です。新しいレイアウトファイルを作成するには、TextViewフォーカス可能またはクリック可能に設定しないでください。)

カスタムアダプターは不要-使用 ArrayAdapter


getChildAtは、現在のスクロールされたアイテムを基準にしています。リストを少しだけスクロールすると、機能しなくなります。
nurettin 2016年


-9

これは、ListViewでの要素の位置がわかっていることを前提としています。

  View element = listView.getListAdapter().getView(position, null, null);

次に、getLeft()とgetTop()を呼び出して、画面上の要素を特定できるはずです。


43
getView()リストを生成するときに、ListViewによって内部的に呼び出されます。あなたはいけません呼び出すと、リスト内のその位置でのビューを取得するためにそれを使用getView()するためにnullを指定してconvertView、アダプタが(すでに表示されているビューを取得しません)アダプタのレイアウトリソースから新しいビューを膨らませる原因となります。
Joe、

1
位置も、アダプターのデータソースの位置ではなく、ビジュアル画面内の位置になります。
ビカス

@jasonhudginsこれは私がこれまで使用してきた方法であり、最良であると思いましたが、子ビューのプログレスバーを非表示にしようとしたときに、listvewのすべてのプログレスバーを非表示にしました........すべて受け入れられたすべての回答がうまくいった
Edijae Crusar
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.