Skip to content

Fragment

A Fragment in Android is a subactivity. A single activity can host multiple fragments. SO for example if you need one main page with sub-pages, then you need to think about Fragments. What is interesting is that Fragments have their own lifecycle and thus provide us with an independent way of working without having to rely on activities that much.

This tutorial teaches how to use fragments via simple HowTo Examples based on Kotlin Android.

Example 1: Kotlin Android - Show Fragment in Activity

The activity will have a button that when clicked shows a fragment. Here is the demo image of what is created:

Kotlin Android Fragment Example

Step 1: Dependencies

No third party dependencies are needed for this project.

Step 2: Design Layouts

You need two layouts: one for the fragment and the other for the main activity.

(a). fragment.xml

This is the layout for the fragment. It will simply contain a textiew:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/txt_fragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="top|left"
        android:text="@string/str_fragment"
        android:textColor="#2a2a2a"
        android:layout_margin="10dp"
        android:padding="10dp"/>

</LinearLayout>

(b). activity_main.xml

This is the layout for the main activity. It will contain a button and a framelayout. When the user clicks the button, and fragment is initialized and rendered in the framelayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_show"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="0.9"
        android:text="@string/show"/>

    <FrameLayout
        android:id="@+id/fragment_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="0.1">

    </FrameLayout>
</LinearLayout>

Step 3: Create a Fragment

The third step is to create the actual fragment and inflate it's layout. A fragment is created by extending the androidx.fragment.app.Fragment class. It is inflated by overriding the onCreateView() and returning a view object inflated from a layout for the fragment.

Here is the full code:

Fragment_one.kt

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment.*

class Fragment_one : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment,container,false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        txt_fragment.setOnClickListener {
            Toast.makeText(activity,"text fragment",Toast.LENGTH_SHORT).show()
        }

    }

}

Step 4: Create MainActivity

This is the activity that will host the fragment. Fragments don't exist on their own but are hosted by activities. A single activity can host multiple fragments.

To show a fragment inside an activity, you need to perform what is called a Fragment Transaction. Such a transaction can be adding a fragment, removing a fragment, replacing a fragment etc. In our case we are interested in replacement of our framelayout with our fragment. Here is the code to do it:

    fun showFragment(fragment: Fragment_one){
        val fram = supportFragmentManager.beginTransaction()
        fram.replace(R.id.fragment_main,fragment)
        fram.commit()
    }

Here is the full code for this activity:

MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btn_show.setOnClickListener {

            val fragment = arb.test.fragment.Fragment_one()
            showFragment(fragment)

        }

    }

    fun showFragment(fragment: Fragment_one){
        val fram = supportFragmentManager.beginTransaction()
        fram.replace(R.id.fragment_main,fragment)
        fram.commit()
    }
}

Run

Now run the project.

Reference

Download the code below:

No. Link
1. Download code
2. Follow code author

Example 2: Kotlin Android Fragment Lifecycle

This is a project to teach you about handling the lifecycle events in Fragment.

Step 1: Create Project

Start by creating an empty Android Studio project.

Step 2: Dependencies

No third party dependency is needed.

Step 3: Design Layouts

We need three layouts: two for our two fragments and one for the Activity:

(a). fragment_first.xml

Add several TextViews in this layout. This layout will be inflated into our first Fragment:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".FirstFragment">

    <TextView
        android:id="@+id/firstFragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/first_fragment"
        android:textColor="@color/colorPrimary"/>

    <TextView
        android:id="@+id/txtUsername"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textColor="@color/colorPrimary"/>

    <TextView
        android:id="@+id/txtLastName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textColor="@color/colorPrimary"/>
</LinearLayout>

(b). fragment_second.xml

Add a button and edittexts in this layout. This is the layout for the second Fragment.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <EditText
        android:id="@+id/edtUsername"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:autofillHints=""
        android:textColor="#FF0000"
        android:hint="@string/enter_name"
        android:inputType="textPersonName" />
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edtLastName"
        android:textColor="#FF0000"
        android:hint="@string/enter_last_name"
        android:autofillHints=""
        android:inputType="textPersonName" />
    <Button
        android:id="@+id/btnShow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/show_details"/>
</LinearLayout>

(c). activity_main.xml

Add the Fragment element in this layout. This is the layout for our MainActivity.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/fragment_container"
        android:name="com.example.lifecycle.SecondFragment"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <View
        android:id="@+id/divider"
        android:layout_width="match_parent"
        android:layout_height="5dp"
        android:layout_below="@id/fragment_container"
        android:layout_marginTop="329dp"
        android:background="@color/black" />

    <fragment
        android:id="@+id/first_fragment"
        android:name="com.example.lifecycle.FirstFragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/divider"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="187dp" />

