Android: Warum gibt es kein maxHeight für eine Ansicht?

184

Ansichten haben eine,minHeight aber irgendwie fehlt eine maxHeight:

Was ich erreichen möchte, ist, dass einige Elemente (Ansichten) a ausfüllen ScrollView. Wenn es 1..3 Elemente gibt, möchte ich sie direkt anzeigen. Das heißt, die ScrollViewhat die Höhe von entweder 1, 2 oder 3 Elementen.

Wenn es 4 oder mehr Elemente gibt, möchte ich, dass das nicht ScrollViewmehr erweitert wird (also a maxHeight) und mit dem Scrollen beginnt.

Es gibt jedoch leider keine Möglichkeit, eine zu setzen maxHeight. Daher muss ich meine ScrollViewHöhe wahrscheinlich programmgesteuert entweder auf WRAP_CONTENT1..3 Elemente und auf 3*sizeOf(View)4 oder mehr Elemente einstellen .

Kann mir jemand erklären, warum es keine gibt maxHeight, wenn es schon eine gibt minHeight?

(Übrigens: Einige Ansichten ImageViewhaben eine maxHeightimplementiert.)

znq
quelle
Ich habe eine Lösung in einem anderen Thread gepostet: stackoverflow.com/questions/18425758/…
JMPergar
2
Ich habe eine Lösung dafür auf chintanrathod.com/…
Chintan Rathod
Das Entfernen von maxHeight durch Google ist ärgerlich und unpraktisch. Schauen Sie sich alle Dinge an, die Sie jetzt tun müssen, um das gleiche Ergebnis zu erzielen.
Ian Wambai

Antworten:

86

Keine dieser Lösungen funktionierte für das, was ich brauchte, nämlich eine ScrollView, die auf wrap_content gesetzt war, aber eine maxHeight hatte, sodass sie nach einem bestimmten Punkt nicht mehr expandierte und mit dem Scrollen begann. Ich habe einfach die onMeasure-Methode in ScrollView überschrieben.

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

Dies funktioniert möglicherweise nicht in allen Situationen, gibt mir aber mit Sicherheit die für mein Layout erforderlichen Ergebnisse. Und es geht auch auf den Kommentar von Madhu ein.

Wenn ein Layout unterhalb der Bildlaufansicht vorhanden ist, funktioniert dieser Trick nicht - madhu 5. März um 4:36 Uhr

zischen
quelle
1
Wann würde das nicht funktionieren? Dies scheint eine sehr saubere Lösung zu sein. Ich frage mich, warum sie es nicht in die XML implementiert haben.
Christophe Smet
1
Es würde wahrscheinlich nicht funktionieren, wenn Sie die Höhe manuell auf 240 einstellen würden. Ich habe mich nicht darum gekümmert, den Modus zu überprüfen, in dem sich die Bildlaufansicht befindet, da ich nur einen bestimmten Modus (wrap_content) unterstützen musste.
Whizzle
Für diese Antwort gibt es eine Bearbeitung mit der Aufschrift "Wenn ein Layout unterhalb der Bildlaufansicht vorhanden ist, funktioniert dieser Trick nicht", was nicht der Fall ist. Ich habe ein Layout am unteren Rand der Seite ausgerichtet und dieses benutzerdefinierte Layout hat "android: layout_above = '@ + ...'", wodurch das benutzerdefinierte Layout immer über dem unteren Layout platziert wird :)
Machine Tribe
70

Um ein ScrollViewoder ListViewmit einem maxHeight zu erstellen, müssen Sie nur ein transparentes lineares Layout mit einer Höhe erstellen, die der Höhe entspricht, die das maxHeight haben soll. Anschließend setzen Sie die Höhe von ScrollView auf wrap_content. Dadurch wird eine ScrollView erstellt, die scheinbar wächst, bis ihre Höhe dem übergeordneten LinearLayout entspricht.

Justin Morris
quelle
3
Dies war nützlich, um zu verhindern, dass ein Dialogfeld mit Bildlaufinhalten auf die gesamte Bildschirmhöhe erweitert wird.
Kyle Ivey
Ein kleiner Vorschlag wäre, ein FrameLayout anstelle eines LinearLayout zu verwenden, aber ich bezweifle, dass es wichtig ist.
Kyle Ivey
43
Wenn ein Layout unterhalb der Bildlaufansicht vorhanden ist, funktioniert dieser Trick nicht
Sreedhu Madhu
2
Können Sie bitte einen Code angeben? es hat bei mir nicht funktioniert, also mache ich vielleicht etwas falsch ...
Android-Entwickler
funktioniert nicht, wenn Sie Schaltflächen darunter haben. es wird die Tasten vom Bildschirm drücken
Li Tian Gong
43

