material-components / material-components-android

Modular and customizable Material Design UI components for Android
Apache License 2.0
16.27k stars 3.06k forks source link

[MaterialButtonToggleGroup] Some buttons are not reachable when MaterialButtonToggleGroup is used inside a HorizontalScrollView #1457

Closed MasoudFallahpour closed 4 years ago

MasoudFallahpour commented 4 years ago

Description: I want to display a single selection list of buttons using MaterialButtonToggleGroup. Because of the number of buttons that I want to display, some buttons go beyond the edge of the screen so I nested the MaterialButtonToggleGroup inside a HorizontalScrollView. When I set android:layout_gravity="center" on MaterialButtonToggleGroup some buttons could not be reached with scrolling. If I remove android:layout_gravity="center" then everything works fine.

Here are some screenshots. In the first screenshot button "A" is out of reach and button "B" is partially displayed. In the second one I scrolled to the right and there is a huge gap after the last button.

Screenshot_1593776619 Screenshot_1593776926

Expected behavior: All buttons should be reachable no matter what android:layout_gravity is used.

Source code: The following layout demonstrates the issue.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="match_parent"
    tools:context=".MainActivity">

    <HorizontalScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center">

        <com.google.android.material.button.MaterialButtonToggleGroup
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            app:checkedButton="@id/cButton">

            <com.google.android.material.button.MaterialButton
                android:id="@+id/aButton"
                style="?attr/materialButtonOutlinedStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="A" />

            <com.google.android.material.button.MaterialButton
                android:id="@+id/bButton"
                style="?attr/materialButtonOutlinedStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="B" />

            <com.google.android.material.button.MaterialButton
                android:id="@+id/cButton"
                style="?attr/materialButtonOutlinedStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="C" />

            <com.google.android.material.button.MaterialButton
                android:id="@+id/dButton"
                style="?attr/materialButtonOutlinedStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="D" />

            <com.google.android.material.button.MaterialButton
                android:id="@+id/eButton"
                style="?attr/materialButtonOutlinedStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="E" />

            <com.google.android.material.button.MaterialButton
                android:id="@+id/fButton"
                style="?attr/materialButtonOutlinedStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="F" />

            <com.google.android.material.button.MaterialButton
                android:id="@+id/gButton"
                style="?attr/materialButtonOutlinedStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="G" />

        </com.google.android.material.button.MaterialButtonToggleGroup>

    </HorizontalScrollView>

</FrameLayout>

Android API version: 29

Material Library version: 1.3.0-alpha01

Device: Any device

ymarian commented 4 years ago

This works as intended. You don't want to center inside a ScrollView.

You want to change the starting scroll position. This is very unnatural because if you think of scrollable content you wouldn't want to hide the beginning.

Regardless what you want could be something like this:

 override fun onResume() {
        super.onResume()
        scrollView.post {
            val position = (toggleGroup.width - scrollView.width) / 2f;
            scrollView.scrollTo(position.toInt(), 0);
        }
    }
ebraminio commented 2 years ago

I had the same need and saw the issue mentioned by OP but ended up with this,

    <HorizontalScrollView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_gravity="center">

        <com.google.android.material.button.MaterialButtonToggleGroup
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:singleSelection="true">

            <com.google.android.material.button.MaterialButton
                style="?attr/materialButtonOutlinedStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

            ...

        </com.google.android.material.button.MaterialButtonToggleGroup>

    </HorizontalScrollView>

It won't change starting scroll position which wasn't needed on my case, it just puts content at center if the content short enough but takes all the space and adds horizontal scroller if the content is lengthy. Hopefully the approach won't have a not known side effect but doesn't hit the issue mentioned by OP at least I can say.