</RelativeLayout>

Step 4: Create first Fragment

Override the Fragment's lifecycle methods.

Here is the code for this fragment:

FirstFragment.kt

package com.example.lifecycle

import android.content.ContentValues.TAG
import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.TextView

class FirstFragment : Fragment() {
    var TAG = "ActivityLifeCycle"
    lateinit var firstnameTxt : TextView
    lateinit var lastnameTxt : TextView
    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.d(TAG, "===>fragment===>onAttach()")
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "===>fragment===>onCreate()")
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        Log.d(TAG, "===>fragment===>onCreateView()")
        val view = inflater.inflate(R.layout.fragment_first, container, false)
        firstnameTxt = view.findViewById<TextView>(R.id.txtUsername)
        lastnameTxt = view.findViewById<TextView>(R.id.txtLastName)
        return view
    }
    fun showDetails(firstName:String, lastName:String){
        firstnameTxt.text = firstName
        lastnameTxt.text = lastName
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        Log.d(TAG, "===>fragment===>onActivityCreated()")
    }

    override fun onStart() {
        super.onStart()
        Log.d(TAG, "===>fragment===>onStart()")
    }

    override fun onResume() {
        super.onResume()
        Log.d(TAG, "===>fragment===>onResume()")
    }

    override fun onPause() {
        super.onPause()
        Log.d(TAG, "===>fragment===>onPause()")
    }

    override fun onStop() {
        super.onStop()
        Log.d(TAG, "===>fragment===>onStop()")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d(TAG, "===>fragment===>onDestroyView()")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "===>fragment===>onDestroy()")
    }

    override fun onDetach() {
        super.onDetach()
        Log.d(TAG, "===>fragment===>onDetach()")
    }

}

Step 5: Create Second Fragment

Create the second fragment and add the following code:

SecondFragment.kt

package com.example.lifecycle

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_second.*

class SecondFragment : Fragment() {

    interface GetUserDetail{
        fun showDetails(firstName:String, lastName:String)
    }
    lateinit var getUserDetail : GetUserDetail
    lateinit var firstNameEditText : EditText
    lateinit var lastNameEditText: EditText

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_second, container, false)
        val showButton = view.findViewById<Button>(R.id.btnShow)
        firstNameEditText = view.findViewById(R.id.edtUsername)
        lastNameEditText = view.findViewById(R.id.edtLastName)
        showButton.setOnClickListener(View.OnClickListener {
            getUserDetail.showDetails(firstNameEditText.text.toString(),lastNameEditText.text.toString())
        })
        return view
        }
}

Step 6: Create MainActivity

The fragments have to be hosted in an Activity. It is this MainActivity that will host both fragments.

Fragment.kt

package com.example.lifecycle

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.fragment.app.FragmentManager
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity(), SecondFragment.GetUserDetail {

    var TAG = "ActivityLifeCycle"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d(TAG, "===>onCreate()")
        loadFragment()
    }
    private fun loadFragment()
    {
        val fragmentManager = supportFragmentManager
        val fragmentTransaction = fragmentManager.beginTransaction()
        val secondFragment = SecondFragment()
        secondFragment.getUserDetail = this
        fragmentTransaction.add(R.id.fragment_container,secondFragment)
        fragmentTransaction.commit()
    }
    override fun onStart() {
        super.onStart()
        Log.d(TAG, "===>onStart()")
    }
    override fun onResume() {
        super.onResume()
        Log.d(TAG, "===>onResume()")
    }

    override fun onPause() {
        super.onPause()
        Log.d(TAG, "===>onPause()")
    }

    override fun onStop() {
        super.onStop()
        Log.d(TAG, "===>onStop()")
    }

    override fun onRestart() {
        super.onRestart()
        Log.d(TAG, "===>onRestart()")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "===>onDelete()")
    }

    override fun showDetails(firstName: String, lastName: String) {
        val firstFragment:FirstFragment = first_fragment as FirstFragment
        firstFragment.showDetails(firstName, lastName)
    }
}

Run

Copy the code or download it in the link below, build and run.

Reference

Here are the reference links:

Number Link
1. Download Example
2. Follow code author

Example 3: Android Simple Fragment inside Activity

This is another simple Fragment inside Activity example. However this time we write our code in Java. We will also see how to work with widgets inside the Fragment independent of the Activity.

Let's start.

Step 1: Create Project

Start by creating an empty Android Studio project.

