6

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()得られますが、を呼び出すとゼロ以外の値が得られますが、実際の高さは得られません。下にスクロールしてからもう一度上にスクロールすると(行の1つが表示されなくなります)getHeight() == getMeasuredHeight()、両方とも正しい値になります。getViewでmHeightsを更新するだけの場合(と言ってmHeights.set(position, row.getHeight()); それは機能しますが、ListViewの一番下までスクロールした後でのみです。getViewメソッド内でrow.measure()を呼び出そうとしましたが、これgetHeight()を最初に実行すると0になります。

私の質問はこれです:リストビューの行の正しい高さでmHeightsを計算して入力するにはどうすればよいですか?私はいくつかの同様の質問を見ましたが、それらは私が探しているものではないようです。このViewTreeObserverメソッドは有望なようですが、getView()の呼び出しを強制する方法(または、ListViewの行を繰り返す方法)がわかりません。呼び出すadapter.notifyDataSetChanged()と、無限の(ただしブロッキングではない)ループが発生します。

  1. 実際のビューの高さを取得する
  2. リストビューでアイテムの高さを取得する方法は?

これは、このテーマに関する私の以前の質問に関連していますが、ポイントを逃したようです:リストの一番上からのListView距離

4

2 に答える 2

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));
    }
});

ここで、はアダプターでrow返されるビュー、は の各要素の高さのリスト、はリスト ビューの上部からの距離 (ピクセル単位) のリストです - 私が計算したかった実物(つまり、リスト ビュー全体を端から端までレイアウトした場合、一番上の要素からどれだけ離れているか)。これらはすべて custom 内に保存されます。これらのリストはゼロに初期化されます。getView()mHeightsListViewmDistancesArrayAdapter

このコールバックを追加すると、ビューの高さを計算できるようになりました。

私の目標は、リストとともにスクロールする背景を持つ ListView を持つことでした。興味のある方がいらっしゃれば、コードを GitHub にアップします: https://github.com/mdkess/TexturedListView

于 2012-10-31T01:07:00.973 に答える
2

このSO の回答は、11 未満の API レベルもサポートしたい開発者に有効です。

基本的に、ビューに を追加する代わりにView.onLayoutChnageListener、ビューの に を設定できOnGlobalLayoutListenerますViewTreeObserver

于 2014-02-21T22:40:27.067 に答える