Неправильная высота представления списка Android, обернутого в HorizontalScrollView, где элементы списка имеют различную высоту

У меня есть ListView, завернутый в HorizontalScrollView, где представления элементов списка имеют разную высоту в зависимости от содержимого. Расположение элемента списка выглядит следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:baselineAligned="false"
    android:orientation="horizontal"
    android:weightSum="1" >

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight=".5"
        android:minHeight="50dp"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

            <TextView
                android:id="@+id/nextStopType"
                android:layout_width="20dp"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="P"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="@color/dohrn_orange" />

            <TextView
                android:id="@+id/nextStopName"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:maxLines="2"
                android:text="Customer Name"
              android:textAppearance="?android:attr/textAppearanceMedium" />

        </LinearLayout>

        <TextView
            android:id="@+id/nextstopAddress"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minLines="2"
            android:paddingLeft="20dp"
            android:text="Address"
            android:textAppearance="?android:attr/textAppearanceSmall" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight=".3"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/nextStopCount"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minWidth="@dimen/nextStopDetailsWidth"
            android:text="Stop Count"
            android:textAppearance="?android:attr/textAppearanceSmall" />

        <TextView
            android:id="@+id/nextStopTimes"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="?android:attr/textAppearanceSmall"
            android:text="Open/Close Times"
            android:textAppearance="?android:attr/textAppearanceSmall" />

        <TextView
            android:id="@+id/nextStopContact"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Contact Number"
            android:textAppearance="?android:attr/textAppearanceSmall" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_weight=".2"
        android:gravity="right" >

        <TextView
            android:id="@+id/nextStopPieces"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:minWidth="@dimen/nextStopPiecesWidth"
            android:text="HUs"
            android:textAppearance="?android:attr/textAppearanceSmall" />

        <TextView
            android:id="@+id/nextStopWeight"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:minWidth="@dimen/nextStopWeightWidth"
            android:text="Weight"
            android:textAppearance="?android:attr/textAppearanceSmall" />

    </LinearLayout>

</LinearLayout>

Все в порядке, если nextStopName представляет собой одну строку, но если он переносится на две строки, высота списка неверно рассчитывается. Если я смотрю на иерархию представлений в DDMS, высота ListView составляет 111 пикселей, но высота LinearLayout, включающего элемент списка, составляет 122 пикселя, что является высотой LinearLayout, включающей nextStopType и nextStopName. 111 - это высота второго LinearLayout, содержащего nextStopCount, et. и др.

По сути, всякий раз, когда оборачивается nextStopName, я получаю эту ошибку.

Ниже приведен снимок экрана, где вы можете увидеть эффект.

Снимок экрана с усеченным элементом спискаНиже приведен макет для этого экрана.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<HorizontalScrollView
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:fillViewport="true"
    android:layout_weight="1" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight=".5"
                android:gravity="center_vertical"
                android:maxLines="2"
                android:minWidth="@dimen/nextStopAddressWidth"
                android:text="Customer Name &amp; Address"
              android:textAppearance="?android:attr/textAppearanceMedium" />

            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight=".3"
                android:hint="?android:attr/textAppearanceMedium"
                android:minWidth="@dimen/nextStopDetailsWidth"
                android:text="Details"
              android:textAppearance="?android:attr/textAppearanceMedium" />

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_gravity="center_vertical"
                android:layout_weight=".2"
                android:gravity="right" >

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:gravity="right"
                    android:minWidth="@dimen/nextStopPiecesWidth"
                    android:text="HUs"
               android:textAppearance="?android:attr/textAppearanceSmall" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:gravity="right"
                    android:minWidth="@dimen/nextStopWeightWidth"
                    android:text="Weight"
               android:textAppearance="?android:attr/textAppearanceSmall" />

            </LinearLayout>
        </LinearLayout>

        <ListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" >
        </ListView>
    </LinearLayout>
</HorizontalScrollView>

<LinearLayout
    android:id="@android:id/empty"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="0"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/eolMargin"
        android:gravity="center"
        android:text="Waiting For Stops"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <Button
        android:id="@+id/logoutButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="@dimen/eolMargin"
        android:text="Logout"
        android:textAppearance="?android:attr/textAppearanceButton" />
</LinearLayout>

Соответствующая часть адаптера проста.

    public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    if (row == null) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        row = inflater.inflate(rowLayout, parent, false);
    }
    StopItem stopItem = getItem(position);
    TextView pdFlag = (TextView) row.findViewById(R.id.nextStopType);
    pdFlag.setText(stopItem.getType());
    if (isCurrentDestination(stopItem)) {
        pdFlag.setTextColor(Color.GREEN);
    } else {
        pdFlag.setTextColor(DOHRN_ORANGE);
    }

    TextView name = (TextView) row.findViewById(R.id.nextStopName);
    name.setText(stopItem.getCustomerName());

    TextView address = (TextView) row.findViewById(R.id.nextstopAddress);
    address.setText(stopItem.getAddress());

    TextView stopCount = (TextView)row.findViewById(R.id.nextStopCount);
    stopCount.setText(stopItem.getStopCount() );

    TextView timesView = (TextView)row.findViewById(R.id.nextStopTimes);
    String times = stopItem.getTimes("\n");
    if (times.length() == 0) {
        timesView.setVisibility(View.GONE);
    } else {
        timesView.setText(times);
    }

    TextView phoneView = (TextView)row.findViewById(R.id.nextStopContact);
    String phoneNumber = stopItem.getFormattedPhoneNumber();
    if (phoneNumber.length() == 0) {
        phoneView.setVisibility(View.GONE);
    } else {
        phoneView.setText(phoneNumber);
    }

    TextView pieceCount = (TextView)row.findViewById(R.id.nextStopPieces);
    pieceCount.setText(stopItem.getPieceCount());

    TextView weight = (TextView)row.findViewById(R.id.nextStopWeight);
    weight.setText(stopItem.getWeight());
    return row;
}

Я перепробовал множество вариаций макетов, все с одинаковым результатом. Странно то, что в приложении есть другие ListViews, которые имеют элементы с разной высотой и работают нормально, но они не оборачиваются в представление HorizontalScroll и не имеют столь же сложного макета элемента.

2 ответа

Вы должны изменить размер ScrollView высота с новымLayoutParams а также requestLayout() метод в getView() каждый раз, когда getView() звонит.

2 или больше AbsView не могут удерживать друг друга в одно и то же время, когда один из них не имеет фиксированного размера.

В итоге я использовал разные макеты для разных размеров экрана. Для маленьких экранов (по умолчанию) макеты используют HorizontalScrollView, но ширина элементов элемента списка имеет фиксированную ширину, как предложено выше. Для больших экранов нет HorizontalScrollView, а ширина элемента списка - это полный экран, а ширина элементов элемента списка определяется весами. Работает как шарм.

Я был сбит с толку предложениями, что все, что вам нужно было сделать, чтобы использовать HorizontalScrollView, это обернуть существующий макет в один линейный макет и обернуть его в HorizontalScrollView. Вышесказанное просто иллюстрирует, где такой простой совет не совсем вся история.

Другие вопросы по тегам