【问题标题】:How to getY() for ListView items如何为 ListView 项目获取()
【发布时间】:2016-04-15 21:45:18
【问题描述】:

在水平 LinearLayout(与屏幕宽度匹配)中,我有两个 ListView 实例(带有动态列表项)和一个 TextView。使用 TextView 作为画布,我想绘制(贝塞尔)线连接左侧 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 中为每个列表项监听列表项布局的结尾?

【问题讨论】:

    标签: android listview onscrolllistener


    【解决方案1】:

    好的,我找到了一个很好的解决方案: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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-11-10
      • 1970-01-01
      • 2021-07-11
      • 1970-01-01
      • 2012-06-15
      • 1970-01-01
      • 1970-01-01
      • 2019-08-28
      • 1970-01-01
      相关资源
      最近更新 更多