Step 2: Dependencies

No external or special dependencies are needed.

Step 3: Design Layouts

We need two layouts: one for Fragment and the other for the Activity.

(a). fragment_simple.xml

Add a widgets like Button, EditText and TextView inside this layout. This layout will be inflated into our Fragment:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingBottom="@dimen/activity_vertical_margin"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                tools:context=".MainActivity" >

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10" android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true" android:layout_alignParentStart="true"
        android:layout_alignRight="@+id/textView1" android:layout_alignEnd="@+id/textView1">

        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Submit" android:layout_below="@+id/editText1"
        android:layout_alignParentLeft="true" android:layout_alignParentStart="true"
        android:layout_alignRight="@+id/editText1" android:layout_alignEnd="@+id/editText1"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/textView1"
        android:layout_below="@+id/button1" android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true" android:layout_alignParentBottom="true"
        android:background="#ff7299ff"/>

</RelativeLayout>

(b). activity_main.xml

This is our MainActivity layout. Given that this activity will host our Fragment, we need to add our Fragment tag inside.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:gravity="center_horizontal"
              android:orientation="vertical"
              android:padding="4dip" >

    <fragment
        android:id="@+id/FrameLayout1"
        android:name="com.example.ankitkumar.singlescreenfragment.MainActivity"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1" >
    </fragment>

</LinearLayout>

Step 4: Write Code

Here is our full code:

MainActivity.java

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {
    int i = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        getFragmentManager().findFragmentById(R.id.FrameLayout1);

    }

    public static class SimpleAddition extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_simple, container, false);

            Button b = (Button) v.findViewById(R.id.button1);
            final EditText et1 = (EditText) v.findViewById(R.id.editText1);
            final TextView tv = (TextView) v.findViewById(R.id.textView1);

            b.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    tv.setText(et1.getText().toString());
                }
            });
            return v;
        }
    }

}

Run

Copy the code or download it in the link below, build and run.

Reference

Here are the reference links:

Number Link
1. Download Example
2. Follow code author

More Examples

Here are more examples

Kotlin Android Fragment Example

Learn about Fragment using these simple examples.

Step 1: Dependencies

No external dependencies are needed for this project.

Step 2: Design Layouts

We will have 4 layouts. Two of them for Fragments, two for Activities:

(a). fragment_second.xml

Declare a TextView as the root and only element:

<?xml version="1.0" encoding="utf-8"?>

<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="@android:color/holo_red_light"
    android:text="@string/secondFragmentText"/>

(b). fragment_main.xml

Declare a TextView and a Button inside a RelativeLayout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/mainFragmentText"/>

    <Button
        android:id="@+id/mainFragmentButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_margin="20dp"
        android:text="@string/mainFragmentButton"/>

</RelativeLayout>

(c). activity_second.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    android:id="@+id/contentFrame"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Do not add Views inside FrameLayout used for fragment transactions. This is only for a test purpose-->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:onClick="showFragment"
        android:text="@string/secondActivityButton"/>
</FrameLayout>

(d). activity_main.xml

Declare our main Fragment inside this layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".activities.MainActivity">

    <fragment
        android:id="@+id/mainFragment"
        android:name="fr.esilv.fragmentexample.fragments.MainFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

Step 3: Write Fragment Code

(a). SecondFragment.kt

package fr.esilv.fragmentexample.fragments

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import fr.esilv.fragmentexample.R

class SecondFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_second, container, false)
    }
}

(b). MainFragment.kt

package fr.esilv.fragmentexample.fragments

import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import fr.esilv.fragmentexample.R
import fr.esilv.fragmentexample.activities.SecondActivity
import kotlinx.android.synthetic.main.fragment_main.mainFragmentButton

class MainFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_main, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mainFragmentButton.setOnClickListener(OnMainFragmentButtonClickListener())
    }

    private inner class OnMainFragmentButtonClickListener : View.OnClickListener {
        override fun onClick(v: View) {
            startActivity(Intent(v.context, SecondActivity::class.java))
        }
    }
}

Step 4: Create Activities

Create Activities code as follows:

(a). SecondActivity.kt

package fr.esilv.fragmentexample.activities

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import fr.esilv.fragmentexample.R
import fr.esilv.fragmentexample.fragments.SecondFragment

class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
    }

    //this method is called by the Button in activity_second.xml. the android:onClick attribute binds with this method.
    fun showFragment(view: View) {
        view.visibility = View.GONE
        supportFragmentManager.beginTransaction()
                .apply {
                    //the id passed as parameter is the id of the FrameLayout defined in activity_second.xml.
                    replace(R.id.contentFrame, SecondFragment())
                    //the transaction has to be committed for changes to happen.
                    commit()
                }

    }
}