Dies funktionierte für mich, um es in XML anpassbar zu machen:

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>

Beispiellayout

<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>
SlickDev
quelle
Das Erstellen einer benutzerdefinierten Ansicht ist definitiv der beste Weg, um dies zu erreichen.
Bertram Gilfoyle
Und das funktioniert, wenn Sie ein Layout unterhalb der Bildlaufansicht haben! Perfekt!
Ragaisis
25

(Ich weiß, dass dies die Frage nicht direkt beantwortet, aber für andere hilfreich sein kann, die nach maxHeight-Funktionalität suchen.)

ConstraintLayout bietet seinen Kindern maximale Körpergröße über

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

oder

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

Beispielnutzung hier .

user1506104
quelle
2
Dies funktioniert nicht, wenn sich die Ansicht in einer vertikalen Kette befindet (wie in den ConstraintLayout-Dokumenten angegeben)
Arno Schoonbee
Danke für die Information.
user1506104
8

Ich hätte die Antwort von whizzle kommentiert, wenn ich könnte, fand es aber nützlich zu bemerken, dass ich den Code geringfügig ändern musste, um dieses Problem im Kontext des Mehrfenstermodus in Android N zu lösen:

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

Dadurch kann die Größe des Layouts kleiner als die maximale Höhe sein, aber auch verhindert werden, dass es größer als die maximale Höhe ist. Ich habe diese Layoutklasse verwendet, die überschrieben wird. Dadurch RelativeLayoutkonnte ich einen benutzerdefinierten Dialog mit einem ScrollViewals untergeordnetem Dialogfeld erstellen MaxHeightRelativeLayout, das nicht die gesamte Bildschirmhöhe erweitert und auch verkleinert wird, um in die kleinste Witwengröße in Multi-Window für Android zu passen N.

JP Krause
quelle
4

Es gibt keine Möglichkeit, maxHeight einzustellen. Sie können jedoch die Höhe einstellen.

Dazu müssen Sie die Höhe jedes Elements Ihrer scrollView ermitteln. Danach setzen Sie einfach Ihre scrollView-Höhe auf numberOfItens * heightOfItem.

Um die Höhe eines Gegenstands zu ermitteln, gehen Sie wie folgt vor:

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

So stellen Sie die Höhe ein:

// 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));
Derzu
quelle
4

Wickeln Sie ScrollViewIhre Ebene LinearLayoutmit layout_height = "max_height" um Ihre Ebene , dies wird einen perfekten Job machen. Tatsächlich habe ich diesen Code in der Produktion der letzten 5 Jahre ohne Probleme.

<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>
Sai
quelle
1
Perfekte Lösung. Clever und einfach. Es ist sogar für die Recycling-Ansicht geeignet.
Alex Belets
3

Meine MaxHeightScrollViewbenutzerdefinierte Ansicht

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>

Verwenden von

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

    ...

</....MaxHeightScrollView>
Phan Van Linh
quelle
2

Ich habe hier eine Antwort:

https://stackoverflow.com/a/29178364/1148784

Erstellen Sie einfach eine neue Klasse, die ScrollView erweitert, und überschreiben Sie die onMeasureMethode.

    @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);
    }
babay
quelle
2

Wie oben erwähnt, bietet ConstraintLayout seinen Kindern maximale Körpergröße über:

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

Wenn die maximale Höhe für ein Kind von ConstraintLayout bis zur Ausführung der App ungewiss ist, kann dieses Kind außerdem automatisch eine veränderbare Höhe anpassen, unabhängig davon, wo es in der vertikalen Kette platziert wurde.

Zum Beispiel müssen wir einen unteren Dialog mit einer veränderlichen Kopfzeile TextView, einer veränderlichen ScrollView und einer veränderlichen Fußzeile TextView anzeigen. Die maximale Höhe des Dialogfelds beträgt 320 dp ,, wenn die Gesamthöhe 320 dp nicht erreicht. ScrollView fungiert als wrap_content, wenn die Gesamthöhe ScrollView überschreitet, fungiert als "maxHeight = 320 dp - Kopfzeilenhöhe - Fußzeilenhöhe".

