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.