(b). MainActivity.kt

package fr.esilv.fragmentexample.activities

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import fr.esilv.fragmentexample.R

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Reference

  • Download code here.
  • Follow code author here.

Communicate between DialogFragment and Fragment

Basic fragment result application..

android-fragment-result Example Tutorial

Learn how to communicate between BottomSheetDialogFragment and a Fragment in kotlin android.

Step 1. Dependencies

We need to add some dependencies in our app/build.gradle file as shown below:

(a). build.gradle

Our app-level build.gradle.

We Prepare our dependencies as shown below. You may use later versions.

We will also enable Java8 so that we can utilize a myriad of Java8 features.

We then declare our app dependencies under the dependencies closure, using the implementation statement. We will need the following 9 dependencies:

  1. Kotlin-stdlib - So that we can use Kotlin as our programming language.
  2. Core-ktx - With this we can target the latest platform features and APIs while also supporting older devices.
  3. Appcompat - Allows us access to new APIs on older API versions of the platform (many using Material Design).
  4. Material - Collection of Modular and customizable Material Design UI components for Android.
  5. Constraintlayout - This allows us to Position and size widgets in a flexible way with relative positioning.
  6. Our Navigation-fragment-ktx library.
  7. Our Navigation-ui-ktx library.
  8. Our Legacy-support-v4 support library. Feel free to use newer AndroidX versions.
  9. Fragment-ktx - Enables us to Segment our app into multiple, independent screens that are hosted within an Activity.

Here is our full app/build.gradle:

plugins {
  id 'com.android.application'
  id 'kotlin-android'
}

android {
  compileSdkVersion 30
  buildToolsVersion "30.0.2"

  defaultConfig {
    applicationId "com.fevziomurtekin.myapplication"
    minSdkVersion 16
    targetSdkVersion 30
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
  }

  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
  }
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
  kotlinOptions {
    jvmTarget = '1.8'
  }
}

