Toolbar with Image overlay center and Scroll behaviour

Viewed 285

I'm creating a detailed activity and I have a curved Toolbar and in the center of the Toolbar I have a rounded ImageView, the problem is that on differents screens the image is not centered.

What I want to achieve is :

1.- Create a Toolbar with the back arrow button and one icon on the right

I have it defined as :

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@drawable/curve_toolbar_2"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:theme="@style/ThemeOverlay.AppCompat.Dark" />

    <View
        android:id="@+id/view"
        android:layout_width="75dp"
        android:layout_height="75dp"
        android:background="@drawable/circle_shape"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/toolbar"
        app:layout_constraintVertical_bias="0.09" />

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/iv_pew"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="16dp"
        android:src="@drawable/ic_favorite"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/appCompatImageView"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:background="@drawable/ic_favorite"
        app:layout_constraintBottom_toBottomOf="@+id/view"
        app:layout_constraintEnd_toEndOf="@+id/view"
        app:layout_constraintStart_toStartOf="@+id/view"
        app:layout_constraintTop_toTopOf="@+id/view" />

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/tv_example"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Example"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="@+id/view"
        app:layout_constraintStart_toStartOf="@+id/view"
        app:layout_constraintTop_toBottomOf="@+id/view" />

    <ScrollView
        android:id="@+id/scrollView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fillViewport="true"
        app:layout_conokstraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_example"
        app:layout_constraintVertical_bias="0.13">

        <androidx.cardview.widget.CardView
            android:id="@+id/item_card_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"
            android:elevation="12dp"
            android:innerRadius="0dp"
            android:shape="rectangle"
            android:thicknessRatio="1.9"
            app:cardCornerRadius="40dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:padding="8dp">

                <com.google.android.material.textfield.TextInputLayout
                    android:id="@+id/ti_ex1"
                    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="8dp">

                    <com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/et_ex1"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:hint="Ex1" />
                </com.google.android.material.textfield.TextInputLayout>
                <com.google.android.material.textfield.TextInputLayout
                    android:id="@+id/ti_ex2"
                    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="8dp">

                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/et_ex2"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="Ex2" />
                </com.google.android.material.textfield.TextInputLayout>
                <com.google.android.material.textfield.TextInputLayout
                    android:id="@+id/ti_ex3"
                    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="8dp"/>

                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/et_ex3"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="SSID" />

                <com.google.android.material.textfield.TextInputLayout
                    android:id="@+id/ti_ex4"
                    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="8dp"
                    app:passwordToggleEnabled="true">

                    <com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/et_ex4"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:hint="Ex4"
                        android:imeOptions="actionUnspecified"
                        android:inputType="textPassword" />
                </com.google.android.material.textfield.TextInputLayout>


                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:padding="8dp">

                    <androidx.appcompat.widget.AppCompatButton
                        android:id="@+id/btn_1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginEnd="4dp"
                        android:background="@drawable/button_activation_background"
                        android:text="Example1"
                        android:textColor="@drawable/button_selected_text_color" />

                    <androidx.appcompat.widget.AppCompatButton
                        android:id="@+id/btn_2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginEnd="4dp"
                        android:background="@drawable/button_activation_background"
                        android:checked="false"
                        android:text="Example2"
                        android:textColor="@drawable/button_selected_text_color" />

                    <androidx.appcompat.widget.AppCompatButton
                        android:id="@+id/btn_3"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginEnd="4dp"
                        android:background="@drawable/button_activation_background"
                        android:checked="false"
                        android:text="Example3"
                        android:textColor="@drawable/button_selected_text_color" />
                </LinearLayout>


                <CheckBox
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_gravity="center"
                    android:layout_marginTop="8dp"
                    android:text="Whatever" />

            </LinearLayout>

        </androidx.cardview.widget.CardView>

    </ScrollView>

But I'm sure I'm doing it wrong because I have to play with the margins to be exactly as the left arrow, that I've added it as below :

setSupportActionBar(binding.toolbar)
binding.toolbarCreateQr.setNavigationIcon(R.drawable.ic_arrow_back)
binding.toolbarCreateQr.setNavigationOnClickListener { finish() }

2.- Add this View that is centered manually overlaying the toolbar the same on all screen devices, now I have this: Left(Normal device) Right (Small device)

enter image description here

3.- I have a container below and on my small screen is not showing correctly, even if I add android:windowSoftInputMode="adjustPan" />. Now there are two ways of doing it, just adding a ScrollView for the container and forgetting about the Toolbar, and add a ScrollBehaviour to convert this Toolbar to a rectangle, and move this floating button to the toolbar itself (or leaving it floating).

