Space (View) не работает в макете ListItem
У меня есть ListActivity с пользовательским адаптером. Этот адаптер использует следующий list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/ll1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/default_margin"
android:contentDescription="@string/checkbox_content_description"
android:src="@drawable/checkbox_unchecked"
android:background="@layout/transparent_background"
android:focusableInTouchMode="false"
android:adjustViewBounds="true"
android:clickable="false"
android:focusable="false" />
<TextView
android:id="@+id/tv_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginTop="@dimen/default_margin"
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false"
android:textIsSelectable="false" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginTop="@dimen/default_margin">
<TextView
android:id="@+id/tv_product_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="end"
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false"
android:textIsSelectable="false" />
</LinearLayout>
<TextView
android:id="@+id/tv_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginTop="@dimen/default_margin"
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false"
android:textIsSelectable="false" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll2"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_below="@id/ll1">
<Space
android:id="@+id/filler_space"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginBottom="@dimen/default_margin"
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false" />
<EditText
android:id="@+id/et_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginBottom="@dimen/default_margin"
android:inputType="number" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginBottom="@dimen/default_margin"
android:padding="0dp">
<AutoCompleteTextView
android:id="@+id/actv_search_product"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:singleLine="true"
android:ellipsize="end"
android:inputType="text" />
</LinearLayout>
<EditText
android:id="@+id/et_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginBottom="@dimen/default_margin"
android:inputType="numberDecimal"
android:digits="0123456789.,-" />
</LinearLayout>
</RelativeLayout>
В метод getView адаптера я добавил следующий фрагмент кода:
// Change the width of the Filler-Space to match the Image
// and leave the height as is
Space space = (Space) view.findViewById(R.id.filler_space);
space.setLayoutParams(new LinearLayout.LayoutParams(
imageView.getMeasuredWidth(), space.getMeasuredHeight()));
Сначала это дает следующий результат:
Когда я изменяю видимость моего второго LinearLayout (ll2) на VISIBLE, это дает следующий результат:
Вместо этого я хочу:
Кажется, ширина Space-View вообще не изменяется. Хотя я точно знаю, что методы getView успешно вызываются благодаря сообщениям в журнале и другим вещам, которые я делаю в методе getView.
Кто-нибудь знает, что я сделал не так?
PS: когда я использую View вместо Space, я получаю тот же результат. Никогда раньше не использовал Space, поэтому я подумал, что с этим можно что-то делать.
Решение благодаря варианту Demand 4:
// Since we can't access Measured widths and heights before the View is completely loaded,
// we set up an Observer that will be called once the ListItem's layout is ready
ViewTreeObserver observer = view.getViewTreeObserver();
if(observer.isAlive()){
// In order to access the view in the onGlobalLayout, it needs to be final, so we create a final copy here
final View v = view;
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
// This will be called once the layout is finished, prior to displaying it
@Override
public void onGlobalLayout() {
ImageView imageView = (ImageView) v.findViewById(R.id.image);
Space space = (Space) v.findViewById(R.id.filler_space);
// Change the width of the Filler-Space to match the Image and leave the height as is
space.setLayoutParams(new LinearLayout.LayoutParams(imageView.getMeasuredWidth(), space.getMeasuredHeight()));
}
});
}
1 ответ
Вы устанавливаете ширину и высоту, если ваше пространство равно wrap_content. Это значит, что у пространства будет ширина как у его потомков, но потомков нет, а у вас ширина = 0. Дело не в пространстве, а в измерении макета в Android. Когда вы звоните свой код:
Space space = (Space) view.findViewById(R.id.filler_space);
space.setLayoutParams(new LinearLayout.LayoutParams(
imageView.getMeasuredWidth(), space.getMeasuredHeight()));
Ваш imageView еще не измерен и возвращает ширину = 0. Он будет измерен позже перед рисованием. В getView() в адаптере вы только создаете виды, но измерения, компоновка и рисование будут позже.
У вас есть несколько способов исправить это:
- установите ширину вашего пространства в dp вместо wrap_content.
- используя относительную компоновку вместо трех линейных компоновок.
- Используйте TableLayout.
- Добавьте GlobalTreeObserver и getMeasuredWidth() в нужное время.
- Разместите ваш runnable в обработчике представления, чтобы получить ширину после рисования.
Я думаю, что лучший способ - это 2 и 3, потому что 4 и 5 приведут к измерению несколько раз.