CodeNewbie Community 🌱

Cover image for Different layout for different screen sizes in Android with Kotlin
Tristan
Tristan

Posted on

Different layout for different screen sizes in Android with Kotlin

Introduction

  • This series is going to be where I put all my Android notes. As I learn something new about Android development I will put in this tutorial series

GitHub code

Video Version

What we are going to do

  • So in this tutorial I am going to show how we can have different layouts for our app depending on the screen size. Which ultimately means that the app will have one view for the vertical position and another for the horizontal position.
  • If you are interested in reading more about this subject, you can read the official documentation, HERE

By the end of this tutorial we will be able to see how we can take these two views:

Android app home screen

Android app new Item screen

  • And then once our app turns to the horizontal view, it will display this view:

Android app both screens combined

SlidingPaneLayout

  • The SlidingPaneLayoutclass is what does all the heavy lifting for us. It is what allows the app to seamlessly transition from one view to another. To use it, we must wrap it around the classes that we want to display like so:
<androidx.slidingpanelayout.widget.SlidingPaneLayout
    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:id="@+id/sliding_pane_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="280dp"
        android:layout_gravity="start"
        android:layout_height="match_parent"
        tools:context=".fragments.MainFragment">



        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />


        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="30dp"
            android:layout_marginBottom="100dp"
            android:contentDescription="add new calf"
            android:src="@drawable/ic_add_black_24"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/recyclerview"
            app:layout_constraintVertical_bias="1.0" />


    </androidx.constraintlayout.widget.ConstraintLayout>
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/detail_container"
        android:layout_width="300dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:name="com.elliottsoftware.calftracker2.fragments.NewCalfFragment" />

</androidx.slidingpanelayout.widget.SlidingPaneLayout>

Enter fullscreen mode Exit fullscreen mode
  • As you can see from the XML file above we wrap everything we want to display in the <SlidingPaneLayout> tag. Doing so means a few things: 1)overlaping, if there is no width to display child views,in our case the FragmentContainerView and ConstraintLayout then they will overlap each other. Which will give us the ability to swipe between those views. If we swipe from one side of the screen to the other we will be able to navigate between whatever is nested inside of SlidingPaneLayout.2)width, the layout_width of the child views is what determines when we are able to see the combined views. Notice from the XML above the combined width is 580dp, meaning the combined view will only show if the width of the screen is a minimum of 580dp. In general we want the combined total to be less than 600dp if the primary device our app is running on is a phone. Another important attribute to point out is, android:layout_weight="1", which works simular to how it works inside of the LinearLayout. Read more about the layout_weight, HERE. Since only on child has layout_weight="1" meaning if the size is greater than 580 the child with the layout_weight="1" will expand to fill the rest of the space.

Nested Fragment

  • to reuse a fragment we use the FragmentContainerView class, which is a layout class specifically designed to hold fragments. Notice that we specified the android:name attribute, when this is done inside of the FragmentContainerView 3 things will happen

  • 1) Creates a new instance of the Fragment

  • 2) Calls Fragment.onInflate (inflates the view)

  • 3) executes a FragmentTransaction to add the Fragment to the appropriate FragmentManager

Detecting orientation changes

  • There were some parts of my view that I did not want to show when the orientation changed to horizontal. So to hide certain views we have to detect orientation changes. To do so place this code inside of the onViewCreated() method:
val orientation:Int = resources.configuration.orientation
        if(orientation == Configuration.ORIENTATION_LANDSCAPE){
            //code to hide 
            fabButton.hide()
        }

Enter fullscreen mode Exit fullscreen mode
  • I am first finding the orientation and then hiding the View. Most views can be hidden from the user by getting a reference to them first and then calling the hide() method.

Weird bugs I encountered in Horizontal View

  • 1) The first bug I encountered was with EditText. When in a horizontal configuration, anytime a user would click on a EditText view a massive white keyboard would appear and cover everthing (the soft keyboard). To fix this I applied the android:imeOptions="flagNoExtractUi" to every EditText in my XML files. This tells the Android system to not show the full keyboard during text inputs. This allows for a less jarring ui when a EditText is full screen

  • 2) The second bug was scrolling effect on the EditText view stopped working. Meaning that the user could not see what they where typing. To fix this I wrapped a ScrollView around a LinearLayout like so:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout>
    </LinearLayout>
</ScrollView>
Enter fullscreen mode Exit fullscreen mode
  • The ScrollView allows the user to scroll to the EditText view if it can not be seen while typing.

Programmatically swap out the detail pane

  • tutorials about this will be coming in my next post

Conclusion

  • Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter.

Top comments (0)