The container I have is as below, is not scrolling and I'm using a CardView to make it rounded and looks like a form module, if you think there's another way to do that just answer!

By the way, the drawable resource that I'm using for the curved Toolbar is :

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle"/>
    </item>
    <item
        android:bottom="0dp"
        android:left="-100dp"
        android:right="-100dp"
        android:top="-80dp">
        <shape android:shape="oval">
            <solid android:color="@color/colorPrimaryDark" />
        </shape>
    </item>
</layer-list>

or I've been using this also but didn't work as expected.

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="200.0"
    android:viewportHeight="100.0">
    <path
        android:fillColor="@color/colorPrimaryDark"
        android:pathData="M200,0H0v4.5h0v75.8h0c17.8,10.2 56,17.2 100.5,17.2c44.5,0 81.6,-7 99.5,-17.2h0V4.5h0V0z" />
</vector>

Edit

First iteration, I want to be like the image I've sent but responsive for all the devices, and if it's not responsive now is that somehting I'm doing wrong with the Constraints. Second iteration, I want to have this curve toolbar completely flat in case I arrive to the collapsion with the block of content (where I have all the textViews, EditText) with the image overlayed. Note I have to show also the textView below the icon centered on the Toolbar.

Regarding the curve Toolbar, what I thought is to have a View on the top of the view and when scrolling it fakes this curve to flat, but I'm open to different ways.

1 Answers

Wow, okay, so there are multiple questions at once, which makes it harder to give a complete answer. (Think about asking single question for each issue in the future. I hope I am guessing correctly which view represents which part of the question. Also consider more concise id names :)

1. The right toolbar icon

This one is fully encapsulated within the toolbar and could therefore actually be part of the toolbar.

Option 1 (inside Toolbar):
If it's inside the toolbar you can nicely constraint in to the parent

<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbar"
    .... >

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/iv_pew"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_marginEnd="16dp"
        android:src="@drawable/ic_favorite"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

</androidx.appcompat.widget.Toolbar

Option 2 (separate view):
You can constraint it to the toolbar instead of the parent. With this setup it will always be vertically centered inside the Toolbar and by marginEnd="16dp" you can move it inside as much as you want.

<androidx.appcompat.widget.AppCompatImageView
    android:id="@+id/iv_pew"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:layout_marginEnd="16dp"
    android:src="@drawable/ic_favorite"
    app:layout_constraintEnd_toEndOf="@+id/toolbar"
    app:layout_constraintTop_toTopOf="@+id/toolbar"
    app:layout_constraintBottom_toBottomOf="@+id/toolbar" />

2. The centered img:
To have it nicely aligned with the toolbar, align it bottom to bottom and add a negative margin equals to half the height of your img:

<View
    android:id="@+id/view"
    android:layout_width="76dp"
    android:layout_height="76dp"
    android:layout_marginBottom="-38dp"
    android:background="@drawable/circle_shape"
    app:layout_constraintBottom_toBottomOf="@+id/toolbar"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />

It's more tricky to always have it same "size". On you pictures it actually has the same size! In an absolute perspective. So what you want is a relative same size compared to the screen and not a real same size. So setting width="76dp" will look different on different sized screens. Try making it relative.

An option to make it relative could be like this (the image would always be 1/5 of the screen width; changing the weights adjusts it):

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

    <View
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:weight="2"/>
    <View
        android:id="@+id/view"
        android:layout_width="0dp"
        android:weight="1"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:background="@drawable/circle_shape"
        app:layout_constraintTop_toBottomOf="@+id/toolbar"
        app:layout_constraintBottom_toBottomOf="@+id/toolbar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
    <View
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:weight="2"/>
</LinearLayout>

3. ScrollView:
I'm still not 100% sure whether I understood your problems. But from what I see is that you might have set your attributes for the scrollview not properly. Setting layout_height="wrap_content" makes the scrollView as large as the content. Then you obviously cannot scroll as the content has the same size as the scrollview. Change it to a fixed size or match_parent. This way the scrollview is bound to your screen. And the large content inside can be scrolled through.

4. Curved to flat animation:
For such animations I usually use a MotionLayout. For yours I could think of following setup:

  1. A rectangular view that is fixed and represents the collapsed bar.
  2. A semicircle view underneath that represents the curved part.
  3. The motion layout changes scaleY of the second view to 0 (onSwipe or you setProgress() depending on your scroll state) which makes it disappear smoothly.

Example: https://blog.stylingandroid.com/motionlayout-collapsing-toolbar-part-1/

Related