7

I am creating a custom class to set the max height of a NestedScrollView, based on the answer provided in this StackOverflow question:

How to set the Maximum Height for a NestedScrollView in Android?

However, when I include the custom class (MaxHeightNestedScrollView) in my activity_main.xml code layout, there is no scrollbar appearing when the TextView inside the MaxHeightNestedScrollView exceeds the defined max height. Below is the code for MaxNestedScrollView:

import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.widget.NestedScrollView;

public class MaxHeightNestedScrollView extends NestedScrollView {

    private int maxHeight = -1;

    public MaxHeightNestedScrollView(@NonNull Context context) {
        super(context);
    }

    public MaxHeightNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MaxHeightNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public int getMaxHeight() {
        return maxHeight;
    }

    public void setMaxHeight(int maxHeight) {
        this.maxHeight = maxHeight;
    }

    public void setMaxHeightDensity(int dps){
        this.maxHeight = (int)(dps * getContext().getResources().getDisplayMetrics().density);
    }

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

Below is the code for the attrs.xml file in the values folder:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MaxHeightNestedScrollView">
        <attr name="maxHeight" format="dimension" />
    </declare-styleable>
</resources>

Below is the code for activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffffff"
        android:layout_weight="1"
        android:fillViewport="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <TextView
                android:id="@+id/textView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Lorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
\nLorem ipsum\nLorem ipsum\nLorem ipsum" />

            <com.example.testgradle.MaxHeightNestedScrollView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                app:maxHeight="130dp">
                <TextView
                    android:id="@+id/textView2"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textSize="20dp"
                    android:textColor="#000000"
                    android:text="Lorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
\nLorem ipsum\nLorem ipsum\nLorem ipsumLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
\nLorem ipsum\nLorem ipsum\nLorem ipsum" />
            </com.example.testgradle.MaxHeightNestedScrollView>

            <TextView
                android:id="@+id/textView3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Lorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
\nLorem ipsum\nLorem ipsum\nLorem ipsum" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>
Adam Lee
  • 354
  • 1
  • 9
  • 21
  • `MaxHeightNestedScrollView ` will only work when you set "maxHeight" programmatically. Check my answer to make it work with xml "maxHeight" attribute. – Akhilesh Kumar Jan 16 '20 at 09:19

2 Answers2

6

Your MaxHeightNestedScrollView is incomplete, as it does not specify how to use maxHeight attribute from xml. Use below modified MaxHeightNestedScrollView class(Difference are commented out).

MaxHeightNestedScrollView.java

public class MaxHeightNestedScrollView extends NestedScrollView {

private int maxHeight = -1;

public MaxHeightNestedScrollView(@NonNull Context context) {
    this(context, null, 0); // Modified changes
}

public MaxHeightNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0); // Modified changes
}

public MaxHeightNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context, attrs, defStyleAttr); // Modified changes
}

 // Modified changes
private void init(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr){
    final TypedArray a = context.obtainStyledAttributes(
            attrs, R.styleable.MaxHeightNestedScrollView, defStyleAttr, 0);
    maxHeight = 
    a.getDimensionPixelSize(R.styleable.MaxHeightNestedScrollView_maxHeight, 0);
    a.recycle();
}

public int getMaxHeight() {
    return maxHeight;
}

public void setMaxHeight(int maxHeight) {
    this.maxHeight = maxHeight;
}

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


Also to show scrollbar in NestingScrollView just add android:scrollbars="vertical" attribute to your MaxHeightNestedScrollView view in xml.
After changes your layout file will look like.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:layout_weight="1"
    android:fillViewport="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Lorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
            \nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem 
            ipsum\nLorem ipsum
            \nLorem ipsum\nLorem ipsum\nLorem ipsum" />

        <com.example.testgradle.MaxHeightNestedScrollView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:scrollbars="vertical" // Modified changes
            app:maxHeight="130dp">
            <TextView
                android:id="@+id/textView2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="20dp"
                android:textColor="#000000"
                android:text="Lorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
                \nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
                \nLorem ipsum\nLorem ipsum\nLorem ipsumLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
                \nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
                \nLorem ipsum\nLorem ipsum\nLorem ipsum" />
        </com.example.testgradle.MaxHeightNestedScrollView>

        <TextView
            android:id="@+id/textView3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Lorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
            \nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum\nLorem ipsum
            \nLorem ipsum\nLorem ipsum\nLorem ipsum" />
    </LinearLayout>
</ScrollView>
</LinearLayout>

Hope this help.

Akhilesh Kumar
  • 727
  • 1
  • 5
  • 11
0

You're wrapping the height to wrap_content of your custom scrollView

<com.example.testgradle.MaxHeightNestedScrollView
            android:layout_width="match_parent"
            android:layout_height="provide your desired height"
            android:scrollbars="vertical"
            android:fadeScrollbars="false">
  • This does not satisfy the requirements. Even when the text does not expand to the maxHeight, the MaxHeightNestedScrollView widget will be set to the maxHeight. – Henry Zhu Jan 16 '20 at 07:27
  • @HenryZhu I Updated answer. if you don't want to hide scrollbar automatically then android:fadeScrollbars="false" as per the snippet. – Dhruvan Bhalara Jan 16 '20 at 07:42