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:
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
Communicate between DialogFragment and Fragment
Basic fragment result application..
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:
Kotlin-stdlib
- So that we can use Kotlin as our programming language.Core-ktx
- With this we can target the latest platform features and APIs while also supporting older devices.Appcompat
- Allows us access to new APIs on older API versions of the platform (many using Material Design).Material
- Collection of Modular and customizable Material Design UI components for Android.Constraintlayout
- This allows us to Position and size widgets in a flexible way with relative positioning.- Our
Navigation-fragment-ktx
library. - Our
Navigation-ui-ktx
library. - Our
Legacy-support-v4
support library. Feel free to use newer AndroidX versions. 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:
<?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:
<?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:
<?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:
onStart()
.onStateChanged(p0: View, p1: Int)
.onSlide(p0: View, p1: Float)
.onViewCreated(view: View, savedInstanceState: Bundle?)
.onCancel(dialog: DialogInterface)
.
Then we will be creating the following functions:
setListeners()
.setResult(parameter)
- We pass aBoolean
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:
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. |