dependencies {

  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
  implementation 'androidx.core:core-ktx:1.3.2'
  implementation 'androidx.appcompat:appcompat:1.2.0'
  implementation 'com.google.android.material:material:1.2.1'
  implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
  implementation "androidx.navigation:navigation-fragment-ktx:2.3.2"
  implementation "androidx.navigation:navigation-ui-ktx:2.3.2"
  implementation 'androidx.legacy:legacy-support-v4:1.0.0'

  def fragment_version = "1.3.0-alpha04"
  implementation "androidx.fragment:fragment-ktx:$fragment_version"

  testImplementation 'junit:junit:4.+'
  androidTestImplementation 'androidx.test.ext:junit:1.1.2'
  androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

Step 2. Design Layouts

For this project let's create the following layouts:

(a). fragment_home.xml

Our fragment_home layout.

This layout will represent our Home Fragment's layout. Specify androidx.constraintlayout.widget.ConstraintLayout as it's root element then inside it place the following widgets:

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

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:text="Result : " />

    <Button
        android:id="@+id/btn_show_dialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tv_result"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginTop="10dp"
        android:text="Show Dialog"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

(b). dialog_home.xml

Our dialog_home layout.

This layout will represent our Home Dialog's layout. Specify androidx.constraintlayout.widget.ConstraintLayout as it's root element then inside it place the following widgets:

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

    <TextView
        android:id="@+id/tv_bottom_dialog_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginTop="10dp"
        android:fontFamily="sans-serif-black"
        android:textSize="20sp"
        android:text="Content"
        />

    <LinearLayout
        android:id="@+id/ll_buttons"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginTop="10dp"
        app:layout_constraintTop_toBottomOf="@id/tv_bottom_dialog_content">

        <Button
            android:id="@+id/btnAccept"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:backgroundTint="@android:color/holo_green_light"
            android:layout_marginRight="10dp"
            android:layout_marginLeft="10dp"
            android:text="Accept"
            android:layout_weight="1"/>


        <Button
            android:id="@+id/btnReject"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:backgroundTint="@android:color/holo_red_light"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="reject"
            android:layout_weight="1"
            />

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

(c). activity_main.xml

Our activity_main layout.

This layout will represent our Main Activity's UI. Specify androidx.constraintlayout.widget.ConstraintLayout as it's root element then inside it place the following widgets:

  1. FragmentContainerView
<?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"
  tools:context=".MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />


</androidx.constraintlayout.widget.ConstraintLayout>

Step 3. Write Code

Finally we need to write our code as follows:

(a). HomeDialog.kt

Our HomeDialog class.

Create a Kotlin file named HomeDialog.kt and add the necessary imports. Here are some of the imports we will be using: 1. View from the android.view package. 2. ViewGroup from the android.view package. 3. Button from the android.widget package. 4. bundleOf from the androidx.core.os package. 5. findNavController from the androidx.navigation.fragment package.

Then extend the BottomSheetDialogFragment and add its contents as follows:

First override these callbacks:

  1. onStart().
  2. onStateChanged(p0: View, p1: Int).
  3. onSlide(p0: View, p1: Float).
  4. onViewCreated(view: View, savedInstanceState: Bundle?).
  5. onCancel(dialog: DialogInterface).

Then we will be creating the following functions:

  1. setListeners().
  2. setResult(parameter) - We pass a Boolean object as a parameter.

(a). Our setListeners() function

Write the setListeners() function as follows:

    private fun setListeners() {
        btnAccept?.setOnClickListener { setResult(true) }
        btnReject?.setOnClickListener { setResult(false) }
    }

(b). Our setResult() function

Write the setResult() function as follows:

    private fun setResult(isAccept: Boolean) {
        parentFragmentManager.setFragmentResult(REQUEST_KEY, bundleOf("data" to isAccept))
        findNavController().popBackStack()
    }

Here is the full code:

package replace_with_your_package_name

import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.core.os.bundleOf
import androidx.navigation.fragment.findNavController
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment


class HomeDialog : BottomSheetDialogFragment() {

    private var btnAccept: Button? = null
    private var btnReject: Button? = null

    override fun onStart() {
        super.onStart()
        (requireView().parent as? View)?.let { safeView ->
            BottomSheetBehavior.from(safeView).apply {
                state = BottomSheetBehavior.STATE_EXPANDED
                setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
                    override fun onStateChanged(p0: View, p1: Int) {
                        if (p1 == BottomSheetBehavior.STATE_DRAGGING) {
                            state = BottomSheetBehavior.STATE_EXPANDED
                        }
                    }

                    override fun onSlide(p0: View, p1: Float) {}
                })
            }
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = inflater.inflate(
        R.layout.dialog_home, container, false
    )

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        btnAccept = view.findViewById(R.id.btnAccept)
        btnReject = view.findViewById(R.id.btnReject)
        setListeners()  
    }

    private fun setListeners() {
        btnAccept?.setOnClickListener { setResult(true) }
        btnReject?.setOnClickListener { setResult(false) }
    }

    private fun setResult(isAccept: Boolean) {
        parentFragmentManager.setFragmentResult(REQUEST_KEY, bundleOf("data" to isAccept))
        findNavController().popBackStack()
    }

    override fun onCancel(dialog: DialogInterface) {
        super.onCancel(dialog)
        setResult(false)
    }

}

(b). HomeFragment.kt

Our HomeFragment class.

Create a Kotlin file named HomeFragment.kt and add the necessary imports. Here are some of the imports we will be using: 1. ViewGroup from the android.view package. 2. Button from the android.widget package. 3. TextView from the android.widget package. 4. Fragment from the androidx.fragment.app package. 5. findNavController from the androidx.navigation.fragment package.

Then extend the Fragment and add its contents as follows:

First override these callbacks:

  1. onViewCreated(view: View, savedInstanceState: Bundle?).

Here is the full code:

package replace_with_your_package_name

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController

const val REQUEST_KEY = "request"

class HomeFragment : Fragment() {

    private var tvResult: TextView? = null
    private var btnShowDialog: Button? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = inflater.inflate(R.layout.fragment_home,container,false)


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        tvResult = view.findViewById(R.id.tv_result)
        btnShowDialog = view.findViewById(R.id.btn_show_dialog)

        // this listen to result.
        parentFragmentManager.setFragmentResultListener(
            REQUEST_KEY,
            this,
            { key, data ->
                if(key == REQUEST_KEY){
                    val result = data.getBoolean("data").let { isAccept->
                        if(isAccept) "Accepted" else "Rejected"
                    }
                    tvResult?.text = result
                }
            }
        )

        // show bottom dialog
        btnShowDialog?.setOnClickListener {
            findNavController().navigate(R.id.homeDialog)
        }

    }
}

(c). MainActivity.kt

Our MainActivity class.

Here is the full code:

package replace_with_your_package_name

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
  }
}

Reference

Download the code below:

No. Link
1. Download Full Code
2. Read more here.
3. Follow code author here.