Home > Software design >  Set proper constraint in Constraint Layout in Android Kotlin
Set proper constraint in Constraint Layout in Android Kotlin

Time:11-11

I am creating a chat application. I used stackFromEnd = false and reverseLayout = true to show items from the bottom of screen. In which I used reyclerview and it's working fine, and I am adding the code below with a screenshot. How it looks likes

<?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"
    android:background="#cccccc">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/conversationRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0" />

</androidx.constraintlayout.widget.ConstraintLayout>

The above code is working fine when there is a single item in recyclerView it opens a screen like this

Image 1

Example1

But when there are more items the screen look like this

Image 2

enter image description here

Note: This above image is my expected output. Also soft keyboard shift the layout.

Now the main story starts, I want to add editText at bottom of the screen.

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cccccc">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/conversationRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toTopOf="@ id/inputContainer"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@ id/inputContainer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:paddingStart="10dp"
        android:paddingTop="14dp"
        android:visibility="gone"
        android:paddingEnd="10dp"
        android:paddingBottom="14dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@ id/conversationRecyclerView"
        app:layout_constraintVertical_bias="1.0">

        <EditText
            android:id="@ id/edittext"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="textMultiLine|text|textNoSuggestions"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

Problem 1

Image 1 is not getting the correct constraint and it looks like this

enter image description here

and image 2 is working fine and the soft keyboard shifts the layout.

problem 2

I tried some code to solve problem 1 and the soft keyboard is not shifting the layout

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cccccc">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/conversationRecyclerView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@ id/inputContainer"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@ id/inputContainer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:paddingStart="10dp"
        android:paddingTop="14dp"
        android:paddingEnd="10dp"
        android:paddingBottom="14dp"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintVertical_bias="1.0">

        <EditText
            android:id="@ id/sendMessageEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

UPDATE

After @Cheticamp suggestion, I added this but not working. It has still a problem 1 issue. It's not resolving.

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cccccc">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/conversationRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@ id/inputContainer"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@ id/inputContainer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:paddingStart="10dp"
        android:paddingTop="14dp"
        android:paddingEnd="10dp"
        android:paddingBottom="14dp"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
      >

        <EditText
            android:id="@ id/sendMessageEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

UPDATE 1

After @Tenfour04 suggestions, I added some code please have a look. Am I am doing correctly?

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cccccc">

    <FrameLayout
        android:id="@ id/conversationRecyclerViewViewWrapper"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@ id/inputContainer"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@ id/conversationRecyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="top"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:paddingBottom="10dp"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

    </FrameLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@ id/inputContainer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:paddingStart="10dp"
        android:paddingTop="14dp"
        android:paddingEnd="10dp"
        android:paddingBottom="14dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@ id/conversationRecyclerView">

        <EditText
            android:id="@ id/sendMessageEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:inputType="textMultiLine|text|textNoSuggestions"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

CodePudding user response:

The problem is your RecyclerView's height is wrap_content instead of 0dp (a.k.a. "match_constraints"), so it ignores the constraint that it should be above inputContainer.

So instead of making it wrap_content and using vertical bias to try to keep it at the top of the screen, try wrapping it in a FrameLayout and giving it layout gravity of "top". The FrameLayout should use 0dp for height so it can fill the entire space, but not overlap inputContainer. The RecyclerView can use wrap_content for height, and the layout gravity will bias it to the top of the FrameLayout's space. So replace your RecyclerView element with this:

<FrameLayout
    android:id="@ id/recyclerViewWrapper"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toTopOf="@ id/inputContainer"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/conversationRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="LinearLayoutManager"
        app:reverseLayout="true"/>
</FrameLayout>

The app:layout_constraintVertical_bias is meaningless on inputContainer because it has no top constraint, so you can remove that.

CodePudding user response:

For problem #1, make the height and the width of the RecyclerView 0dp and let the constraints size it to fill the screen. Also, remove the vertical bias - you don't need it.

btw, never use match_parent in a ConstraintLayout. Always use 0dp and the constraints.

That may solve all your issues with this layout.

Update: I should have scrolled down in your layout.

I take it that you want the RecyclerView to fill the screen except for the EditText on the bottom. In general, nesting layout within a ConstraintLayout is not needed and is considered by many poor design.

Make the changes I suggest above, remove the inner ConstraintLayout and place the two views into a vertical chain like this:

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cccccc">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/conversationRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@ id/sendMessageEditText"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@ id/sendMessageEditText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="This is the EditText"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@ id/conversationRecyclerView" />

</androidx.constraintlayout.widget.ConstraintLayout>

enter image description here

  • Related