Подтвердить что ты не робот

ScrollView не изменяет размер сразу после изменений ребенка

У меня возникла очень неприятная проблема с изменением размера ScrollView, и у меня заканчиваются возможные решения.

У меня есть FragmentPager, содержащий несколько разных фрагментов, один из которых имеет ScrollView. Фрагмент с ScrollView состоит из Spinner и ScrollView, содержащих LinearLayout, с несколькими строками других представлений (таких как SeekBars, Buttons, Edittexts). В зависимости от того, какой параметр выбран в Spinner, ScrollView показывает разные виды. Для этого некоторые виды имеют свою видимость, повернутую к Gone, а другие - к Visible. Это отлично работает, за исключением того факта, что ScrollView, похоже, не изменяет свое качество при выборе другой опции с помощью Spinner.

Когда ScrollView заполнен представлениями и, следовательно, прокручивается, если пользователь выбирает параметр, который показывает меньше Viewsthan, необходимый для заполнения ViewPort, прокручивается ScrollView. Когда пользователь снова выбирает старый параметр, ScrollView теперь не может прокручиваться, так как он принимает размер, необходимый для предыдущей опции. Когда пользователь снова выбирает параметр SAME, ScrollView неожиданно прокручивается, так как теперь он изменяется на нужный размер.

Что здесь происходит? И еще лучше, как я могу исправить эту неприятную проблему?

Мой макет:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/control_scroll"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:background="#99000000"
    android:fillViewport="true" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#DD000000"
            android:gravity="bottom"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/lamp_choose_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="2dp"
                android:paddingLeft="5dp"
                android:text="@string/choose_lamp_text"
                android:textColor="#FFFFFF"
                android:textSize="14sp" />
        </LinearLayout>

        <Spinner
            android:id="@+id/lamp_select_spinner"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:textColor="#FFFFFF" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#DD000000"
            android:gravity="bottom"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/lamp_settings_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="2dp"
                android:background="#44000000"
                android:paddingLeft="5dp"
                android:text="@string/lamp_settings_text"
                android:textColor="#FFFFFF"
                android:textSize="14sp" />
        </LinearLayout>
        <!-- Lamp name -->

        <LinearLayout
            android:id="@+id/naam_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="bottom"
            android:paddingBottom="3dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="3dp" >

            <TextView
                android:id="@+id/bridge_naam"
                style="@style/ConfigText"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/config_lightname"
                android:textColor="#FFFFFF"
                android:textSize="16sp" />

            <EditText
                android:id="@+id/lamp_naam_input"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:background="@drawable/tasstextfield"
                android:inputType="textNoSuggestions"
                android:textColor="#FFFFFF" >
            </EditText>
        </LinearLayout>

        <View
            android:id="@+id/separator"
            android:layout_width="fill_parent"
            android:layout_height="0.5dp"
            android:background="@android:color/black"
            android:visibility="visible" />
<!-- Rest of the views -->

Вещи, которые я уже пробовал:

  • ForceLayout/requestLayout для родительского ScrollView
  • Недействительный ScrollView
  • ForceLayout/requestLayout для содержащего LinearLayout
  • Недействительность LinearLayout
  • Нарушение всех дочерних элементов ScrollView
  • ForceLayout/requestLayout для всех дочерних элементов ScrollView
4b9b3361

Ответ 1

Это может быть не самое приятное решение, но оно может работать. Используйте обработчик для отправки сообщения с задержкой, чтобы обновить представление во второй раз, как если бы пользователь дважды выбирал одну и ту же опцию после нажатия кнопки обновления.

// The code when the user wants to update the views 
myButton.setOnClickListener(new OnClickListener{
  @Override
  public void onClick(View view) {
    updateView();
    Message m = Message.obtain();
    m.what = UPDATE_TAG;
    mHandler.sendMessageDelayed(msg, 200);
  }
})

...

final int UPDATE_TAG = 1;

public void updateView() {
  // Code where View.GONE and View.VISIBLE + invalidate is used.
}

Handler mHandler = new Handler {
  @Override
  public void handleMessage(Message input_msg) {
    if(msg.what == UPDATE_TAG) {
      updateView();
    }
  }
}

Ответ 2

Попробуйте с этими изменениями

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/control_scroll"
android:layout_width="fill_parent"
android:layout_height="wrap_content"

android:background="#99000000"
android:fillViewport="true" >

Закройте android:layout_weight="1"

Ответ 3

Я полагаю, что LinearLayout использует какой-то механизм кеширования, чтобы каждый раз не мешать измерениям. Или, может быть, я ошибаюсь.

Однако вы можете попытаться использовать RelativeLayout вместо связки LinearLayout. Это решит вашу проблему, и это будет намного более эффективно, так как вложенный ViewGroup не подходит для производительности.

Ответ 4

Вы можете пойти вперед и установить высоту ScrollView в значение "wrap_content", чтобы даже если изменения в представлении дочерних элементов ScrollView можно настроить на новую настройку