Android : ListView에서 하위보기에 액세스


108

를 사용하여 표시된 목록에서 한 요소의 픽셀 위치를 찾아야합니다 ListView. TextView 중 하나를 얻은 다음을 사용해야 하는 것 같지만 .NET Framework의getTop() 자식보기를 얻는 방법을 알아낼 수 없습니다 ListView.

업데이트 : 의 하위 ViewGroup항목은 목록의 항목과 일대일로 대응하지 않습니다 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

@ pospi : 감사합니다, 좋은 지적입니다! 나는 그것을 설명하기 위해 내 대답을 업데이트했습니다.

대부분의 경우 좋은 대답과 작동하지만 하위 뷰가 하위 뷰 배열에있는 순서대로 나타나는 이유를 이해하지 못합니다. 뷰를 재사용 할 수 있기 때문에 첫 번째 뷰가 마지막으로 보이는 뷰를 나타내지 않는다는 것을 어떻게 확신 할 수 있습니까?
Victor Denisov 2013 년

2
@VictorDenisov : 이것은 UI 스레드에서만 발생할 수 있습니다. 따라서이 코드가 실행되는 동안 UI 스레드가 차단되므로 자식 뷰는 고정되어 수정되지 않습니다. ListView이미 처리하고 주변의 오래된 재활용 후 아이 뷰를 "이동" convertView당신은 너무 등들, 보장 할 수 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 도구에 의해 생성 된 완전히 임의의 정수입니다.
Johan Pelgrim 2010 년

6

ListView 클래스에 대한 문서를 빠르게 검색하면 ViewGroup에서 상속 된 getChildCount () 및 getChildAt () 메서드가 나타납니다. 이것을 사용하여 반복 할 수 있습니까? 잘 모르겠지만 시도해 볼 가치가 있습니다.

여기 에서 찾았습니다


1
나는 선택을 위해 이것을 시도했습니다. 일반적으로 작동하지만 가끔씩 오류가 발생하며 신뢰할 수 없습니다. 나는 그것을 추천하지 않을 것입니다.
Timmmm

고마워요 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));
            }
        }
    }
});

기본적으로 두 개의 드로어 블을 만듭니다. 하나는 투명하고 다른 하나는 원하는 색상입니다. 클릭 한 위치 ( int position정의 된대로) 에서 포커스를 요청하고 해당 행의 색상을 변경합니다. 그런 다음 부모를 살펴보고 ListView그에 따라 다른 모든 행을 변경합니다. 이것은 사용자가 listview여러 번 클릭하는 경우를 고려 합니다. 이 작업은의 각 행에 대한 사용자 지정 레이아웃으로 수행됩니다 ListView. (매우 간단합니다. a를 사용하여 새 레이아웃 파일을 만드십시오 TextView.-포커스 또는 클릭 가능으로 설정하지 마십시오!).

맞춤 어댑터가 필요하지 않음-사용 ArrayAdapter


getChildAt은 현재 스크롤 된 항목에 상대적입니다. 목록을 조금만 스크롤하면 작동이 중지됩니다.
nurettin

4
int position = 0;
listview.setItemChecked(position, true);
View wantedView = adapter.getView(position, null, listview);

1
조금 정교한
innoSPG

-9

이것은 ListView에서 요소의 위치를 ​​알고 있다고 가정합니다.

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

그런 다음 getLeft () 및 getTop ()을 호출하여 화면 위치의 요소를 결정할 수 있어야합니다.


43
getView()목록을 채울 때 ListView에 의해 내부적으로 호출됩니다. 당신은 호출로, 목록에서 그 위치에서보기를 얻기 위해 그것을 사용 getView()(가)에 null와 convertView어댑터의 레이아웃 자원에서 새로운보기를 팽창 할 수있는 어댑터가 발생합니다 (이미 표시되어있는 뷰를 얻을하지 않습니다).
Joe

1
짝수 위치는 어댑터의 데이터 소스 위치가 아닌 시각적 화면의 위치입니다.
Vikas

@jasonhudgins 이것은 내가 최선이라고 생각했지만 자식보기에서 진행률 표시 줄을 보이지 않게 만들려고 할 때 사용했던 방법이지만 대신 listvew의 모든 진행률 표시 줄을 보이지 않게했습니다. 모든 허용 대답은 트릭했다
Edijae Crusar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.