Android: почему нет maxHeight для просмотра?

Просмотр имеет minHeight, но как-то не хватает maxHeight:

То, что я пытаюсь достичь, состоит в том, что некоторые элементы (представления) заполняют ScrollView. Когда есть 1..3 элемента, я хочу отображать их напрямую. Значение ScrollView имеет высоту в 1, 2 или 3 элемента.

Когда есть 4 или более элементов, я хочу, чтобы ScrollView прекратил расширение (таким образом, maxHeight) и начал предоставлять прокрутку.

Однако, к сожалению, нет способа установить maxHeight. Поэтому я, вероятно, должен установить свою ScrollView высоту программно или WRAP_CONTENT, когда есть 1..3 элемента, и установите высоту на 3*sizeOf(View), когда есть 4 или более элементов.

Может ли кто-нибудь объяснить, почему нет maxHeight при условии, что уже есть minHeight?

(BTW: некоторые представления, например ImageView, имеют maxHeight.)

Ответ 1

Ни одно из этих решений не работало для того, что мне было нужно, это был набор ScrollView для wrap_content, но имеющий maxHeight, поэтому он перестанет расширяться после определенного момента и начнет прокрутку. Я просто просто переопределяю метод onMeasure в ScrollView.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    heightMeasureSpec = MeasureSpec.makeMeasureSpec(300, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

Это может не работать во всех ситуациях, но это, безусловно, дает мне результаты, необходимые для моего макета. И он также рассматривает комментарий мадху.

Если какой-то макет присутствует ниже прокрутки, тогда этот трюк не будет работать - мадху 5 марта в 4:36

Ответ 2

Чтобы создать ScrollView или ListView с maxHeight, вам просто нужно создать прозрачный LinearLayout вокруг него с высотой того, что вы хотите, чтобы maxHeight был. Затем установите высоту ScrollView Height на wrap_content. Это создает ScrollView, который, кажется, растет до тех пор, пока его высота не будет равна родительскому LinearLayout.

Ответ 3

Это помогло мне настроить его в xml:

MaxHeightScrollView.java:

public class MaxHeightScrollView extends ScrollView {

private int maxHeight;
private final int defaultHeight = 200;

public MaxHeightScrollView(Context context) {
    super(context);
}

public MaxHeightScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
    if (!isInEditMode()) {
        init(context, attrs);
    }
}

public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    if (!isInEditMode()) {
        init(context, attrs);
    }
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    if (!isInEditMode()) {
        init(context, attrs);
    }
}

private void init(Context context, AttributeSet attrs) {
    if (attrs != null) {
        TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView);
        //200 is a defualt value
        maxHeight = styledAttrs.getDimensionPixelSize(R.styleable.MaxHeightScrollView_maxHeight, defaultHeight);

        styledAttrs.recycle();
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

attr.xml

<declare-styleable name="MaxHeightScrollView">
        <attr name="maxHeight" format="dimension" />
    </declare-styleable>

пример макета

<blah.blah.MaxHeightScrollView android:layout_weight="1"
                app:maxHeight="90dp"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content">
                <EditText android:id="@+id/commentField"
                    android:hint="Say Something"
                    android:background="#FFFFFF"
                    android:paddingLeft="8dp"
                    android:paddingRight="8dp"
                    android:gravity="center_vertical"
                    android:maxLines="500"
                    android:minHeight="36dp"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content" />
            </blah.blah.MaxHeightScrollView>

Ответ 4

(Я знаю, что это не дает прямого ответа на вопрос, но может быть полезно для других, которым нужна функциональность maxHeight)

ConstraintLayout предлагает максимальную высоту для своих детей через

app:layout_constraintHeight_max="300dp"
app:layout_constrainedHeight="true" 

или

app:layout_constraintWidth_max="300dp"
app:layout_constrainedWidth="true" 

Пример использования здесь.

Ответ 5

Я бы прокомментировал ответ whizzle, если мог, но подумал, что полезно отметить, что для того, чтобы решить эту проблему в контексте многооконного режима в Android N, мне нужно немного изменить код

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if(MeasureSpec.getSize(heightMeasureSpec) > maxHeight) {
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

Это позволяет изменять размер макета по сравнению с максимальной высотой, но также не позволяет ему превышать максимальную высоту. Я использовал это класс макета, который переопределяет RelativeLayout, и это позволило мне создать настраиваемый диалог с ScrollView как дочерний элемент MaxHeightRelativeLayout, который не расширяет всю высоту экрана, а также сжимается, чтобы соответствовать наименьший размер вдова в многоэкранном режиме для Android N.

Ответ 6

Невозможно установить maxHeight. Но вы можете установить высоту.

Для этого вам нужно будет определить высоту каждого элемента вашего scrollView. После этого просто установите высоту scrollView в numberOfItens * heightOfItem.

Для обнаружения высоты элемента выполните следующее:

View item = adapter.getView(0, null, scrollView);
item.measure(0, 0);
int heightOfItem = item.getMeasuredHeight();

Чтобы установить высоту, сделайте следующее:

// if the scrollView already has a layoutParams:
scrollView.getLayoutParams().height = heightOfItem * numberOfItens;
// or
// if the layoutParams is null, then create a new one.
scrollView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, heightOfItem * numberOfItens));

