我正在尝试使用ListView创建ListView滚动的背景。我将我的方法基于Shelves中的这个课程,但在Shelves中,一切都有相同的高度,我无法做出同样的保证。
我有这样的活动:
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listView);
List<String> items = new ArrayList<String>();
for(int i=0; i < 100; ++i) {
items.add("Hello " + i);
}
CustomArrayAdapter adapter = new CustomArrayAdapter(this, items);
listView.setAdapter(adapter);
}
}
CustomArrayAdapter的位置是:
public class CustomArrayAdapter extends ArrayAdapter<String> {
private List<Integer> mHeights;
public View getView(int position, View convertView, ViewGroup parent) {
//snip
}
}
我想要做的是在适配器中使用视图行的高度填充mHeights。
我的主要尝试是在getView()中执行此操作:
if(row.getMeasuredHeight() == 0) {
row.measure(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY));
}
mHeights.set(position, row.getMeasuredHeight());
我已经尝试了几种方法来做到这一点,但我无法工作。
在getView
中,如果我调用getHeight()
,则返回值为0,而如果我调用getMeasuredHeight()
,则会得到非零但不是实际高度的内容。如果我向下滚动然后再向上(将其中一行排除在视图之外)getHeight() == getMeasuredHeight()
并且两者都具有正确的值。如果我在getView中更新mHeights(通过说mHeights.set(position, row.getHeight()
);它工作 - 但只有在我滚动到ListView的底部之后。我试过在getView方法中调用row.measure(),但这仍然导致getHeight()
在第一次运行时为0。
我的问题是:如何使用ListView行的正确高度来计算和填充mHeights?我看过一些类似的问题,但它们似乎并不是我想要的。 ViewTreeObserver
方法似乎很有希望,但我无法弄清楚如何强制从它调用getView()(或者迭代ListView的行)。调用adapter.notifyDataSetChanged()
会导致无限(尽管是非阻塞)循环。
这与我先前有关该主题的问题有关,这似乎忽略了这一点:ListView distance from top of the list
答案 0 :(得分:12)
我想出了如何做到这一点。这有点棘手,但它确实有效。
细微之处在于知道布局参数。据我所知,getView()
正在返回视图的初始时间,所以当然它还没有高度 - 父母还不知道该行(从{{1}开始
回调可能是什么?事实证明,我最好能告诉它getView()
行的视图。因此,在我的自定义OnLayoutChangeListener()
的{{1}}中,我添加了getView()
的回调,如下所示:
ArrayAdapter
此处,onLayoutChanged
是适配器中row.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
ref.removeOnLayoutChangeListener(this);
Log.d("CustomArrayAdapter", "onLayoutChange(" + position + "): height " + (bottom - top));
mHeights.set(position, (bottom - top));
if(position > 0) {
mDistances.set(position, bottom - top + mDistances.get(position-1) + ((ListView)parent).getDividerHeight());
}
holderRef.distanceFromTop = mDistances.get(position);
Log.d("CustomArrayAdapter", "New height for " + position + " is " + mHeights.get(position) + " Distance: " + mDistances.get(position));
}
});
返回的视图,row
是getView()
的每个元素的高度列表,{ {1}}是列表视图顶部距离的列表,以像素为单位 - 我想要计算的真实内容(也就是说,如果您将整个列表视图端到端排列,距离顶部元素有多远我会从顶部)。所有这些都存储在自定义mHeights
中。这些列表初始化为零。
添加此回调允许我计算视图的高度。
我的目标是让ListView具有随列表滚动的背景。如果有人有兴趣,我会将代码放在GitHub上,如果有人想要查看它:https://github.com/mdkess/TexturedListView
答案 1 :(得分:2)
This所以答案应该适用于那些也想支持API级别的开发人员。 11.
基本上,您可以在视图View.onLayoutChnageListener
上设置OnGlobalLayoutListener
,而不是在视图中添加ViewTreeObserver
。