Navigation (bazen routing) olarak bilinen sayfa/ekran arası geçişler; web, masaüstü, veya mobil farketmeksizin her türlü ön yüz (front-end) geliştiriciliğinin bel kemiğini oluşturur. Android üzerinde bu işler Jetpack ile beraber çok daha kolay hale geldi. Bu yazıda basit bir örnekle fragmentler arası geçişlerin Jetpack kütüphaneleri kullanılarak nasıl yapılacağına bakalım.

Vereceğimiz örneğin omurgasını kısaca listelemek gerekirse:

  • activity_main üzerinde NavHostFragment bileşeni
  • NavHostFragment üzerinde 2 tane fragment ve bu fragmentler arası geçişler (action)
  • Fragment içerisinde action'ı çağıracak düğme kontrolü
  • Ekranın üst kısmındaki geri tuşu

Şimdi de adım adım bu bileşenleri ekleyelim:

  • Öncelikle yeni bir Android projesi yaratın ve şablon kısmında "Empty Activity"'e tıklayın.
  • app kısmına sağ tıklayarak "New > Android Resource File" seçin.
  • File name kısmına istediğiniz bir ismi verip Resource type kısmına ise Navigation diyerek devam edin. OK tuşuna bastığınızda Android Studio gradle bağımlılıklarını eklemenizi isteyecek. Ona da tamam diyerek devam edin.

build.gradle (Module:app) dosyasına bakacak olursanız aşağıdaki satırların (versiyon numaraları farklı olabilir elbet) eklenmiş olduğunu göreceksiniz. Eğer bir şekilde Android Studio eklemeyi başaramamış ise dependencies kısmına siz ekleyin.

implementation 'androidx.navigation:navigation-fragment:2.2.0'
implementation 'androidx.navigation:navigation-ui:2.2.0'
  • Daha sonra New > Fragment > Fragment (Blank) kullanarak 2 adet fragment ekleyin. Birine ListeFragment öbürüne DetayFragment diyebilirsiniz. Burada "Include fragment factory methods" ve "Include interface callbacks" seçeneklerinin seçili durumunu kaldırın.
  • Android Studio her fragment için biri java öbürü xml olmak üzere 2 dosya oluşturacak. (ör. ListeFragment.java ve fragment_liste.xml)
  • fragment_liste.xml içerisindeki metin kontrolünü silin ve yerine bir tane düğme ekleyin. Ben FloatingActionButton ekledim. Verdiğimiz basit örnek için hangi kontrol olduğunun çok önemi yok. Benim fragment_liste.xml dosyam aşağıdaki gibi oldu:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".ListFragment">

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:src="@android:drawable/btn_star_big_on"
        android:focusable="true"
        android:layout_gravity="bottom|right"
        android:layout_margin="10dp"
        />
</FrameLayout>
  • activity_main.xml dosyasını açın ve içerisindeki metin bileşenini silin ve bir NavHostFragment ekleyin. Eklerken bu hostun hangi resource dosyasından geleceğini soran bir pencere açılacak. Bu örnekte sadece 1 navigation kontrolü olduğu için listedeki tek elemanı seçin ve devam edin.
  • Şimdi ise app > res > navigation içerisindeki xml dosyasını açın ve yeşil artı ikonu bulunan "New Destination" tuşuna basarak 2 fragmenti ekleyin. Liste fragmentinden detay fragmentine sürükle bırakla bir action ekleyin. Aşağıdaki gibi bir görüntü oluşması gerekiyor.
Nav Host Fragment

Artık kodlamaya geçebiliriz. Öncelikle FloatingActionButton'ın işlemini gerçekleştirelim. Tuşa bastığımızda yukarıda okla gösterilen action'ı çağıracağız ve liste fragmentinden detay fragmentine geçiş yapacağız. Çoğu işlemi Android arka planda gerçekleştiriyor. Bize sadece action'ı çağırmak düşüyor. Benim kodum aşağıdaki gibi oldu. İsimlendirmelerimiz farklı olacağı için olduğu gibi yapıştırırsanız hata alabilirsiniz.

public class ListFragment extends Fragment implements View.OnClickListener {


    public ListFragment() {

    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View vw = inflater.inflate(R.layout.fragment_list, container, false);
        FloatingActionButton fab = vw.findViewById(R.id.fab_list);
        fab.setOnClickListener(this);
        return vw;
    }

    @Override
    public void onClick(View v) {

        NavDirections action = new ActionOnlyNavDirections(R.id.action_listFragment_to_detailFragment);
        Navigation.findNavController(v).navigate(action);
    }
}

FloatingActionButton'ın ID'sini kullanarak referansına eriştik ve OnClickListener yardımıyla ekran geçişini tanımlayan action'ı çağırdık.

Şimdi de MainActivity.java'yı aşağıdaki gibi değiştirerek geri tuşunu aktif hale getirelim.

public class MainActivity extends AppCompatActivity {

    private NavController navController;

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

        navController = Navigation.findNavController(this, R.id.fragment);
        NavigationUI.setupActionBarWithNavController(this, navController);

    }

    @Override
    public boolean onSupportNavigateUp() {
        return NavigationUI.navigateUp(navController, (DrawerLayout) null);
    }
}

Sonuç aşağıdaki gibi:

Jetpack Navigation

Sonuç olarak Jetpack Navigation, standart işlemleri çok kolaylaştırıyor. En güzel yanı da neredeyse her yazılım geliştirici bunu benzer şekilde kullanıyor ve başkasının yazdığı kodu okumayı da oldukça kolay hale getiriyor.