计算ListView的每一行的高度

min*_*rus 6 android android-layout android-listview

我试图使用ListView创建ListView滚动的背景.我的方法是基于货架上的这个课程,但在货架上一切都有相同的高度,我无法做出同样的保证.

我有这样的活动:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

CustomArrayAdapter的位置是:

public class CustomArrayAdapter extends ArrayAdapter<String> {
    private List<Integer> mHeights;

    public View getView(int position, View convertView, ViewGroup parent) {
        //snip
    }
}
Run Code Online (Sandbox Code Playgroud)

我想要做的是在适配器中使用视图行的高度填充mHeights.

我的主要尝试是在getView()中执行此操作:

if(row.getMeasuredHeight() == 0) {
    row.measure(
        MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY),
        MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY));
}
mHeights.set(position, row.getMeasuredHeight());
Run Code Online (Sandbox Code Playgroud)

我已经尝试了几种方法来做到这一点,但我无法得到任何工作.

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()会导致无限(尽管非阻塞)循环.

  1. 获得实际的视图高度
  2. 如何在列表视图中获取项目的高度?

这与我之前关于这个主题的问题有关,这似乎忽略了这一点:列表顶部的ListView距离

min*_*rus 12

我想出了如何做到这一点.这有点棘手,但它确实有效.

细微之处在于知道布局参数.据我getView()所知,正在返回视图的初始时间,所以当然它还没有高度 - 父母还不知道该行(因为getView()它的工作是膨胀它),所以我们需要一个打回来.

那回调可能是什么?事实证明,我最好能告诉它OnLayoutChangeListener()是行的视图.所以在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));
    }
});
Run Code Online (Sandbox Code Playgroud)

这里,rowgetView()在适配器中返回的视图,mHeights是每个元素的高度列表ListView,并且mDistances是列表视图顶部的距离列表,以像素为单位 - 我想要计算的真实内容(也就是说,如果你端到端地列出整个列表视图,那么我将从顶部到顶部元素的距离).所有这些都存储在自定义中ArrayAdapter.这些列表初始化为零.

添加此回调允许我计算视图的高度.

我的目标是让ListView具有与列表一起滚动的背景.如果有人有兴趣,我把代码放在GitHub上,如果有人想查看它:https://github.com/mdkess/TexturedListView