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:
- And then once our app turns to the horizontal view, it will display this view:
SlidingPaneLayout
- The
SlidingPaneLayout
class 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>
- 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 theFragmentContainerView
andConstraintLayout
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 ofSlidingPaneLayout
.2)width, thelayout_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 is580dp
, 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 thelayout_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 theandroid:name
attribute, when this is done inside of the FragmentContainerView 3 things will happen1) 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()
}
- 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 theandroid: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 screen2) 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>
- 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)