Ответ 7

Мой MaxHeightScrollView пользовательский вид

public class MaxHeightScrollView extends ScrollView {
    private int maxHeight;

    public MaxHeightScrollView(Context context) {
        this(context, null);
    }

    public MaxHeightScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray styledAttrs =
                context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView);
        try {
            maxHeight = styledAttrs.getDimensionPixelSize(R.styleable.MaxHeightScrollView_mhs_maxHeight, 0);
        } finally {
            styledAttrs.recycle();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (maxHeight > 0) {
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

style.xml

<declare-styleable name="MaxHeightScrollView">
    <attr name="mhs_maxHeight" format="dimension" />
</declare-styleable>

Использование

<....MaxHeightScrollView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:mhs_maxHeight="100dp"
    >

    ...

</....MaxHeightScrollView>

Ответ 8

Вы пытались использовать значение layout_weight? Если вы установите его на значение больше 0, оно растянет это представление на оставшееся свободное пространство.

Если у вас было несколько видов, которые нужно было растянуть, тогда значение станет весом между ними.

Итак, если у вас было два представления, то оба значения равны 1, тогда они оба растягиваются, чтобы заполнить пробел, но они оба растянутся до равного количества пространства. Если вы установите одно из них на значение 2, оно будет растягиваться в два раза больше, чем другое.

Дополнительная информация приведена в разделе "Линейная компоновка" .

Ответ 9

Как мы знаем, устройства, работающие под управлением Android, могут иметь разные размеры экрана. Поскольку мы также знаем, что представления должны динамически регулироваться и стать подходящим пространством.

Если вы установите максимальную высоту, вы можете заставить вид не получить достаточное пространство или заняться меньшим пространством. Я знаю, что иногда кажется, что практически устанавливается максимальная высота. Но если разрешение будет когда-либо изменяться, и оно будет!, то представление, которое имеет максимальную высоту, будет выглядеть не соответствующим.

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

кстати. minHeight не гарантируется (и, возможно, также не должен существовать). он может иметь некоторую выгоду, чтобы заставить элементы быть видимыми, в то время как другие относительные элементы становятся меньше.

Ответ 10

Если кто-то рассматривает использование точного значения для LayoutParams, например.

setLayoutParams(new LayoutParams(Y, X );

Не забывайте учитывать плотность дисплея устройства, иначе вы можете получить очень странное поведение на разных устройствах. Например:

Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics d = new DisplayMetrics();
display.getMetrics(d);
setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, (int)(50*d.density) ));

Ответ 11

Оберните ваш ScrollView вокруг вашей простой LinearLayout с layout_height = "max_height", это отлично подойдет. На самом деле, у меня есть этот код в производстве за последние 5 лет с нулевыми проблемами.

<LinearLayout
        android:id="@+id/subsParent"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:gravity="bottom|center_horizontal"
        android:orientation="vertical">

        <ScrollView
            android:id="@+id/subsScroll"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:layout_marginEnd="15dp"
            android:layout_marginStart="15dp">

            <TextView
                android:id="@+id/subsTv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/longText"
                android:visibility="visible" />

        </ScrollView>
    </LinearLayout>

Ответ 12

Я думаю, что u может установить heiht во время выполнения для одного элемента только scrollView.setHeight(200px), для 2 элементов scrollView.setheight(400px) для 3 или более scrollView.setHeight(600px)

Ответ 13

Сначала получите высоту элемента в пикселях

View rowItem = adapter.getView(0, null, scrollView);   
rowItem.measure(0, 0);    
int heightOfItem = rowItem.getMeasuredHeight();

тогда просто

Display display = getWindowManager().getDefaultDisplay();    
DisplayMetrics displayMetrics = new DisplayMetrics();    
display.getMetrics(displayMetrics);    
scrollView.getLayoutParams().height = (int)((heightOfItem * 3)*displayMetrics .density);

Ответ 14

если вы, ребята, хотите создать прокрутку без переполнения или listview, просто, но на RelativeLayout с верхним и нижним окнами сверху и снизу:

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@+id/topview"
    android:layout_below="@+id/bottomview" >

Ответ 15

У меня есть ответ здесь:

fooobar.com/info/44905/...

Просто создайте новый класс, расширяющий ScrollView, и переопределите его метод onMeasure.

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (maxHeight > 0){
            int hSize = MeasureSpec.getSize(heightMeasureSpec);
            int hMode = MeasureSpec.getMode(heightMeasureSpec);

            switch (hMode){
                case MeasureSpec.AT_MOST:
                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.min(hSize, maxHeight), MeasureSpec.AT_MOST);
                    break;
                case MeasureSpec.UNSPECIFIED:
                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
                    break;
                case MeasureSpec.EXACTLY:
                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.min(hSize, maxHeight), MeasureSpec.EXACTLY);
                    break;
            }
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }