Android:从ListView访问子视图

Android:从ListView访问子视图,android,android-listview,Android,Android Listview,我需要找出列表中一个元素的像素位置,该列表已使用列表视图显示。似乎我应该获取一个文本视图,然后使用getTop(),但我不知道如何获取列表视图的子视图 更新:对于列表视图,视图组的子项与列表中的项目不一一对应。相反,ViewGroup的子视图只对应于当前可见的视图。因此,getChildAt()对ViewGroup内部的索引进行操作,并且不一定与ListView使用的列表中的位置有任何关系。对ListView类的文档进行快速搜索时,出现了从ViewGroup继承的getChildCount()和

我需要找出列表中一个元素的像素位置,该列表已使用
列表视图显示。似乎我应该获取一个文本视图,然后使用
getTop()
,但我不知道如何获取
列表视图的子视图


更新:对于
列表视图,
视图组的子项与列表中的项目不一一对应。相反,
ViewGroup
的子视图只对应于当前可见的视图。因此,
getChildAt()
ViewGroup
内部的索引进行操作,并且不一定与
ListView
使用的列表中的位置有任何关系。

对ListView类的文档进行快速搜索时,出现了从ViewGroup继承的getChildCount()和getChildAt()方法。你能用这些来迭代它们吗?我不确定,但值得一试


找到它

这假设您知道元素在ListView中的位置:

  View element = listView.getListAdapter().getView(position, null, null);
然后,您应该能够调用getLeft()和getTop()来确定屏幕上的元素位置。

请参阅: 再结合上面Foots的部分答案,你可以得到如下结果:

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);
int wantedPosition=10;//不管你在找什么职位
int firstPosition=listView.getFirstVisiblePosition()-listView.getHeaderViewsCount();//这与child#0相同
int wantedChild=wantedPosition-firstPosition;
//比如说,第一个可见位置是8,你想要位置10,想要的孩子现在是2
//这意味着您的视图是视图组中的子视图#2:
if(wantedChild<0 | | wantedChild>=listView.getChildCount()){
w(标签,“无法获取所需位置的视图,因为它没有显示在屏幕上。”);
返回;
}
//还可以检查wantedPosition是否在listView.getFirstVisiblePosition()和listView.getLastVisiblePosition()之间。
View wantedView=listView.getChildAt(wantedChild);

这样做的好处是,您不会迭代ListView的子项,这可能会影响性能。

此代码更易于使用:

 View rowView = listView.getChildAt(viewIndex);//The item number in the List View
    if(rowView != null)
        {
           // Your code here
        }
listview.setOnItemClickListener(新的AdapterView.OnItemClickListener(){
@凌驾
public void onItemClick(AdapterView父视图、最终视图、整型位置、长id){
观点五;
int count=parent.getChildCount();
v=父项。getChildAt(位置);
parent.requestChildFocus(v,视图);
v、 收进背景(res.getDrawable(R.drawable.transparent_按钮));
for(int i=0;i
基本上,创建两个可绘制对象——一个是透明的,另一个是所需的颜色。在单击的位置(
int-position
定义)请求焦点,并更改所述行的颜色。然后遍历父
列表视图
,并相应地更改所有其他行。这是用户多次单击
列表视图时的原因。这是通过
列表视图中每一行的自定义布局来完成的。(非常简单,只需使用
文本视图创建一个新的布局文件-不要设置可聚焦或可点击!)


不需要自定义适配器-填充列表时,ListView会在内部调用use
ArrayAdapter

getView()
。您不应该使用它来获取列表中该位置的视图,因为为
convertView
调用带有null的
getView()
会导致适配器从适配器的布局资源中展开新视图(不会获取已显示的视图)。甚至位置也将是可视屏幕中的一个位置,不是适配器的数据源位置。@jasonhudgins这是我一直使用的方法,我认为这是最好的方法,但当我试图使子视图中的progressbar不可见时,却使listvew中的所有progressbar不可见……。总之,接受的答案是错误的,但是,当列表中有标题视图时,它就不能正常工作。对
firstPosition
的赋值应该是
int firstPosition=listView.getFirstVisiblePosition()-listView.getHeaderViewsCount()来解决这个问题。@pospi:谢谢,说得好!我已经更新了我的答案来解释这一点。答案很好,在大多数情况下都有效,但我不明白为什么您认为子视图是按照它们在子视图数组中的顺序出现的。既然视图可以重用,我们如何确保第一个视图不代表最后一个可见视图?@VictorDenisov:这只能发生在UI线程上;因此,在执行此代码时,UI线程将被阻塞,因此子视图是固定的,不会被修改
ListView
在回收旧的
convertView
s等后,已经在处理“移动”子视图,因此可以保证
ListView.getChildAt(0)
实际上是适配器中的第一个附加视图。它可能不完全可见(甚至可能根本不可见,这取决于
ListView
在循环使用它认为是“滚动出视图”的视图之前的“可见性”阈值)。@Matheus Android ListView不是这样工作的。如果列表项不在屏幕上,则其视图已被回收并重新用于屏幕上的其他列表项之一。如果需要的话,你应该重新考虑一下你是如何使用ListView的。我已经试过了,在做选择的时候。它通常可以工作,但有时会出现一个接一个的错误,因此不可靠。我不推荐。谢谢你,蒂姆,我实际上没有试过,只是在文档中找到的。不总是有效的。getChildAt从第一个可见行开始计数,而不是从第
int position = 0;
listview.setItemChecked(position, true);
View wantedView = adapter.getView(position, null, listview);
int position = 0;
listview.setItemChecked(position, true);
View wantedView = adapter.getView(position, null, listview);