Android:ビューにmaxHeightがないのはなぜですか?


184

ビューにはありますminHeightが、どういうわけか欠けていmaxHeightます:

私が達成しようとしているのは、いくつかの項目(ビュー)を埋めることScrollViewです。1..3のアイテムがある場合、直接表示したい。の意味はScrollView、1、2、または3項目の高さです。

4つ以上のアイテムがある場合は、ScrollView展開を停止して(したがってmaxHeight)、スクロールの提供を開始します。

ただし、を設定する方法はありませんmaxHeight。したがって、おそらく1..3のアイテムがある場合はScrollViewプログラムでWRAP_CONTENT高さを設定し、3*sizeOf(View)4つ以上のアイテムがある場合は高さを設定する必要があります。

maxHeightすでに存在するのに、なぜ提供されていないのか誰かが説明できますminHeightか?

(ところでImageViewmaxHeight実装されているようないくつかのビュー。)


私は他のスレッドで解決策を掲載しました: stackoverflow.com/questions/18425758/...
JMPergar


GoogleがmaxHeightを削除するのは面倒で不便です。同じ結果を得るために今しなければならないことをすべて見てください。
Ian Wambai 2017

回答:


86

これらのソリューションはどれも、wrap_contentに設定されたScrollViewである必要なものに対して機能しませんでしたが、maxHeightがあるため、特定のポイントの後で展開が停止し、スクロールが開始されます。単にScrollViewのonMeasureメソッドをオーバーライドしました。

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

これはすべての状況で機能するわけではありませんが、レイアウトに必要な結果が確実に得られます。また、madhuのコメントにも対応しています。

スクロールビューの下にレイアウトが存在する場合、このトリックは機能しません– madhu Mar 5 at 4:36


1
これはいつうまくいきませんか?これは非常にクリーンなソリューションのようです。彼らがなぜそれをxmlに実装しなかったのか不思議に思います。
Christophe Smet 14年

1
高さを手動で240に設定した場合は、おそらく機能しません。1つの特定のモード(wrap_content)のみをサポートする必要があるため、スクロールビューのモードを確認する必要はありませんでした。
2014年

「スクロールビューの下にレイアウトが存在する場合、このトリックは機能しません」というこの回答の編集がありますが、これは正しくありません。ページの下部に配置されたレイアウトがあり、このカスタムレイアウトには「android:layout_above = '@ + ...'」があり、常にカスタムレイアウトが下部レイアウトの上に配置されます:)
Machine Tribe

70

作成するために、ScrollViewまたはListViewのmaxHeightであなたはちょうどあなたがのmaxHeightになりたいものの高さとその周りの透明のLinearLayoutを作成する必要があります。次に、ScrollViewの高さをに設定しwrap_contentます。これにより、高さが親のLinearLayoutと等しくなるまで拡大するように見えるScrollViewが作成されます。


3
これは、コンテンツがスクロールするダイアログが画面の高さいっぱいに拡大するのを防ぐのに役立ちました。
Kyle Ivey

小さな提案は、LinearLayoutの代わりにFrameLayoutを使用することですが、それが重要であるとは思いません。
Kyle Ivey

43
スクロールビューの下にレイアウトが存在する場合、このトリックは機能しません
Sreedhu Madhu

2
コードを提供していただけますか?それは私にとってはうまくいきませんでした、それでおそらく私は何か間違ったことをしています...
アンドロイド開発者

その下にボタンがある場合は機能しません。それはボタンを画面から押し出します
Li Tian Gong

43

これは私にとってそれを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>

これを実現するには、カスタムビューを作成することが間違いなく最善の方法です。
バートラムギルフォイル2018年

そして、これはスクロールビューの下にレイアウトがある場合に機能します!パーフェクト!
Ragaisis

25

(私はこれが質問に直接回答しないことを知っていますが、maxHeight機能を探している他の人に役立つかもしれません)

ConstraintLayoutはその子に最大の高さを提供します

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

または

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

使用例はこちら


2
(ConstraintLayoutのドキュメントで指定されているように)ビューが垂直チェーンにある場合、これは機能しません
Arno Schoonbee

情報をありがとう。
user1506104

8

できればウィズルの答えについてコメントしましたが、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


4

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));

4

あなたのラップScrollViewあなたの平野を周りLinearLayoutlayout_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>

1
確かに完璧なソリューション。賢くてシンプル。recyclerviewにも適しています。
Alex Belets

3

私の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>

2

私はここに答えがあります:

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

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);
    }

2

上記のように、ConstraintLayoutは次の方法で子に最大の高さを提供します。

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

