Fragments


שימוש בפרגמנטים

Single Activity, Three Fragments, Bottom Navigation


Overview

This tutorial will guide you through creating an Android project with:

  • One Activity (MainActivity)
  • Three Fragments (Fragment1, Fragment2, Fragment3)
  • Bottom Navigation to switch between fragments
  • Each fragment with a Button and a TextView
  • When you click the button, the TextView updates with a message specific to the fragment

The focus:

  • Understanding fragment lifecycle methods: onCreateView vs. onViewCreated
  • Using the FragmentManager to swap fragments
  • Implementing bottom navigation

1. Project Structure

app/
├─ java/
│   └─ com.example.bottomnavdemo/
│       ├─ MainActivity.java
│       ├─ Fragment1.java
│       ├─ Fragment2.java
│       └─ Fragment3.java
├─ res/
│   ├─ layout/
│   │   ├─ activity_main.xml
│   │   ├─ fragment_1.xml
│   │   ├─ fragment_2.xml
│   │   └─ fragment_3.xml
│   ├─ menu/
│   │   └─ bottom_nav_menu.xml
│   └─ drawable/

2. Add Material Library

In your build.gradle (Module: app):

    implementation (libs.material)

3. Bottom Navigation Menu

res/menu/bottom_nav_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/nav_fragment1"
        android:icon="@drawable/ic_looks_one"
        android:title="Fragment 1" />
    <item
        android:id="@+id/nav_fragment2"
        android:icon="@drawable/ic_looks_two"
        android:title="Fragment 2" />
    <item
        android:id="@+id/nav_fragment3"
        android:icon="@drawable/ic_looks_3"
        android:title="Fragment 3" />
</menu>

You can use built-in icons or your own drawables for demonstration.


4. Main Layout

res/layout/activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:menu="@menu/bottom_nav_menu"/>
</LinearLayout>

5. Fragment Layouts

res/layout/fragment_1.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btnFragment1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fragment 1" />

    <TextView
        android:id="@+id/tvFragment1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:textSize="18sp"
        android:layout_marginTop="20dp" />
</LinearLayout>

(Copy & adapt for fragment_2.xml and fragment_3.xml, changing IDs and Button text to btnFragment2, tvFragment2, etc.)


6. MainActivity.java

package com.example.bottomnavdemo;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import com.google.android.material.bottomnavigation.BottomNavigationView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);

        // Show Fragment1 by default
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, new Fragment1())
                .commit();
        }

        bottomNav.setOnItemSelectedListener(item -> {
            Fragment selectedFragment = null;
            switch (item.getItemId()) {
                case R.id.nav_fragment1:
                    selectedFragment = new Fragment1();
                    break;
                case R.id.nav_fragment2:
                    selectedFragment = new Fragment2();
                    break;
                case R.id.nav_fragment3:
                    selectedFragment = new Fragment3();
                    break;
            }
            if (selectedFragment != null) {
                getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, selectedFragment)
                    .commit();
            }
            return true;
        });
    }
}

7. Fragment1.java

package com.example.bottomnavdemo;

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.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class Fragment1 extends Fragment {

    // 1. onCreateView: Inflate and return the layout for the fragment
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        // Only inflate and return the view here
        return inflater.inflate(R.layout.fragment_1, container, false);
    }

    // 2. onViewCreated: View is created, set up listeners and UI logic here
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Button btn = view.findViewById(R.id.btnFragment1);
        TextView tv = view.findViewById(R.id.tvFragment1);

        btn.setOnClickListener(v -> tv.setText("Clicked button in fragment number 1"));
    }
}

8. Fragment2.java and Fragment3.java

(Repeat similar structure, updating IDs and text for each fragment)

Fragment2.java

package com.example.bottomnavdemo;

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.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class Fragment2 extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_2, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Button btn = view.findViewById(R.id.btnFragment2);
        TextView tv = view.findViewById(R.id.tvFragment2);

        btn.setOnClickListener(v -> tv.setText("Clicked button in fragment number 2"));
    }
}

Fragment3.java

package com.example.bottomnavdemo;

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.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class Fragment3 extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_3, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Button btn = view.findViewById(R.id.btnFragment3);
        TextView tv = view.findViewById(R.id.tvFragment3);

        btn.setOnClickListener(v -> tv.setText("Clicked button in fragment number 3"));
    }
}

9. Key Learnings: onCreateView vs. onViewCreated

  • onCreateView:
    • Inflate and return the fragment’s view (do NOT do logic or access UI elements here)
    • Use only for layout inflation
  • onViewCreated:
    • Called after the view is created and attached
    • Safe place to find views with view.findViewById, set up listeners, adapters, update UI, etc.
    • Keeps code clean and avoids null pointer exceptions

10. Run & Test

  • Launch the app.
  • Tap each bottom navigation item to switch fragments.
  • Each fragment should show its own button.
  • When you tap the button, the TextView updates with the relevant message.

Summary Table

Fragment Method Use For Example In This Project
onCreateView Inflate the layout, return View inflater.inflate(..., ...)
onViewCreated Set up UI logic/listeners on the view Set button click listeners

You now have a clean demonstration of:

  • Bottom navigation
  • FragmentManager usage for swapping fragments
  • Fragment lifecycle: onCreateView vs. onViewCreated