安卓 ScrollView 布局(wrap_content,最大尺寸)

5

这是我希望我的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开始使其工作。


你为什么叫它“layout_weight”?不应该是类似于“layout_max_height”的名称吗? - android developer
5个回答

7
我最终编写了自己的类,扩展了 ScrollView。
既然你问了...这里是代码。可能不是最干净的,但它做到了我想要的效果。
请注意,它期望在视图创建时设置 layout_weight,并且您不应该在父 LinearLayout 中设置 weightSum,否则会出现奇怪的情况(因为 ScrollView 的内容大小会使此值从原始值更改为 0)。
首先,在布局文件中,视图的声明如下:
<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);
        }
    }
}

您本可以在您的实现/解决方案中发布更多细节。 - Ovidiu Latcu
能否将最大高度设置为dp而不是权重?如果可以,怎么做? - android developer
也许你想要检查这个:https://dev59.com/qG855IYBdhLWcg3w-JXR - Matthieu

0
JMpergar的回答似乎是正确的,但在我将onMeasure方法更改如下之前它并没有起作用。
 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        try {
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            if (maxHeight != WITHOUT_MAX_HEIGHT_VALUE
                    && heightSize > maxHeight) {
                heightSize = maxHeight;
                heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST);
                getLayoutParams().height = heightSize;

            } else {
                heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST);
                setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec)
                        , getDefaultSize(this.getSuggestedMinimumHeight(), heightMeasureSpec));
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

0

你可以将你的ScrollView包裹在另一个ConstraintLayout中,然后约束高度(使用app:layout_constrainedHeight="true"):

<!-- another constraint layout to keep ScrollView shrinking -->
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constrainedHeight="true"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent">

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:id="@+id/content_layout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

0
如果我正确理解您的要求,我实现这样的功能的方法是将ScrollView与其他任何想要在其下显示的内容放置在RelativeLayout中。然后,在您的布局文件中,首先将项目放置在屏幕底部(使用android:layout_alignParentBottom =“true”),然后放置滚动视图并使用诸如android:layout_above =“@ id / firstItem”之类的内容将其放置在第一个项目上方。就像这样,我在底部放置了一个ImageView,上面是一个占据剩余空间的ScrollView:
<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>

需要尝试一下...不过我有几个问题...看起来"orientation"对于RelativeLayout不太合适?我不想让ScrollView下面的内容在屏幕底部...如果我也从上到下填充布局,它会起作用吗?我认为这可能是一个很好的替代方案,尽管我不能像LinearLayout那样使用任何权重。 - Matthieu

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接