Вычислите размер представления списка или как рассказать, чтобы он полностью расширялся
В настоящее время я пытаюсь использовать ListView внутри ScrollView. Я знаю, из того, что я прочитал, это выглядит сверху вниз, но я пытаюсь полностью расширить ListView, показывая все его строки, поэтому нет необходимости прокручивать его. Однако я боролся с тем, как показать, что ListView полностью расширяется, чтобы показать все его строки, так как ему нужна определенная высота. Кто-нибудь знает способ вычисления высоты полностью расширенного ListView до его рисования?
Эта проблема в основном связана с тем, что вы не можете поместить прокручиваемый вид внутри другого прокручиваемого представления. Я в порядке с тем, что ListView не сможет прокручивать, пока я могу его расширить, чтобы показать все его строки. Однако я не могу этого сделать, не имея возможности дать ему определенную высоту, что, по-видимому, мне нужно будет вычислить.
Посмотрите URL-адрес ниже для эскиза (я новый пользователь, поэтому мне не разрешено публиковать его). Он показывает, что мой полный макет слишком велик для "физического" экрана и ему нужно прокрутить, чтобы показать остальную часть списка и кнопки внизу. Я пытаюсь понять, что "виртуальный" экран слишком велик, чтобы соответствовать одному экрану даже без ListView.
http://img51.imageshack.us/img51/7210/screenmockup.png
Ответы
Ответ 1
Хорошо, спасибо Руди, его предложения были очень полезными. Вот как это можно реализовать.
1) Создайте новый класс, который расширяет ListView:
package com.example.android.views;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.ListView;
public class ExpandedListView extends ListView {
private android.view.ViewGroup.LayoutParams params;
private int old_count = 0;
public ExpandedListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
if (getCount() != old_count) {
old_count = getCount();
params = getLayoutParams();
params.height = getCount() * (old_count > 0 ? getChildAt(0).getHeight() : 0);
setLayoutParams(params);
}
super.onDraw(canvas);
}
}
2)... и, наконец, добавим новое представление в ваш файл макета xml:
<com.example.android.views.ExpandedListView
android:id="@+id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none"
android:padding="0px"
/>
Ответ 2
Правильный способ расчета высоты точно:
int height = 0;
for (int i = 0; i < listView.getChildCount(); i++) {
height += listView.getChildAt(i).getMeasuredHeight();
height += listView.getDividerHeight();
}
Ответ 3
Внимание!
Правильный способ расчета высоты не
params.height = getCount() * (old_count > 0 ? getChildAt(0).getHeight() : 0);
Мы должны добавить высоту каждой (минус одной) высоты разделителя.
if(oldCount > 0 && getCount() > 0)
params.height = getCount()
* (getChildAt(0).getHeight() + getDividerHeight())
- getDividerHeight();
else
params.height = 0;
Ответ 4
Если вы хотите, чтобы ListView, который не будет прокручиваться, не мог бы просто использовать LinearLayout?
Ответ 5
@Override
public void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
if (this.isExpanded) {
final int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
final ViewGroup.LayoutParams params = this.getLayoutParams();
params.height = this.getMeasuredHeight();
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Ответ 6
Нельзя размещать ListView в ScrollView. ListView уже прокручивается.
ListView должен полностью развернуться по умолчанию, если это единственное в макете.
Если это не единственное в макете, и вы хотите, чтобы ListView расширялся, чтобы заняться всем свободным пространством, установите layout_weight в ListView равным 1, где все остальные layout_weight = 0.
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent" orientation="vertical">
<TextView id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ListView id="@+id/listView"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
Изменить:
ListView действительно предназначен для прокрутки... макет экрана, который у вас есть на скриншоте, на самом деле не похож на "андроидный путь".
Однако, если вы действительно хотите обойти это, вы можете попробовать раздуть одну из строк, получить ее minHeight и умножить на количество элементов в адаптере ListView.
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.label_value_row, null, false);
int height = adapter.getCount() * view.getMinHeight();
Ответ 7
Я взял функцию из ответа djunod (функция в статическом классе)
рассчитать размер списка просмотров
и измените метод ondraw следующим образом.
он успешно работает после успешных операций удаления.
вот мой последний класс
класс ExpandedListView расширяет ListView {
private android.view.ViewGroup.LayoutParams params;
private int old_count = 0;
public ExpandedListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
if (getCount() != old_count) {
params = getLayoutParams();
old_count = getCount();
int totalHeight = 0;
for (int i = 0; i < getCount(); i++) {
this.measure(0, 0);
totalHeight += getMeasuredHeight();
}
params = getLayoutParams();
params.height = totalHeight + (getDividerHeight() * (getCount() - 1));
setLayoutParams(params);
}
super.onDraw(canvas);
}
}
теперь мой список расширяется после вставки строки без прокрутки.
и после удаления строки этот код вычисляет правильный размер для списка.
Я не знаю, как он работает.
но он работает.
BR
Ответ 8
Я закончил переопределять onDraw()
ListView и вычислял среднюю высоту видимых строк в представлении, а затем оценивал фактическую высоту списка в зависимости от количества элементов в адаптере. Эта оценка выполняется несколько раз, пока все строки не будут видны.
Ответ 9
Я изучал, как это сделать, и хотя на этот вопрос уже был дан ответ, я хотел бы предложить решение, которое, я думаю, будет лучше:
Глядя на исходный код ListView, вы можете увидеть следующее внутри кода onMeasure (...):
if (heightMode == MeasureSpec.AT_MOST) {
// TODO: after first layout we should maybe start at the first visible position, not 0
heightSize = measureHeightOfChildren(widthMeasureSpec, 0, NO_POSITION, heightSize, -1);
}
Так просто вызовите меру listView и передайте MeasureSpec.AT_MOST для высоты вместо обычного MeasureSpec.UNSPECIFIED.
Я делаю следующее, чтобы измерить список и поместить его во всплывающее окно:
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels, MeasureSpec.EXACTLY);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels, MeasureSpec.AT_MOST);
mCatalogView.measure(widthMeasureSpec, heightMeasureSpec);
mPopup.setWidth(mCatalogView.getMeasuredWidth());
mPopup.setHeight(mCatalogView.getMeasuredHeight());
Ответ 10
Я знаю это поздно, и есть уже и ответ, но если вы действительно хотите сделать это, вам будет проще:
Создать представление списка Элемент с определенной высотой
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="horizontal" >
<ImageView
android:id="@+id/lvItemSurpriseMeImgRestaurant"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginLeft="5dp"
android:contentDescription="@string/restaurantImageDescriptionColon" />
</LinearLayout>
Теперь мы знаем, что элемент 100dp
высокий, и если мы знаем количество элементов, то это очень просто
установите высоту ListView
буквально в значение NoOfItems
* Height
+ 10dp
extra
Он никогда не изменится, поскольку все объединения находятся в dp
.
Если у вас более одного типа элемента, то вычислите его с помощью базовой математики и установите его
<ListView
android:id="@+id/menuListView"
android:layout_width="match_parent"
android:layout_height="210dp"
android:layout_weight="1.0"
tools:ignore="NestedScrolling"
tools:listitem="@layout/menu_item" >
</ListView>
Ответ 11
Если у вас есть элементы с разной высотой, вам нужно использовать этот метод:
public void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter != null) {
int numberOfItems = listAdapter.getCount();
// Get total height of all items.
int totalItemsHeight = 0;
for (int itemPos = 0; itemPos < numberOfItems; itemPos++) {
View item = listAdapter.getView(itemPos, null, listView);
float px = 300 * (listView.getResources().getDisplayMetrics().density);
item.measure(
View.MeasureSpec.makeMeasureSpec((int)px, View.MeasureSpec.AT_MOST),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
int height = item.getMeasuredHeight();
totalItemsHeight += height;
}
// Get total height of all item dividers.
int totalDividersHeight = listView.getDividerHeight() *
(numberOfItems - 1);
// Set list height.
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalItemsHeight + totalDividersHeight;
listView.setLayoutParams(params);
listView.requestLayout();
}
}
он отлично работает с любым ListView с любыми элементами
Ответ 12
использовать это будет:
public class ListViewEx extends ListView {
public ListViewEx(Context context) {
super(context);
}
/**
* @param context
* @param attrs
*/
public ListViewEx(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 设置不滚动
*/
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return ev.getAction()==MotionEvent.ACTION_MOVE||super.dispatchTouchEvent(ev);
}
}