さらに、1つのConstraintLayoutの子の最大の高さがアプリの実行まで不確かな場合でも、垂直のチェーンのどこに配置されていても、変更可能な高さにこの子を自動的に適応させる方法があります。

たとえば、可変のヘッダーTextView、可変のScrollView、可変のフッターTextViewを備えた下部のダイアログを表示する必要があります。ダイアログの最大の高さは320dpです。合計の高さが320dpに達しない場合、ScrollViewはwrap_contentとして機能し、合計の高さがScrollViewを超える場合は、「maxHeight = 320dp-ヘッダーの高さ-フッターの高さ」として機能します。

これは、xmlレイアウトファイルを使用するだけで実現できます。

<?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>

ほとんどのインポートコードは短いです:

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

app:layout_constrainedHeight="true"

水平方向のmaxWidthの使用法はまったく同じです。


1

layout_weight値を使用してみましたかか?1つを0より大きい値に設定すると、そのビューが残りの使用可能なスペースに拡大されます。

ストレッチする必要がある複数のビューがある場合、値はそれらの間の重みになります。

したがって、layout_weight値が1に設定された2つのビューがある場合、両方ともスペースを埋めるために伸びますが、同じ量のスペースまで伸びます。それらの1つを値2に設定すると、他のビューの2倍に拡大されます。

リニアレイアウトの下にリストされているいくつかの詳細情報。


1
重みの問題は、それらが相対的であることです。さまざまな画面サイズ、さまざまな結果、たとえば800ピクセルの画面では、特定の領域に希望の200ピクセルになるように、重みを特定の値に設定できます。ただし、850ピクセルの画面では、特定の領域は200ピクセルより大きくなりますが、囲まれた要素はまだ200ピクセルしかありません。それmaxHeightが私が特定のディップ値に設定できるものを持つことを好んだ理由です。(最終的にプログラムで高さを計算して設定することになりました)
znq

1

実行時に高さを1アイテムだけscrollView.setHeight(200px)に、2アイテムscrollView.setheight(400px)を3以上に設定できると思いますscrollView.setHeight(600px)


8
ディメンションを「px」に設定する必要はありません。複数のデバイスで必要な結果が得られない可能性が非常に高いです。developer.android.com/guide/topics/resources/...
Hernd DerBeld

@HerndDerBeldそれがコードでどのように機能するかです。必要に応じて、常にDPからピクセルに簡単に変換できます。
Android開発者、

1

私たちが知っているように、androidを実行しているデバイスは異なる画面サイズを持つことができます。さらに知っているように、ビューは動的に調整され、適切なスペースになるはずです。

最大の高さを設定した場合は、ビューに十分なスペースを確保しないか、スペースを少なくしてください。最大の高さを設定するのが実際的であるように見える場合があることを知っています。ただし、解像度が劇的に変化し、変化する場合、最大の高さのビューは適切に見えません。

私はあなたが望むレイアウトを正確に行う適切な方法はないと思います。レイアウトマネージャーと相対メカニズムを使用してレイアウトを検討することをお勧めします。何を達成しようとしているのかわかりませんが、リストに3つの項目しか表示されず、ユーザーがスクロールしなければならないのは少し奇妙に思えます。

ところで。minHeightは保証されていません(おそらく存在しないはずです)。他の相対的なアイテムが小さくなる一方で、アイテムを強制的に表示することにはいくつかの利点があります。


6
これは間違っています。このロジックでは、android:layout_width = "500dp"とも言えません。
Glenn Maynard

私はあなたの論理解釈も何が間違っているべきかわかりません。layout_widthを設定した場合(これで問題ないこともあります)、それが得られるとは限りません。500 dpは、適切なデバイスとそうでないデバイスで見ている可能性があります。レイアウトマネージャーftw!たぶん、あなたは反対投票の邪魔になるより多くのbcsを説明することができます:)
Diego Frehner

3
android:maxWidth = "500dp"と言っても、android:layout_width = "500dp"と言っても同じです。どちらもビューに特定の寸法を強制します。
Glenn Maynard

1

誰かが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) ));

0

最初にアイテムの高さをピクセル単位で取得します

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);

0

オーバーフローではないスクロールビューまたはリストビューを作成したい場合は、RelativeLayoutでトップビューとボトムビューを上下に配置します。

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

これにはもっとクレジットが必要です。具体的だがシンプルな実装。
ルークアリソン

0

を使用するKotlin製のカスタムScrollViewを使用しましたmaxHeight。使用例:

<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>

ここにコードがあります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
}
}

この宣言も必要ですvalues/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ScrollViewWithMaxHeight">
        <attr name="android:maxHeight" />
    </declare-styleable>
</resources>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.