Неправильная высота представления списка 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 & 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. Вышесказанное просто иллюстрирует, где такой простой совет не совсем вся история.