Wir können dies nur durch eine XML-Layoutdatei erreichen:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="320dp">

    <TextView
        android:id="@+id/tv_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/black_10"
        android:gravity="center"
        android:padding="10dp"
        app:layout_constraintBottom_toTopOf="@id/scroll_view"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1"
        app:layout_constraintVertical_chainStyle="packed"
        tools:text="header" />

    <ScrollView
        android:id="@+id/scroll_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/black_30"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@id/tv_footer"
        app:layout_constraintHeight_max="300dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_header">

        <LinearLayout
            android:id="@+id/ll_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tv_sub1"
                android:layout_width="match_parent"
                android:layout_height="160dp"
                android:gravity="center"
                android:textColor="@color/orange_light"
                tools:text="sub1" />

            <TextView
                android:id="@+id/tv_sub2"
                android:layout_width="match_parent"
                android:layout_height="160dp"
                android:gravity="center"
                android:textColor="@color/orange_light"
                tools:text="sub2" />

        </LinearLayout>
    </ScrollView>

    <TextView
        android:id="@+id/tv_footer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/black_50"
        android:gravity="center"
        android:padding="10dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/scroll_view"
        tools:text="footer" />
</android.support.constraint.ConstraintLayout>

Der meiste Importcode ist kurz:

app:layout_constraintVertical_bias="1"
app:layout_constraintVertical_chainStyle="packed"

app:layout_constrainedHeight="true"

Die horizontale maxWidth-Nutzung ist ziemlich gleich.

xionghg
quelle
1

Haben Sie versucht, den Wert layout_weight zu verwenden ? ? Wenn Sie einen Wert größer als 0 festlegen, wird diese Ansicht auf den verbleibenden verfügbaren Speicherplatz ausgedehnt.

Wenn Sie mehrere Ansichten hatten, die gestreckt werden mussten, wird der Wert zu einem Gewicht zwischen ihnen.

Wenn Sie also zwei Ansichten auf den Wert layout_weight von 1 gesetzt hätten, würden sich beide dehnen, um den Raum auszufüllen, aber beide würden sich auf den gleichen Raum erstrecken. Wenn Sie einen von ihnen auf den Wert 2 setzen, wird er doppelt so stark gedehnt wie die andere Ansicht.

Weitere Informationen finden Sie hier unter Lineares Layout.

Bryan Denny
quelle
1
Das Problem mit den Gewichten ist, dass sie relativ sind. Unterschiedliche Bildschirmgrößen, unterschiedliche Ergebnisse, z. B. bei einem 800px-Bildschirm kann ich ein Gewicht auf einen bestimmten Wert einstellen, sodass ein bestimmter Bereich die gewünschten 200px ergibt. Bei einem 850px-Bildschirm ist der spezifische Bereich jedoch größer als 200px, aber die eingeschlossenen Elemente sind immer noch nur 200px groß. Deshalb habe ich es vorgezogen, einen zu haben, maxHeightden ich auf einen bestimmten Eintauchwert einstellen kann. (Ich endete schließlich damit, die Höhen programmgesteuert zu berechnen und einzustellen)
znq
1

Ich denke, Sie können die Höhe zur Laufzeit nur für 1 Element einstellen scrollView.setHeight(200px), für 2 Elemente scrollView.setheight(400px)für 3 oder mehrscrollView.setHeight(600px)

Yayo28
quelle
8
Sie möchten die Dimension nicht in 'px' festlegen. Es ist sehr wahrscheinlich, dass Sie auf mehreren Geräten nicht das gewünschte Ergebnis erzielen. developer.android.com/guide/topics/resources/…
Hernd DerBeld
@ HerndDerBeld so funktioniert es im Code. Wenn Sie möchten, können Sie jederzeit ganz einfach von DP in Pixel konvertieren: float pixels = TypedValue.applyDimension (TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources () .getDisplayMetrics ());
Android-Entwickler
1

Wie wir wissen, können Geräte mit Android unterschiedliche Bildschirmgrößen haben. Wie wir weiter wissen, sollten sich Ansichten dynamisch anpassen und zum geeigneten Raum werden.

Wenn Sie eine maximale Höhe festlegen, erzwingen Sie möglicherweise, dass die Ansicht nicht genügend Platz erhält oder weniger Platz benötigt. Ich weiß, dass es manchmal praktisch zu sein scheint, eine maximale Höhe einzustellen. Wenn sich die Auflösung jedoch jemals dramatisch ändern wird und dies auch!, Wird die Ansicht mit maximaler Höhe nicht angemessen aussehen.

