如何为 ListView 项目获取()
How to getY() for ListView items
在水平 LinearLayout(匹配屏幕宽度)中,我有两个 ListView 实例(带有动态列表项)和一个 TextView 实例。使用 TextView 作为 canvas,我想绘制(Bezier)线连接左侧 ListView 中的选定列表项与右侧 ListView 中的所有列表项,反之亦然。现在完全有可能被选中的列表项或另一侧的任何列表项都在 ListView 的可见区域之外。在这种情况下,我想只在可见的范围内绘制这些线(从 above/below 进入或离开 above/below)。为了绘制这些线,我需要在每条线的开头和结尾处设置 x 和 y 值。 x 只是 textView.getLeft() 和 textView.getRight(),但 y 取决于两个列表的当前滚动位置。
我的问题是获取特定 ListView 项目的当前 y 值:
list.getChildAt(indexOfCurrentlySelectedItem).getY()
我需要在列出列表后访问这些值。我需要确定哪些列表项是可见的,哪些列表项是不可见的(不可见的列表项是否具有 y 值?视图?可回收视图(使用持有人模式)?)。我需要能够遍历我为了将这些 y 值传递给我的 TextView 的 onDraw 方法的列表。最后我需要安装一个机制来在滚动发生后重新绘制线条。
如何获取当前的 y 值(布局后和滚动后)?我是否必须跟踪 OnScrollListener 中的可见位置?我是否必须在 OnGlobalLayoutListener 中监听列表布局的结尾?我(还)是否必须在 OnGlobalLayoutListener 中为每个列表项监听列表项布局的结尾?
好的,我找到了一个很好的解决方案: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);
}
}
在水平 LinearLayout(匹配屏幕宽度)中,我有两个 ListView 实例(带有动态列表项)和一个 TextView 实例。使用 TextView 作为 canvas,我想绘制(Bezier)线连接左侧 ListView 中的选定列表项与右侧 ListView 中的所有列表项,反之亦然。现在完全有可能被选中的列表项或另一侧的任何列表项都在 ListView 的可见区域之外。在这种情况下,我想只在可见的范围内绘制这些线(从 above/below 进入或离开 above/below)。为了绘制这些线,我需要在每条线的开头和结尾处设置 x 和 y 值。 x 只是 textView.getLeft() 和 textView.getRight(),但 y 取决于两个列表的当前滚动位置。
我的问题是获取特定 ListView 项目的当前 y 值:
list.getChildAt(indexOfCurrentlySelectedItem).getY()
我需要在列出列表后访问这些值。我需要确定哪些列表项是可见的,哪些列表项是不可见的(不可见的列表项是否具有 y 值?视图?可回收视图(使用持有人模式)?)。我需要能够遍历我为了将这些 y 值传递给我的 TextView 的 onDraw 方法的列表。最后我需要安装一个机制来在滚动发生后重新绘制线条。
如何获取当前的 y 值(布局后和滚动后)?我是否必须跟踪 OnScrollListener 中的可见位置?我是否必须在 OnGlobalLayoutListener 中监听列表布局的结尾?我(还)是否必须在 OnGlobalLayoutListener 中为每个列表项监听列表项布局的结尾?
好的,我找到了一个很好的解决方案: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);
}
}