web-dev-qa-db-ja.com

ListViewアイテムが成長してコンテンツをラップしないのはなぜですか?

リストアイテムの高さが可変の、かなり複雑なListViewがあります。特定の条件下では、リストアイテムに追加のビューを表示する必要がありますが、これはデフォルトでは非表示になっています(View.GONE)。これを有効(View.VISIBLE)にすると、リストアイテムの高さが大きくなります(または、少なくとも想定されています)。

問題:アイテムのルートレイアウトをwrap_contentに宣言し、アイテムの各コンポーネントをfill_parentに宣言しても、アイテムの高さを変更することになっている非表示/表示のビューは、親の代わりに下部で切り取られます(アイテムのレイアウト)を完全に表示するために高さが大きくなります。

ListViews、アイテムのレイアウト、アイテムの高さに関連する落とし穴がありますか?

その他の観測:

テストの目的で、リストアイテムのレイアウトを減らして、ルートのLinearLayoutとImageViewのみを含めるようにしました。 LinearLayoutの高さを例えば200dipおよびImageViewをfill_parentにすると、ImageViewが親によって設定された200dipの制限に達するまでImageViewが大きくなることが予想されます。

ただし、代わりに画像はビットマップリソースと同じ高さになり(wrap_contentに設定した場合と同じように)、リストアイテム全体が同じ高さになります(つまり、wrap_contentに設定した場合と同じように)。

ただし、画像の高さをたとえば200dipの場合、リストアイテムの高さが増加し、アイテムのレイアウトも増加します。

つまり、リストアイテムレイアウトのlayout_heightは完全に無視され、ハードコードされたピクセル値以外のImageViewの高さの値も完全に無視されます。

56
Matthias

私はこれを修正することができましたが、whyがわかりません。

前述したように、リストアイテムレイアウトのlayout_heightwrap_contentに設定しました(ListViewの高さが無限にあることを考えると、fill_parentはここでは意味がないため)。

ただし、すべてのビューのlayout_heightを設定していましたinsideそのレイアウトはfill_parentに設定されていました。代わりにwrap_contentに設定すると、問題はなくなりました。

これにより、他に2つの質問が発生します。

1)親がfill_parentである場合、wraps_contentを要求するビューのセマンティクスは何ですか?どのサイズのリクエストが優先されますか?

2)fill_parentが機能しないように見える場合、どのようにしてリスト項目をビューで埋めますか?

ご意見をお寄せいただきありがとうございます。

56
Matthias

これを試してください: http://www.Java2s.com/Code/Android/UI/setListViewHeightBasedOnChildren.htm

public class Utils {

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter(); 
        if (listAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }     
}
29
PeBek

行をどのように膨らませていますか?

現在使用していない場合は、LayoutInflater#inflate(layoutId, parent, false)を使用してみてください(parentgetView()またはnewView()に提供されるAdapterViewです):

v = getLayoutInflater().inflate(R.layout.list_item, parent, false);
21
CommonsWare

ScrollViewがラッパーになることにより、レイアウトの問題が発生する可能性があります

私は http://developer.Android.com/reference/Android/widget/ExpandableListView.html でいくつかの注意を見つけました

"...注:親のサイズも厳密に指定されていない場合、XMLでExpandableListViewのAndroid:layout_height属性に値wrap_contentを使用することはできません(たとえば、親がScrollViewの場合、wrap_contentも指定できないため、ただし、ExpandableListViewの親のサイズが100ピクセルなどの特定のサイズである場合は、wrap_contentを使用できます。

ScrollViewの折り返しを削除すると、線形レイアウトが正常に機能し始めました。これで、ScrollViewにデータをラップする方法を理解できるようになりました。神よ私を救い給え

とにかく、これは本当に奇妙な動作です。 fill_parentは本当に正しい表現ではないと思います。 heirarchyviewerツールを使用すると、layout_widthとleayout_heightのWRAP_CONTENTとMATCH_PARENTの値が常に表示されます。したがって、おそらくfill_parentは実際にはmatch_parentを意味し、これによって私は認知的不協和に陥ります。

14
kirhgoff

「AbsListView.LayoutParams」を使用して、「Adapter.getView()」内で幅と高さを手動で構成します。

1
roys

サイズ変更するリスト項目としてカスタムViewを使用している場合、PeBekの答えから取得して、Viewを構築するときにこれを行うことができます。

addOnLayoutChangeListener(
            new OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View _, int __, int ___, int ____, int bottom, int _____, int ______,
                                           int _______, int old_bottom) {
                    final ListView list_view = (ListView) getParent();
                    final ViewGroup.LayoutParams params = list_view.getLayoutParams();
                    params.height += bottom - old_bottom;
                    list_view.setLayoutParams(params);
                    list_view.requestLayout();
                }
            });

Viewのサイズが変更されると、このコールバックメソッドが実行され、ListViewの高さが更新されて、高さの変化が反映されます(デルタボトム)。他の値は、view(ビューへの参照)、lefttoprightbottomold_leftold_topold_rightold_bottom。ビューを展開したり折りたたんだりするために機能します。

API 11OnLayoutChangeListenerに必要です。下位互換性のある方法があるかどうかはわかりません。

1
Dandre Allison

これは私のために働く

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"

    Android:padding="@dimen/activity_vertical_margin">

    <TextView
        Android:id="@+id/tv_status"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:gravity="center"
        Android:textSize="17sp"
        Android:text="@string/text_list_devices" />

    <ListView
        Android:id="@+id/lv_paired"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="@dimen/activity_vertical_margin"
        Android:cacheColorHint="#00000000"
        Android:layout_above="@+id/signup_t"
        Android:layout_below="@id/tv_status"
        />

    <Button

        Android:id="@+id/signup_t"
        style="?android:textAppearanceSmall"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="20dp"
        Android:textColor="@Android:color/white"
        Android:layout_alignParentBottom="true"
        Android:text="Print All Records"
        Android:typeface="sans"
        Android:layout_marginLeft="45dp"
        Android:layout_marginRight="45dp"
        Android:textSize="24sp"
        Android:background="@drawable/selector_for_button"
        Android:textStyle="bold" />
</RelativeLayout>
0
Nouman Ch

私は同じ問題を抱えていました:デバイスが水平方向よりも垂直方向にあるときでも、すべての画面を満たすアクティビティ内のリストを持ちたいです。 fill_parentを必要とする高さを持つ線形レイアウトを使用して問題を解決し、layout_weightが1に設定されている間にリスト内のアイテムの高さを0dpに設定します。

Android:layout_weight="1"
Android:layout_height="0dp"
0
Fra