Ich denke, es gibt keinen richtigen Weg, um genau das Layout zu machen, das Sie wollen. Ich würde Ihnen empfehlen, Ihr Layout mithilfe von Layout-Managern und relativen Mechanismen zu überdenken. Ich weiß nicht, was Sie erreichen wollen, aber es klingt für mich etwas seltsam, dass eine Liste nur drei Elemente enthalten sollte und der Benutzer dann scrollen muss.

Übrigens. minHeight ist nicht garantiert (und sollte vielleicht auch nicht existieren). Es kann einen gewissen Vorteil haben, die Sichtbarkeit von Elementen zu erzwingen, während andere relative Elemente kleiner werden.

Diego Frehner
quelle
6
Das ist falsch. Nach dieser Logik könnten Sie auch nicht sagen: android: layout_width = "500dp".
Glenn Maynard
Ich sehe weder, was falsch sein sollte, noch Ihre logische Interpretation. Wenn Sie layout_width festlegen (was manchmal in Ordnung ist), kann dies nicht garantiert werden. 500dp schauen vielleicht auf einem Gerät passend, auf einem anderen nicht. Layout Manager ftw! Vielleicht könnten Sie mehr bcs erklären, die die Abstimmung stört :)
Diego Frehner
3
Es ist genauso gültig, android: maxWidth = "500dp" zu sagen wie android: layout_width = "500dp". Beide erzwingen bestimmte Abmessungen in der Ansicht.
Glenn Maynard
1

Wenn jemand erwägt, einen genauen Wert für LayoutParams zu verwenden, z

setLayoutParams(new LayoutParams(Y, X );

Denken Sie daran, die Dichte der Geräteanzeige zu berücksichtigen, da sonst auf verschiedenen Geräten ein sehr merkwürdiges Verhalten auftreten kann. Z.B:

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

Ermitteln Sie zuerst die Elementhöhe in Pixel

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

dann einfach

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

Wenn ihr eine nicht überlaufende Bildlauf- oder Listenansicht erstellen wollt, aber nur in einem RelativeLayout mit einer Draufsicht und einer Unteransicht oben und unten dafür:

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@+id/topview"
    android:layout_below="@+id/bottomview" >
Ein Quoc Duy Nguyen
quelle
Dies erfordert mehr Kredit. Spezifische aber einfache Implementierung.
Luke Allison
0

Ich habe eine benutzerdefinierte ScrollView aus Kotlin verwendet, die verwendet maxHeight. Anwendungsbeispiel:

<com.antena3.atresplayer.tv.ui.widget.ScrollViewWithMaxHeight
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:maxHeight="100dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
</com.antena3.atresplayer.tv.ui.widget.ScrollViewWithMaxHeight>

Hier ist der Code von ScrollViewWidthMaxHeight:

import android.content.Context
import android.util.AttributeSet
import android.widget.ScrollView
import timber.log.Timber

class ScrollViewWithMaxHeight @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ScrollView(context, attrs, defStyleAttr) {

companion object {
    var WITHOUT_MAX_HEIGHT_VALUE = -1
}

private var maxHeight = WITHOUT_MAX_HEIGHT_VALUE

init {
    val a = context.obtainStyledAttributes(
        attrs, R.styleable.ScrollViewWithMaxHeight,
        defStyleAttr, 0
    )
    try {
        maxHeight = a.getDimension(
            R.styleable.ScrollViewWithMaxHeight_android_maxHeight,
            WITHOUT_MAX_HEIGHT_VALUE.toFloat()
        ).toInt()
    } finally {
        a.recycle()
    }
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    var heightMeasure = heightMeasureSpec
    try {
        var heightSize = MeasureSpec.getSize(heightMeasureSpec)
        if (maxHeight != WITHOUT_MAX_HEIGHT_VALUE) {
            heightSize = maxHeight
            heightMeasure = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST)
        } else {
            heightMeasure = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.UNSPECIFIED)
        }
        layoutParams.height = heightSize
    } catch (e: Exception) {
        Timber.e(e, "Error forcing height")
    } finally {
        super.onMeasure(widthMeasureSpec, heightMeasure)
    }
}

fun setMaxHeight(maxHeight: Int) {
    this.maxHeight = maxHeight
}
}

das braucht auch diese Erklärung in values/attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ScrollViewWithMaxHeight">
        <attr name="android:maxHeight" />
    </declare-styleable>
</resources>
Mario Velasco
quelle