How to set a maximum height with wrap content in android?
Asked Answered
N

8

39

In android, how can you create a scroll view that's got a max height, and wrap contents, basically it wraps the content vertically, but has a maximum height?

I tried

<ScrollView 
     android:id="@+id/scrollView1"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
         android:maxHeight="200dp"
     android:layout_alignParentBottom="true" >

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

    </LinearLayout>
</ScrollView>

But this isn't working?

Neoptolemus answered 25/8, 2013 at 4:39 Comment(1)
here is another solution to the problem: #42694855Underclay
S
36

you can add this to any view (override onMeasure in a class inherited from a view)

@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);
}
Sotted answered 21/3, 2015 at 1:49 Comment(2)
how to use this?Frangible
@Frangible extend some view class, override onMeasure method of the class.Sotted
P
22

I've extended ScrollView and added code to implement this feature:

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

I hope that be useful.

Phenanthrene answered 5/11, 2014 at 13:40 Comment(1)
This implementation works at once. The only thing I would add is the maxHeight parameter in a/the res/values/attrs.xml file to be able to specify it right in the XML (developer.android.com/training/custom-views/…)Didactics
E
21

You can do it programmatically.

 private static class OnViewGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
    private final static int maxHeight = 130;
    private View view;

    public OnViewGlobalLayoutListener(View view) {
        this.view = view;
    }

    @Override
    public void onGlobalLayout() {
        if (view.getHeight() > maxHeight)
            view.getLayoutParams().height = maxHeight;
    }
}

And add listener to the view:

view.getViewTreeObserver()
                  .addOnGlobalLayoutListener(new OnViewGlobalLayoutListener(view));

Listener will call method onGlobalLayout(), when view height will be changed.

Enphytotic answered 20/1, 2015 at 9:58 Comment(3)
I think that you need to remove the void on your OnViewGlobalLayoutListener(View view) constructor.Johnie
I like this solution because it avoids the need for a custom View class, and can therefore be applied to any View type. By the way, it didn't work for me at first - I had to modify the way you set the height to use setLayoutParams after modifying the LayoutParams retrieved from getLayoutParams (as described at https://mcmap.net/q/127602/-how-to-resize-a-custom-view-programmatically/995218).Reprobative
The best Answer I have Found, I give an answer some modifiedClementina
S
7

It can be done by wrapping the view into ConstraintLayout and using layout_constraintHeight_max attribute.

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="200dp">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHeight_max="wrap"
        app:layout_constraintVertical_bias="0">

        ...

    </ScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>

In the example above, the parent ConstraintLayout height is limited to 200dp, and the child ScrollView height wraps the content till it's less than 200dp. Note that app:layout_constraintVertical_bias="0" aligns the child ScrollView at the top of the parent, otherwise it will be centered.

Seay answered 3/8, 2020 at 9:33 Comment(1)
This works for my requirement thanks @Valeriy katkovVertigo
W
0

for set scrollview height you must use 2 linerlayout inside together and then set scrool view as them child then set middle linerlayout layout:height for limit scrollview height.

Waylen answered 28/5, 2016 at 15:33 Comment(0)
T
0

1.) Create a class to handle setting maximum height to what is passed by the user:

public class OnViewGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {


private Context context;
private int maxHeight;
private View view;

public OnViewGlobalLayoutListener(View view, int maxHeight, Context context) {
    this.context = context;
    this.view = view;
    this.maxHeight = dpToPx(maxHeight);
}

@Override
public void onGlobalLayout() {
    if (view.getHeight() > maxHeight) {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        params.height = maxHeight;
        view.setLayoutParams(params);
    }
}

public int pxToDp(int px) {
    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    int dp = Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
    return dp;
}

public int dpToPx(int dp) {
    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
    return px;
}
}

2.) Attach this to the view and pass the maximum height in DP:

messageBody.getViewTreeObserver()
            .addOnGlobalLayoutListener(
             new OnViewGlobalLayoutListener(messageBody, 256, context)
             );

Thanks to @harmashalex for the inspiration. I made modifications to as setting the layout params didn't work by @harma's code. Also, dp-to-px conversion is necessary to offload wondering about it.

Thunell answered 28/9, 2019 at 20:11 Comment(0)
C
0

Some modification of harmashalex answer, I can pass desired max height for any view :

    import android.view.View;
    import android.view.ViewTreeObserver;
    
    public class MaxHeightForAnyView implements ViewTreeObserver.OnGlobalLayoutListener{
    
        private   int maxHeight = 130;
        private View view;
    
        public MaxHeightForAnyView(View view, int maxHeight) {
            this.view = view;
            this.maxHeight = maxHeight ;
        }
        @Override
        public void onGlobalLayout() {
            if (view.getHeight() > maxHeight)
                view.getLayoutParams().height = maxHeight;
        }
     
}

And just set the listener to any view in oncreate with desired height :

txtShowTrans.getViewTreeObserver().addOnGlobalLayoutListener(new MaxHeightForAnyView(txtShowTrans, 600));
Clementina answered 22/4 at 10:26 Comment(0)
C
-7

Here you can set height of your Scrollview like this -:

<ScrollView 
 android:id="@+id/scrollView1"
 android:layout_width="match_parent"
 android:layout_height="200dp"
 android:layout_alignParentBottom="true" >

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

           </LinearLayout>
</ScrollView>
Curriculum answered 25/8, 2013 at 6:3 Comment(1)
Certainly doesn't answer the question!Robert

© 2022 - 2024 — McMap. All rights reserved.