如何获取ListView项目的Y()

时间:2016-04-15 21:45:18

标签: android listview onscrolllistener

在水平LinearLayout(匹配屏幕宽度)中,我有两个ListView实例(带有动态列表项)和介于两者之间的TextView。使用TextView作为画布,我想绘制(Bezier)线,将左侧ListView中的选定列表项与右侧ListView中的所有列表项连接,反之亦然。现在,完全可能的是,所选列表项或另一侧的任何列表项都在ListView的可见区域之外。在这种情况下,我想绘制那些线(从上/下进入或从上/下离开)只有它们可见。为了绘制这些线,我需要在每一行的开头和结尾都有x和y值。 x只是textView.getLeft()和textView.getRight(),但y取决于两个列表的当前滚动位置。

我的问题是获取特定ListView项目的当前y值:

list.getChildAt(indexOfCurrentlySelectedItem).getY()

列表布局后,我需要访问这些值。我需要确定哪些列表项和哪些列表项不可见(不可见的列表项是否具有y值?视图?可循环查看(使用持有者模式)?)。我需要能够遍历列表,我命令将这些y值传递给TextView的onDraw方法。最后,我需要安装一种机制来在滚动之后重新绘制线条。

如何保持当前的y值(布局后和滚动后)?我是否必须跟踪OnScrollListener中的可见位置?我是否必须在OnGlobalLayoutListener中监听列表布局的结尾?我是否也必须在OnGlobalLayoutListener中为每个列表项侦听列表项布局的结尾?

1 个答案:

答案 0 :(得分:0)

好的,我找到了一个很好的解决方案:OnScrollListener提供了我所需要的一切,而这里不需要OnGlobalLayoutListener。

public class ArrayListAdapter extends ArrayAdapter<String>
    implements AbsListView.OnScrollListener

...

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {}

@Override
public synchronized void onScroll(final AbsListView listView, int firstVisibleItem,
                                  int visibleItemCount, int totalItemCount) {
    List<Integer>yList = new ArrayList<>();
    int checkedPosition = listView.getCheckedItemPosition();
    double yChecked = 0;

    for (int pos = 0; pos < totalItemCount; pos++) {
        CheckedTextView tv = (CheckedTextView) this
                .getViewByPosition(pos, listView, firstVisibleItem,
                        firstVisibleItem + visibleItemCount - 1);
        if (pos == checkedPosition) {
            yChecked = tv.getY();
        }
        yList.add(pos, tv.getY());
    }        
    // Here I pass the fresh y-values to the fragment holding the 
    // two ListViews. After some further calculations the fragment
    // passes the data to the TextView where it is stored and
    // this.invalidate is called to eventually trigger the onDraw method.
    originalFragment.setScrollData(yList, yChecked);
}

private View getViewByPosition(int pos, AbsListView listView, int firstVisibleItem,
                               int lastVisibleItem) {
    if (pos < firstVisibleItem || pos > lastVisibleItem) {
        // The next line is the only downside of this solution I have
        // found so far. If the convertView of the getView(int
        // position, View convertView, ViewGroup parent) method is null
        // the holder pattern I applied in my adapter becomes useless.
        // In my case the recreation of the CheckedTextViews is fast
        // enough though.
        return listView.getAdapter().getView(pos, null, listView);
    } else {
        return listView.getChildAt(pos - firstVisibleItem);
    }
}