How to create an Android App: Improving designs
Tags: android, java, tutorial
Published: 2019-09-12 19:37:48

### Here we are one week more, in the last part of this series. ###

We had reviewed important topics like database connectivity, image selecting, etc. However, there’s still missing an important, missing it will devalue our application no matter the powerful functionality it has. I’m talking about the design.

I’m going to be honest and tell to you that I’m not a great designer. In fact, this last part take me lot of time to prepare, while I’d been writing the series, I was practicing and reading resources for all over the internet to write a great entry.

In this last post we’ll review a material components, not all of them, and a tool to improve designs.

First of all, Android allow us to use components call materials. This kind of components give to us hole new experience on UX patterns with interesting designs like elevations, shadows, animations, and drawables.

Considering the previous mentioned, let’s change all text view and text edit, also the button. Image container, as far as I know, doesn’t  support materials, so we’ll let it as it.

To modify text edit we’ll use TextInputLayout and TextInputEdit. The layout is used as container of text input, it can contain a hint and images to avoid even more components.
The code below show how to change the EditText to the new component.
Notice the hint tag with “Username” text, it’s like a decorator, when you press the component, it will change its position; and boxStrokeColor tag, allowing us to change the color of the stroke.

```{xml}
<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/profile_username_edittext_layout"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout_marginStart="20dp"
    android:layout_marginLeft="20dp"
    android:layout_marginTop="44dp"
    android:layout_marginEnd="8dp"
    android:layout_marginRight="8dp"
    android:ems="10"
    android:hint="Username"
    android:textColorHint="@android:color/black"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="1.0"
    app:layout_constraintStart_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/profile_imageView">

    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/profile_username_edittext"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:inputType="textPersonName"
        android:maxLength="15"
        android:textColor="@android:color/black"
        android:singleLine="true" />

</com.google.android.material.textfield.TextInputLayout>
```

Because of the hint tag of the component I remove the TextView, being redundant.

Now the radio buttons will be changed for images, a great page where you can find free png resources is [icons8](https://icons8.com/), you could add drawable to the left or right and the icons will be shown, in case you don’t like que orientation, also there’s a possibility to add it top or bottom, hiding the circular button.

```{xml}
<RadioGroup
    android:id="@+id/profile_gender_radiogroup"
    android:layout_width="wrap_content"
    android:layout_height="100dp"
    android:gravity="center"
    android:orientation="horizontal"
    app:layout_constraintBottom_toTopOf="@+id/profile_birthday_dateselect_layout"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.497"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/profile_gender_textview"
    app:layout_constraintVertical_bias="0.506">

    <androidx.appcompat.widget.AppCompatRadioButton
        android:id="@+id/profile_male_radiobutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="16dp"
        android:drawableRight="@drawable/icons8_man_50" />

     <androidx.appcompat.widget.AppCompatRadioButton
        android:id="@+id/profile_female_raidobutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="16dp"
        android:drawableRight="@drawable/icons8_woman_50" />
</RadioGroup>
```

Next step is changing birthday field as we did with the username field, the variant in this case is changing the input type by none to avoid the user from writing. This last step was performed programmatically, once everything is initialized.


```{xml}
<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/profile_birthday_dateselect_layout"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout_marginStart="20dp"
    android:layout_marginLeft="20dp"
    android:layout_marginTop="152dp"
    android:layout_marginEnd="8dp"
    android:layout_marginRight="8dp"
    android:ems="10"
    android:hint="Birthday"
    android:textColorHint="@android:color/black"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/profile_gender_textview">

    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/profile_birthday_dateselect"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusable="false"
        android:inputType="textPersonName"
        android:maxLength="15"
        android:singleLine="true" />

</com.google.android.material.textfield.TextInputLayout>
```

```{java}
birthday.setInputType(InputType.TYPE_NULL);
```

Then, center everything in the screen and change a cool color and its contrast, a great page is [paletton](https://paletton.com/). I suggest to pick up light colors, but not too bright (imagine yourself using sunglasses every time you open up your app because of the bright).

Combine all together into a style to your layouts, just to to `style.xml` file and add the following


```{xml}
<style name="UsernameLabel" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
    <!-- Hint color and label color in FALSE state -->
    <item name="android:textColorHint">@color/ColorFalseState</item>
    <item name="android:textSize">20sp</item>
    <item name="hintTextAppearance">@color/boxStroke</item>
    <!-- Label color in TRUE state and bar color FALSE and TRUE State -->
    <item name="colorAccent">@color/boxStroke</item>
    <item name="colorControlNormal">@color/boxStroke</item>
    <item name="colorControlActivated">@color/boxStroke</item>
    <item name="boxStrokeColor">@color/boxStroke</item>
</style>
```

Don’t miss to change the names of the style, that is, `UsernameLabel` and color values to something fit great to your app.

To import this style to your component, just add an style tag, like this.


```{xml}
<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/profile_birthday_dateselect_layout"
    style="@style/UsernameLabel"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout_marginStart="20dp"
    android:layout_marginLeft="20dp"
    android:layout_marginTop="152dp"
    android:layout_marginEnd="8dp"
    android:layout_marginRight="8dp"
    android:ems="10"
    android:hint="Birthday"
    android:textColorHint="@android:color/black"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/profile_gender_textview">

    ...

</com.google.android.material.textfield.TextInputLayout>
```

Taking advantage of Text input layouts, let’s complement our functionality with error message. To do that, use a text change listener on your edit text; on after change check if the change made, when the text field change to empty, set an error; otherwise change text layout to original state.

```{java}
username.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void afterTextChanged(Editable editable) {
            if (editable.toString().isEmpty()) {
                username.setError(getResources().getString(R.string.username_error));
                username_layout.setBoxStrokeColor(Color.RED);
            } else if (!editable.toString().isEmpty()) {
                username_layout.setBoxStrokeColor(getResources().
                                                  getColor(R.color.boxStroke));
            }
        }
   });
```

You should do this for every text layout you want to show an error.

At the end the app should look like this.


![Final Image](https://thepracticaldev.s3.amazonaws.com/i/xkrv4z6nobomekgq1zv4.png)

(Less orange, I really don’t know why image is turned this color when I take an snip)

But there’s one missing issue, what happen if the app is used on a small device? everything will look weird, we simply put layout into a ScrollView, and problem solved.

```{xml}
<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="1.0">

    <include layout="@layout/content_main" />

</ScrollView>
```

Aaaand…. that’s it. 

Thanks for reading, and remember that the project is on github (link) for whatever purpose you want to give it.