Creating a Fragment Dynamically

Let's continue from our current activity!

The main difference in creating a fragment is that you have to manage the Fragment using FragmentManager and FragmentTransaction statements that can add, remove, and replace a Fragment

Creating a Fragment Class

Just as you did just now, create a fragment called RatingFragment .

Set the Layout of the Class

This time, let's use a RatingBar instead of a RadioGroup with RadioButtons

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="@color/fragment_color"
    tools:context=".RatingFragment">

    <TextView
        android:id="@+id/carText"
        android:layout_marginLeft="@dimen/padding_standard"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        android:padding="4dp"
        android:text="@string/rating_message" />
    <RatingBar
        android:id="@+id/ratingBar"
        style="@android:style/Widget.DeviceDefault.RatingBar.Small"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:numStars="6"
        android:padding="8dp"
        android:rating="0"
        android:stepSize="0.5"
        android:isIndicator="false"
        />

</LinearLayout>

Now just as we did before, we can edit and place interactivity in our fragment right away.

In this new fragment, we have a new function newInstance(). This allows us to instantiate the Fragment in the MainActivity later on.

 public static RatingFragment newInstance() {

        RatingFragment fragment = new RatingFragment();
        return fragment;
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        final View rootView = inflater.inflate(R.layout.fragment_rating, container, false);
        final RatingBar rB = rootView.findViewById(R.id.ratingBar);
        rB.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
            @Override
            public void onRatingChanged(RatingBar ratingBar, float v, boolean b) {
                String s = getString(R.string.rating_message);
                Toast.makeText(getActivity().getApplicationContext(),s+ " "+ v,Toast.LENGTH_SHORT).show();
            }
        });
        return rootView;
    }

Note:Toast here displays simple messages in a small popup for a selected amount of time.

Great! Now all we need is to edit the rest on the MainActivity and activity_main.xml

Creating functions to display/hide Fragments

We are going to use a <FrameLayout> as a fragment container instead of a <fragment> in activity_main.xml

First, let's specify ViewGroup for Fragment in layout

<FrameLayout
    android:id="@+id/fragment_container"
    android:name="com.example.fragmentdemo1.RatingFragment"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@id/fragment"
    tools:layout="@layout/fragment_rating" />

Add the following code within the MainActivityclass.

    public void displayFragment(){
        RatingFragment ratingFragment = RatingFragment.newInstance();
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.fragment_container,ratingFragment).addToBackStack(null).commit();
        sButtonl.setText(R.string.close);
        isFragmentDisplayed = true;
    }
    public void closeFragment(){
        FragmentManager fragmentManager = getSupportFragmentManager();
        RatingFragment ratingFragment = (RatingFragment)fragmentManager.findFragmentById(R.id.fragment_container);
        if(ratingFragment!=null){
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.remove(ratingFragment).addToBackStack(null).commit();
        }
        sButtonl.setText(R.string.open);
        isFragmentDisplayed = false;

    }

What the code is doing here is instantiating RatingFragmentand FragmentManager

Use getSupportFragmentManager() for compatibility

Use FragmentTransaction for adding/removing/replacing dynamically.

FragmentManager:

FragmentManager interacts with Fragment which are within an Activity.

Function

What it does

beginTransaction()

start fragment transaction and returns FragmentTransaction

findFragmentById(int id)

by passing id, it returns fragment instance.

FragmentTransaction

FragmentTransactionperforms fragment operations. Find some methods.

Function

What it does

add(int containerViewId, Fragment fragment)

adds a given fragment to activity state.

attach(Fragment fragment)

The detached fragment can be re-attached by using this method.

detach(Fragment fragment)

Detaches the given fragment from UI. Fragment state is still managed by FragmentManager.

remove(Fragment fragment)

Removes the given fragment from UI and container.

replace(int containerViewId, Fragment fragment)

For the given container view id, we can replace existing fragment by new given fragment.

commit()

Transaction is committed.

Fragment operations are wrapped into a transaction:

  • Start transaction with beginTransaction()

  • Do all Fragment operations (add, remove, etc.)

  • addingtoBackStack(null) saves transaction to the back stack so the user can reverse the transaction and bring back the previous fragment by pressing the Back button.

  • End transaction with commit()

Alright, now we just need to add a Button and set up its OnClickListener() to our functions

First, place the button in the activity_main.xml layout

<Button
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/button_car"
    app:layout_constraintTop_toBottomOf="@id/article"
    />

Now, find its view in the MainActivity and setOnClickListener()

Button sButtonl;
    private Boolean isFragmentDisplayed = false;
    static final String STATE_FRAGMENT = "state_of_fragment";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sButtonl = findViewById(R.id.button);
        sButtonl.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!isFragmentDisplayed){
                    displayFragment();
                }else{
                    closeFragment();
                }
            }
        });
        if(savedInstanceState!=null){
            isFragmentDisplayed = savedInstanceState.getBoolean(STATE_FRAGMENT);
        }
        
    }
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState){
        savedInstanceState.putBoolean(STATE_FRAGMENT,isFragmentDisplayed);
        super.onSaveInstanceState(savedInstanceState);
    }
    

And you should be able to build and run your app!

Last updated