In this post, we’ll learn Fragment Communication using Interface in Android. For doing that we’ll create a sample android application that contains ViewPager, TabLayout and Fragments. In this app, We’ll implement functionality that passing data between fragments.
Normally, Intents are used for sending data to activity level. To pass data between fragment have used setArguments(Bundle) when you are creating a new instance of Fragment. So once you have created new instance of the fragment you can’t update that bundle. Let’s think for movement how to communicate between fragments in android.
UseCase
Let’s take a proper use case, you are using ViewPager with tab layout and you want to update the second fragment on a certain event of first fragments.
There are several ways to doing that, In this post, we will learn only using Interface.
1. Let’s move to Android Studio and create a new project
In this project, we are using androidx with material design. let’s ensure below dependencies.
implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'com.google.android.material:material:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
2. Defined in the styles.xml file as shown below.
The styles for the TabLayout and ToolBar below
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="AppTheme.NoActionBar"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> </style> <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/> <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/> </resources>
3. Prepare MainActivity XML layout
In this android application, we are using ViewPager, TabLayout with Fragments. Let’s open the activity_main.xml layout file and paste below code.
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout 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" > <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay" > <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:minHeight="?actionBarSize" android:padding="@dimen/appbar_padding" android:text="@string/app_name" android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title" /> <com.google.android.material.tabs.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" /> </com.google.android.material.appbar.AppBarLayout> <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" app:srcCompat="@android:drawable/ic_dialog_email" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
4. Now create a fragment named FirstFragment
4.1 In a root package, create a new Fragment and update that xml as below.
In this layout, I have added two TextInputLayout. So we send data first fragment to the second fragment onTextChange() event.
<?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" > <ImageView android:id="@+id/imageView" android:layout_width="96dp" android:layout_height="96dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:layout_marginTop="24dp" android:src="@drawable/user_avatar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <com.google.android.material.textfield.TextInputLayout android:id="@+id/textInputLayout" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:layout_marginStart="16dp" android:layout_marginTop="24dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/imageView" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" > <com.google.android.material.textfield.TextInputEditText android:id="@+id/textInputTextName" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter Name" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textInputLayout" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" > <com.google.android.material.textfield.TextInputEditText android:id="@+id/textInputTextEmail" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter Email" /> </com.google.android.material.textfield.TextInputLayout> </androidx.constraintlayout.widget.ConstraintLayout>
4.2 Now open fragment java file and paste below code
package com.fragmentcommunicationexample.ui.main; import android.content.Context; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.fragmentcommunicationexample.R; import com.google.android.material.textfield.TextInputEditText; public class FirstFragment extends Fragment { private OnFragmentCommunicationListener mListener; public FirstFragment() { // Required empty public constructor } /** * Create a new instance of this fragment * * @return A new instance of fragment FirstFragment. */ public static FirstFragment newInstance() { return new FirstFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_first, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); TextInputEditText nameEditText = view.findViewById(R.id.textInputTextName); TextInputEditText emailEditText = view.findViewById(R.id.textInputTextEmail); nameEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { mListener.onNameChange(charSequence.toString()); } @Override public void afterTextChanged(Editable editable) { } }); emailEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { mListener.onEmailChange(charSequence.toString()); } @Override public void afterTextChanged(Editable editable) { } }); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnFragmentCommunicationListener) { mListener = (OnFragmentCommunicationListener) context; } else { throw new RuntimeException(context.toString() + " must implement OnFragmentCommunicationListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } /** * This interface must be implemented by activities that contain this * fragment to allow an interaction in this fragment to be communicated * to the activity */ public interface OnFragmentCommunicationListener { void onNameChange(String name); void onEmailChange(String email); } }
5. Create another fragment named SecondFragment
As usual, create a new fragment, In this fragment, we’ll receive the data and display on TextView
<?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=".ui.main.SecondFragment" > <ImageView android:id="@+id/imageView2" android:layout_width="144dp" android:layout_height="144dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:layout_marginTop="24dp" android:src="@drawable/user_avatar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textViewName" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:layout_marginTop="32dp" android:gravity="center" android:hint="User Display Name" android:textColor="@color/colorPrimaryDark" android:textSize="22sp" android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/imageView2" tools:text="Morris" /> <TextView android:id="@+id/textViewEmail" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:gravity="center" android:hint="user@gmail.com" android:textColor="@color/colorPrimary" android:textSize="18sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textViewName" /> </androidx.constraintlayout.widget.ConstraintLayout>
6. The layout is ready to use now, Now configure it with JAVA code.
package com.fragmentcommunicationexample.ui.main; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.fragmentcommunicationexample.R; public class SecondFragment extends Fragment { private static final String TAG = "SecondFragment"; private TextView txtName, txtEmail; public SecondFragment() { // Required empty public constructor } /** * Use this factory method to create a new instance of this fragment. * * @return A new instance of fragment SecondFragment. */ public static SecondFragment newInstance() { return new SecondFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_second, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); txtName = view.findViewById(R.id.textViewName); txtEmail = view.findViewById(R.id.textViewEmail); } public void onNameChange(String name) { txtName.setText(name); Log.d(TAG, "onNameChange() returned: " + name); } public void onEmailChange(String email) { txtEmail.setText(email); Log.d(TAG, "onEmailChange() returned: " + email); } }
6. Create a ViewPager Adapter where the Fragments are initialized.
package com.fragmentcommunicationexample.ui.main; import android.content.Context; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; import com.fragmentcommunicationexample.R; /** * A [FragmentPagerAdapter] that returns a fragment corresponding to * one of the sections/tabs/pages. */ public class SectionsPagerAdapter extends FragmentPagerAdapter { @StringRes private static final int[] TAB_TITLES = new int[] { R.string.tab_text_1, R.string.tab_text_2 }; private final Context mContext; public SectionsPagerAdapter(Context context, FragmentManager fm) { super(fm); mContext = context; } @Override public Fragment getItem(int position) { // getItem is called to instantiate the fragment for the given page. if (position == 0) { return FirstFragment.newInstance(); } else { return SecondFragment.newInstance(); } } @Nullable @Override public CharSequence getPageTitle(int position) { return mContext.getResources().getString(TAB_TITLES[position]); } @Override public int getCount() { // Show 2 total pages. return 2; } }
7. Finally, Open the MainActivity Java class and paste below code
package com.fragmentcommunicationexample; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import androidx.viewpager.widget.ViewPager; import com.fragmentcommunicationexample.ui.main.FirstFragment; import com.fragmentcommunicationexample.ui.main.SecondFragment; import com.fragmentcommunicationexample.ui.main.SectionsPagerAdapter; import com.google.android.material.tabs.TabLayout; public class MainActivity extends AppCompatActivity implements FirstFragment.OnFragmentCommunicationListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager()); ViewPager viewPager = findViewById(R.id.view_pager); viewPager.setAdapter(sectionsPagerAdapter); TabLayout tabs = findViewById(R.id.tabs); tabs.setupWithViewPager(viewPager); } @Override public void onNameChange(String name) { String tag = "android:switcher:" + R.id.view_pager + ":" + 1; SecondFragment fragment = (SecondFragment) getSupportFragmentManager().findFragmentByTag(tag); if (fragment != null) { fragment.onNameChange(name); } } @Override public void onEmailChange(String email) { String tag = "android:switcher:" + R.id.view_pager + ":" + 1; SecondFragment fragment = (SecondFragment) getSupportFragmentManager().findFragmentByTag(tag); if (fragment != null) { fragment.onEmailChange(email); } } }
Conclusion
In this android tutorial, I have learned the way of fragment communication using Interface in Android. We have also created a sample android application with ViewPager in android. I hope it’s helpful for you, Help me by sharing this post with all your friends who learning android app development.
Keep in touch
If you want to keep in touch when I write new blog posts follow me on facebook or subscribe us. It only takes about 5 seconds to register.
Deep drive on fragment commucation Four ways to communicate between fragments in android
Still, if you have any queries please put your comment below.