Макет прокрутки Android (wrap_content, максимальный размер)

Вот что я хотел бы, чтобы мой ScrollView выглядел так:

  • Максимальный размер определяется с помощью layout_weight (так что другие элементы под ScrollView могут отображаться правильно)
  • Если содержимое меньше этого максимального размера, то оно просто ведет себя как с layout_height="wrap_content"

Вот что я сейчас имею:

 <ScrollView android:layout_height="wrap_content" android:layout_width="fill_parent" android:measureAllChildren="true" android:fillViewport="false" > 

Я не думаю, что measureAllChildren действительно вообще что-то делает …

Если я добавлю android:layout_weight , размер всегда будет тем, что я хотел бы, чтобы максимум был. Без этого он просто расширяется больше, чем нужно …

Я не возражаю расширить класс ScrollView, чтобы изменить поведение onMeasure, если мне нужно …?

PS: Если это создает различия, я пытаюсь заставить это работать от Froyo вперед.

Я закончил писать свой собственный класс, расширяя ScrollView

Поскольку вы спрашиваете … вот код. Наверное, не самый чистый, но он делает то, что я хочу.

Обратите внимание, что он ожидает, что layout_weight будет установлен при создании представления, и вы не должны устанавливать weigthSum в родительском LinearLayout или вы получите забавные вещи (так как вес этого изменяется от исходного значения до 0 в зависимости от размера Содержимого ScrollView)

Во-первых, в файле макета представление объявляется следующим образом:

 <com.matthieu.widget.ShrinkingScrollView android:id="@+id/scroll" android:scrollbars="vertical" android:layout_height="0dp" android:layout_width="fill_parent" android:layout_weight="4" android:background="#cc0000" > <TextView android:id="@+id/in_scroll_view" android:layout_height="wrap_content" android:layout_width="fill_parent" android:background="#0000bb" /> </com.matthieu.widget.ShrinkingScrollView> 

Затем код виджета:

 import android.content.Context; import android.util.AttributeSet; import android.widget.LinearLayout; import android.widget.ScrollView; public class ShrinkingScrollView extends ScrollView { private float original_weight=-1; public ShrinkingScrollView(Context context) { super(context); } public ShrinkingScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public ShrinkingScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) getLayoutParams(); float previous_weight = params.weight; if (original_weight == -1) original_weight = params.weight; if ((getChildCount()>0) && (getVisibility()!=GONE)) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED)); int overall_height = getChildAt(0).getMeasuredHeight(); super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (getMeasuredHeight() >= overall_height) { if (previous_weight != 0) { params.weight=0; params.height = overall_height; setLayoutParams(params); post(new Runnable() { public void run() { requestLayout(); } }); } setMeasuredDimension(getMeasuredWidth(),overall_height); } else if (previous_weight == 0) { params.weight = original_weight; params.height = 0; setLayoutParams(params); post(new Runnable() { public void run() { requestLayout(); } }); } } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } 

Если я правильно понимаю ваши требования, то, как я сделал что-то вроде этого, нужно поместить scrollview вместе с чем-либо еще, что вы хотите отобразить под ним в Relative layout. Затем в вашем файле макета сначала поместите элемент в нижней части экрана в файл (с андроидом: layout_alignParentBottom = "true"), затем поместите вид прокрутки и поместите его над первым элементом, используя что-то вроде: android: layout_above = "@ идентификатор / firstItem". Подобно этому, в котором я помещал изображение в нижнюю часть, с просмотром прокрутки над ним, занимающим оставшееся пространство:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/searchByNameScreen" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center_horizontal" android:layout_marginTop="1dip" android:gravity="center_horizontal" android:orientation="vertical" > <ImageView android:id="@+id/bottomImage" android:layout_width="fill_parent" android:layout_height="75dip" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:paddingBottom="15dip" android:paddingLeft="10dip" android:paddingRight="10dip" android:paddingTop="7dip" android:scaleType="fitXY" android:src="@drawable/android_450x50_moreinfo" /> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ScrollView01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_above="@id/bottomImage" android:layout_marginBottom="3dip" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:layout_marginTop="1dip" android:scrollbars="none" > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/aboutCopyLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/aboutTopLayer" android:layout_centerHorizontal="true" android:layout_gravity="center_horizontal" android:background="@drawable/rounded_background" android:gravity="center" android:padding="5dip" > <!-- android:background="@drawable/rounded_background" --> <TextView android:id="@+id/aboutCopyText" style="@style/ResortNameExtraLine" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_horizontal" android:text="@string/aboutCopy" /> </LinearLayout> </ScrollView> </RelativeLayout> 

Здесь другое решение, использующее размеры вместо весов. Я расширил ScrollView и добавил код для реализации этой функции:

https://gist.github.com/JMPergar/439aaa3249fa184c7c0c

Надеюсь, это будет полезно.