Gezinme bileşenine taşıma

Gezinme bileşeni, karmaşık gezinmeyi yönetebilen bir kitaplık, geçiş animasyonu, derin bağlantı ve .

Bu doküman, mevcut bir uygulamanın Google Yönetici Konsolu'na taşınması için genel Gezinme bileşenini kullanma.

Taşıma işlemi genel olarak şu adımları içerir:

  1. Ekrana özgü kullanıcı arayüzü mantığını etkinliklerin dışına taşıyın: Uygulamanızın kullanıcı arayüzünü taşıyın Böylece her aktivitenin yalnızca Scrum’da aynı mantıktan yola çıkarak Toolbar gibi genel gezinme kullanıcı arayüzü bileşenleri her ekranın bir parçaya veya özel hedefe uygulanmasını sağlayın.

  2. Gezinme bileşenini entegre edin: Her etkinlik için bir tarafından yönetilen bir veya daha çok parçayı içeren gezinme grafiği etkinliği'ne dokunun. Parça işlemlerini Gezinme bileşeni işlemleriyle değiştirin.

  3. Etkinlik hedefi ekle - startActivity() aramayı şununla değiştir: işlemlerdir.

  4. Etkinlikleri birleştirme: Şu durumlarda gezinme grafiklerini birleştirin: Ortak bir düzene sahip birden çok etkinlik vardır.

ziyaret edin.

Ön koşullar

Bu kılavuzda, uygulamanızı kullanmak için önceden taşıdığınız varsayılır. AndroidX kitaplıklarında güncelleyin. Henüz yapmadıysanız projenizi taşımadan önce AndroidX'i devam ediyor.

Ekrana özgü kullanıcı arayüzü mantığını etkinliklerin dışına taşı

Etkinlikler, grafik etkileşimi kolaylaştıran sistem düzeyinde bileşenlerdir en iyi uygulamaları paylaşacağız. Etkinlikler, uygulamanızın manifest dosyasına kaydedilir Böylece Android hangi etkinliklerin başlatılabileceğini bilir. Etkinlik sınıfı, uygulamanızın Android değişikliklerine de tepki vermesini sağlar (örneğin, Uygulamanın kullanıcı arayüzü ön plana giriyor veya ön plandan çıkıyor, dönüyor vb. İlgili içeriği oluşturmak için kullanılan ve etkinlikleriniz aynı zamanda ekranlar arasında durum paylaşma bölümüne bakın.

Uygulamanız bağlamında etkinlikler, gezinme için bir barındırma aracı işlevi görmelidir. ekranlar arasında geçiş yapmanın mantığını ve bilgisini içerir. vs. Ancak kullanıcı arayüzünüzün ayrıntılarını yönetmek yeniden kullanılabilir bir parçaya dönüştürmenizi sağlar. Bu için önerilen uygulama kalıp parçalardır. Görüntüleyin Tek etkinlik: Neden, ne zaman ve nasıl? başlıklı makalemizi incelemenizi öneririz. Gezinme, navigasyon parçası bağımlılığı aracılığıyla parçaları destekler. Navigasyon, özel hedef türleri bölümüne gidin.

Uygulamanız fragman kullanmıyorsa yapmanız gereken ilk şey bir parça kullanmak için her ekranı kullanın. Şu konumdaki etkinliği kaldırmıyorsunuz: bu noktada. Bunun yerine, ekranı temsil eden bir parça oluşturuyor ve kullanıcı arayüzü mantığınızı sorumluluk çerçevesinde ayırmanız gerekir.

Parçalarla tanışın

Parçaları tanıtma sürecini göstermek için bir örnekle başlayalım. iki ekrandan oluşan bir uygulamadır: ürün listesi ekranı ve product details (ürün ayrıntıları) ekranını belirtin. Liste ekranındaki bir ürünü tıkladığınızda veya ürünle ilgili daha fazla bilgi edinmek için kullanıcının bir ayrıntılar ekranına gelmesini sağlar.

Bu örnekte, liste ve ayrıntılar ekranları şu anda ayrı etkinliklerdir.

Kullanıcı Arayüzünü Barındırmak İçin Yeni Bir Düzen Oluşturun

Bir parçayı kullanıma sunmak için önce etkinliğin depolanacağı yeni bir düzen dosyası oluşturun. barındırmasına olanak tanır. Bu, etkinliğin mevcut içerik görüntüleme düzeninin yerini alır.

Basit bir görünüm için aşağıda gösterildiği gibi bir FrameLayout kullanabilirsiniz: örnek product_list_host:

<FrameLayout
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/main_content"
   android:layout_height="match_parent"
   android:layout_width="match_parent" />

id özelliği, olabilir.

Ardından, etkinliğinizin onCreate() işlevinde, düzen dosyası referansını değiştirin. aşağıdaki yeni düzen dosyasına işaret etmek için etkinliğinizin onCreate işlevinde kullanabilirsiniz:

Kotlin

class ProductListActivity : AppCompatActivity() {
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Replace setContentView(R.layout.product_list) with the line below
        setContentView(R.layout.product_list_host)
        ...
    }
}

Java

public class ProductListActivity extends AppCompatActivity {
    ...
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        ...
        // Replace setContentView(R.layout.product_list); with the line below
        setContentView(R.layout.product_list_host);
        ...
    }
}

Mevcut düzen (bu örnekte product_list), kök görünümü olarak kullanılır parçaya yerleştirin.

Parça oluşturma

Ekranınızın kullanıcı arayüzünü yönetmek için yeni bir parça oluşturun. Bu nedenle kullanabileceğiniz etkinlik barındırıcı adınızla tutarlı olmalıdır. Aşağıdaki snippet, ProductListFragment, örneğin:

Kotlin

class ProductListFragment : Fragment() {
    // Leave empty for now.
}

Java

public class ProductListFragment extends Fragment {
    // Leave empty for now.
}

Etkinlik mantığını bir parçaya taşı

Parça tanımı oluşturulduktan sonra sıradaki adım, bu ekranı, etkinlikten bu yeni parçaya aktarır. Bir işleme dayalı mimariniz varsa büyük olasılıkla çok sayıda görünüm etkinliğinizin onCreate() işlevinde gerçekleşiyor.

Taşımamız gereken kullanıcı arayüzü mantığına sahip etkinliğe dayalı bir ekran örneğini burada bulabilirsiniz:

Kotlin

class ProductListActivity : AppCompatActivity() {

    // Views and/or ViewDataBinding references, Adapters...
    private lateinit var productAdapter: ProductAdapter
    private lateinit var binding: ProductListActivityBinding

    ...

    // ViewModels, System Services, other Dependencies...
    private val viewModel: ProductListViewModel by viewModels()

    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // View initialization logic
        DataBindingUtil.setContentView(this, R.layout.product_list_activity)

        // Post view initialization logic
        // Connect adapters
        productAdapter = ProductAdapter(productClickCallback)
        binding.productsList.setAdapter(productAdapter)

        // Initialize view properties, set click listeners, etc.
        binding.productsSearchBtn.setOnClickListener {...}

        // Subscribe to state
        viewModel.products.observe(this, Observer { myProducts ->
            ...
        })

        // ...and so on
    }
   ...
}

Java

public class ProductListActivity extends AppCompatActivity {

    // Views and/or ViewDataBinding references, adapters...
    private ProductAdapter productAdapter;
    private ProductListActivityBinding binding;

    ...

    // ViewModels, system services, other dependencies...
    private ProductListViewModel viewModel;

    ...

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // View initialization logic
        DataBindingUtil.setContentView(this, R.layout.product_list_activity);

        // Post view initialization logic
        // Connect adapters
        productAdapter = new ProductAdapter(productClickCallback);
        binding.productsList.setAdapter(productAdapter);

        // Initialize ViewModels and other dependencies
        ProductListViewModel viewModel = new ViewModelProvider(this).get(ProductListViewModel.java);

        // Initialize view properties, set click listeners, etc.
        binding.productsSearchBtn.setOnClickListener(v -> { ... });

        // Subscribe to state
        viewModel.getProducts().observe(this, myProducts ->
            ...
       );

       // ...and so on
   }

Etkinliğiniz ayrıca kullanıcının şuraya ne zaman ve nasıl erişeceğini kontrol ediyor olabilir: sonraki ekranı seçin:

Kotlin

    // Provided to ProductAdapter in ProductListActivity snippet.
    private val productClickCallback = ProductClickCallback { product ->
        show(product)
    }

    fun show(product: Product) {
        val intent = Intent(this, ProductActivity::class.java)
        intent.putExtra(ProductActivity.KEY_PRODUCT_ID, product.id)
        startActivity(intent)
    }

Java

// Provided to ProductAdapter in ProductListActivity snippet.
private ProductClickCallback productClickCallback = this::show;

private void show(Product product) {
    Intent intent = new Intent(this, ProductActivity.class);
    intent.putExtra(ProductActivity.KEY_PRODUCT_ID, product.getId());
    startActivity(intent);
}

Parçanızın içinde bu çalışmayı onCreateView() ve onViewCreated(), yalnızca gezinme mantığıyla:

Kotlin

class ProductListFragment : Fragment() {

    private lateinit var binding: ProductListFragmentBinding
    private val viewModel: ProductListViewModel by viewModels()

     // View initialization logic
    override fun onCreateView(inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?): View? {
        binding = DataBindingUtil.inflate(
                inflater,
                R.layout.product_list,
                container,
                false
        )
        return binding.root
    }

    // Post view initialization logic
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // Connect adapters
        productAdapter = ProductAdapter(productClickCallback)
        binding.productsList.setAdapter(productAdapter)

        // Initialize view properties, set click listeners, etc.
        binding.productsSearchBtn.setOnClickListener {...}

        // Subscribe to state
        viewModel.products.observe(this, Observer { myProducts ->
            ...
        })

        // ...and so on
    }

    // Provided to ProductAdapter
    private val productClickCallback = ProductClickCallback { product ->
        if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
            (requireActivity() as ProductListActivity).show(product)
        }
    }
    ...
}

Java

public class ProductListFragment extends Fragment {

    private ProductAdapter productAdapter;
    private ProductListFragmentBinding binding;

    // View initialization logic
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
            @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        binding = DataBindingUtil.inflate(
                inflater,
                R.layout.product_list_fragment,
                container,
                false);
        return binding.getRoot();
    }

    // Post view initialization logic
    @Override
    public void onViewCreated(@NonNull View view,
            @Nullable Bundle savedInstanceState) {

        // Connect adapters
        binding.productsList.setAdapter(productAdapter);

        // Initialize ViewModels and other dependencies
        ProductListViewModel viewModel = new ViewModelProvider(this)
                .get(ProductListViewModel.class);

        // Initialize view properties, set click listeners, etc.
        binding.productsSearchBtn.setOnClickListener(...)

        // Subscribe to state
        viewModel.getProducts().observe(this, myProducts -> {
            ...
       });

       // ...and so on

    // Provided to ProductAdapter
    private ProductClickCallback productClickCallback = new ProductClickCallback() {
        @Override
        public void onClick(Product product) {
            if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
                ((ProductListActivity) requireActivity()).show(product);
            }
        }
    };
    ...
}

ProductListFragment içinde setContentView() bağlantı kurmak için de kullanabilirsiniz. Bir parçada, onCreateView() ilk kullanıma hazırlar: kök görünümü. onCreateView(), şunun bir örneğini alır: LayoutInflater Bir düzen kaynak dosyasına göre kök görünümünü şişirin. Bu örnekte, hiçbir şey olmadığı için etkinlik tarafından kullanılan mevcut product_list düzeni düzenin kendisinin değiştirilmesi gerekiyor.

Etkinliğinizin onStart(), onResume() ve sonraki adımlarında yer alan kullanıcı arayüzü mantığınız varsa gezinmeyle ilgili olmayan onPause() veya onStop() işlevleri için bunları parça üzerinde aynı ada sahip karşılık gelen işlevlere taşımanızı sağlar.

Ana makine etkinliğinde parçayı başlatın

Kullanıcı arayüzü mantığının tamamını parçaya taşıdıktan sonra yalnızca gezinme etkinlikte de kalmalıdır.

Kotlin

class ProductListActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.product_list_host)
    }

    fun show(product: Product) {
        val intent = Intent(this, ProductActivity::class.java)
        intent.putExtra(ProductActivity.KEY_PRODUCT_ID, product.id)
        startActivity(intent)
    }
}

Java

public class ProductListActivity extends AppCompatActivity {

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

    public void show(Product product) {
        Intent intent = new Intent(this, ProductActivity.class);
        intent.putExtra(ProductActivity.KEY_PRODUCT_ID, product.getId());
        startActivity(intent);
    }
}

Son adım, onCreate() içinde parçanın bir örneğini oluşturmaktır. içerik görünümünü ayarladıktan sonra:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.product_list_host)

    if (savedInstanceState == null) {
        val fragment = ProductListFragment()
        supportFragmentManager
                .beginTransaction()
                .add(R.id.main_content, fragment)
                .commit()
    }
}

Java

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

    if (savedInstanceState == null) {
        ProductListFragment fragment = new ProductListFragment();
        getSupportFragmentManager()
                .beginTransaction()
                .add(R.id.main_content, fragment)
                .commit();
    }
}

Bu örnekte gösterildiği gibi, FragmentManager otomatik olarak kaydeder ve geri yükler yapılandırma değişikliklerinden yararlanır. Böylece, yalnızca savedInstanceState null.

Amaç ekstralarını parçaya iletin

Etkinliğiniz bir intent üzerinden Extras alıyorsa bunları bağımsız değişken olarak oluşturabilirsiniz.

Bu örnekte ProductDetailsFragment, bağımsız değişkenlerini doğrudan alır etkinliğin amaç ekstralarından:

Kotlin

...

if (savedInstanceState == null) {
    val fragment = ProductDetailsFragment()

    // Intent extras and Fragment Args are both of type android.os.Bundle.
    fragment.arguments = intent.extras

    supportFragmentManager
            .beginTransaction()
            .add(R.id.main_content, fragment)
            .commit()
}

...

Java

...

if (savedInstanceState == null) {
    ProductDetailsFragment fragment = new ProductDetailsFragment();

    // Intent extras and fragment Args are both of type android.os.Bundle.
    fragment.setArguments(getIntent().getExtras());

    getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.main_content, fragment)
            .commit();
}

...

Bu noktada, uygulamanızı çalıştırmayı ilk ekranla test edebilmeniz gerekir bir parça kullanacak şekilde güncellenir. Etkinliğe dayalı diğer etkinlikleri taşımaya devam edin her yinelemeden sonra test etmek zaman alır.

Gezinme bileşenini entegre etme

Parça tabanlı bir mimari kullanmaya başladıktan sonra Gezinme bileşenini entegre etmeye hazır olursunuz.

Öncelikle, en yeni Navigasyon bağımlılıklarını projenize ekleyin, buradaki talimatlar Gezinme kitaplığı sürüm notları.

Gezinme grafiği oluşturma

Navigasyon bileşeni, kaynak dosyasını grafik halinde gösterecek şekilde tanımlarsınız. Bu, kullanıcıların uygulamanızın gezinme deneyimini kod tabanınızın dışında düzenli bir şekilde tutar ve gezinmenizi görsel olarak düzenlemenize olanak tanır.

Gezinme grafiği oluşturmak için önce adlı yeni bir kaynak klasörü oluşturun. navigation Grafiği eklemek için bu dizini sağ tıklayın ve Yeni > Gezinme kaynak dosyası.

Gezinme bileşeni bir etkinliği gezinme ana makinesi ve kullanıcılarınız sayfada gezinirken tek tek parçaları bu ana makineyle değiştirir en iyi şekilde yararlanabilirsiniz. Uygulamanızın gezinme şeklini görsel olarak düzenlemeye başlamadan önce bunu barındıracak etkinliğin içinde bir NavHost yapılandırmanız gerekir grafiğe dönüştürülebilir. Parçaları kullandığımız için Gezinme bileşeninin varsayılan NavHost uygulaması, NavHostFragment

NavHostFragment, FragmentContainerView üzerinden yapılandırılır aşağıdaki örnekte gösterildiği gibi, bir barındırıcı etkinliğinin içine yerleştirilir:

<androidx.fragment.app.FragmentContainerView
   android:name="androidx.navigation.fragment.NavHostFragment"
   app:navGraph="@navigation/product_list_graph"
   app:defaultNavHost="true"
   android:id="@+id/main_content"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />

app:NavGraph özelliği, bununla ilişkili gezinme grafiğini işaret eder gezinme ana makinesi. Bu özelliğin ayarlanması, gezinme grafiğini şişirir ve grafiği ayarlar NavHostFragment üzerinde. app:defaultNavHost özelliği, NavHostFragment cihazınızın sistemin Geri düğmesini engellediğini doğrulayın.

DrawerLayout veya BottomNavigationView, bu FragmentContainerView ana içerik görünümü öğenizin yerini alır. Görüntüleyin Gezinme Arayüzü ile kullanıcı arayüzü bileşenlerini güncelleme inceleyebilirsiniz.

Basit bir düzen için şunu ekleyebilirsiniz: FragmentContainerView öğesini ViewGroup kökünün alt öğesi olarak kullanın:

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

<androidx.fragment.app.FragmentContainerView
   android:id="@+id/main_content"
   android:name="androidx.navigation.fragment.NavHostFragment"
   app:navGraph="@navigation/product_list_graph"
   app:defaultNavHost="true"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />

</FrameLayout>

Alt kısımdaki Tasarım sekmesini tıklarsanız benzer bir grafik görürsünüz ona benzer. Grafiğin sol üst tarafında, Hedefler'i seçerseniz NavHost etkinliğine ilişkin referansları formda görebilirsiniz / layout_name (resource_id).

Artı düğmesini tıklayın. . tıklayın.

Gezinme bileşeni, ekranları hedefler olarak ifade eder. Hedefler; parçalar, etkinlikler veya özel hedefler olabilir. Ekleyebileceğiniz: grafiğinize her tür hedefin eklenmesidir, ancak etkinlik hedeflerinin terminal hedefler olarak kabul edilir, çünkü bir etkinliğe gittiğinizde ayrı bir gezinme ana makinesinde ve grafikte faaliyet gösteriyorsanız

Gezinme bileşeni, kullanıcıların bir tarayıcıdan web'de başka bir hedefe işlem olarak atayabilirsiniz. İşlemler, geçiş sürecini popüler animasyonlar ve pop davranışı.

Parça işlemlerini kaldırma

Artık Gezinme bileşenini kullandığınıza göre, aynı etkinlik altındaki parça tabanlı ekranlar arasında geziniyorsanız FragmentManager etkileşimleridir.

Uygulamanız aynı etkinlik veya üst düzey altında birden fazla parça kullanıyorsa gezinme gibi bir gezinme alanına sahipseniz muhtemelen FragmentManager ve FragmentTransactions bölümüne ekleyin veya mevcut parçaları değiştirin. Bu artık gezinme bileşeni kullanılarak değiştirilebilir ve basitleştirilir. hedefleri bağlayıp gezinmek için NavController

Karşılaşabileceğiniz birkaç senaryo ve bu senaryoda taşımayı öğreteceğim.

Birden çok parçayı yöneten tek bir etkinlik

Birden çok parçayı yöneten tek bir etkinliğiniz varsa etkinliğiniz kod aşağıdaki gibi görünebilir:

Kotlin

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Logic to load the starting destination
        //  when the Activity is first created
        if (savedInstanceState == null) {
            val fragment = ProductListFragment()
            supportFragmentManager.beginTransaction()
                    .add(R.id.fragment_container, fragment, ProductListFragment.TAG)
                    .commit()
        }
    }

    // Logic to navigate the user to another destination.
    // This may include logic to initialize and set arguments on the destination
    // fragment or even transition animations between the fragments (not shown here).
    fun navigateToProductDetail(productId: String) {
        val fragment = new ProductDetailsFragment()
        val args = Bundle().apply {
            putInt(KEY_PRODUCT_ID, productId)
        }
        fragment.arguments = args

        supportFragmentManager.beginTransaction()
                .addToBackStack(ProductDetailsFragment.TAG)
                .replace(R.id.fragment_container, fragment, ProductDetailsFragment.TAG)
                .commit()
    }
}

Java

public class MainActivity extends AppCompatActivity {

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

        // Logic to load the starting destination when the activity is first created.
        if (savedInstanceState == null) {
            val fragment = ProductListFragment()
            supportFragmentManager.beginTransaction()
                    .add(R.id.fragment_container, fragment, ProductListFragment.TAG)
                    .commit();
        }
    }

    // Logic to navigate the user to another destination.
    // This may include logic to initialize and set arguments on the destination
    // fragment or even transition animations between the fragments (not shown here).
    public void navigateToProductDetail(String productId) {
        Fragment fragment = new ProductDetailsFragment();
        Bundle args = new Bundle();
        args.putInt(KEY_PRODUCT_ID, productId);
        fragment.setArguments(args);

        getSupportFragmentManager().beginTransaction()
                .addToBackStack(ProductDetailsFragment.TAG)
                .replace(R.id.fragment_container, fragment, ProductDetailsFragment.TAG)
                .commit();
    }
}

Kaynak hedefin içinde, yanıt olarak kullanabilirsiniz:

Kotlin

class ProductListFragment : Fragment() {
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // In this example a callback is passed to respond to an item clicked
        //  in a RecyclerView
        productAdapter = ProductAdapter(productClickCallback)
        binding.productsList.setAdapter(productAdapter)
    }
    ...

    // The callback makes the call to the activity to make the transition.
    private val productClickCallback = ProductClickCallback { product ->
            (requireActivity() as MainActivity).navigateToProductDetail(product.id)
    }
}

Java

public class ProductListFragment extends Fragment  {
    ...
    @Override
    public void onViewCreated(@NonNull View view,
            @Nullable Bundle savedInstanceState) {
    // In this example a callback is passed to respond to an item clicked in a RecyclerView
        productAdapter = new ProductAdapter(productClickCallback);
        binding.productsList.setAdapter(productAdapter);
    }
    ...

    // The callback makes the call to the activity to make the transition.
    private ProductClickCallback productClickCallback = product -> (
        ((MainActivity) requireActivity()).navigateToProductDetail(product.getId())
    );
}

Bunun yerine, gezinme grafiğinizi başlangıç hedefini ve hedeflerinizi bağlamak ve hedeflerinizi bağımsız değişkenlerin kullanılması için:

<navigation 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:id="@+id/product_list_graph"
    app:startDestination="@id/product_list">

    <fragment
        android:id="@+id/product_list"
        android:name="com.example.android.persistence.ui.ProductListFragment"
        android:label="Product List"
        tools:layout="@layout/product_list">
        <action
            android:id="@+id/navigate_to_product_detail"
            app:destination="@id/product_detail" />
    </fragment>
    <fragment
        android:id="@+id/product_detail"
        android:name="com.example.android.persistence.ui.ProductDetailFragment"
        android:label="Product Detail"
        tools:layout="@layout/product_detail">
        <argument
            android:name="product_id"
            app:argType="integer" />
    </fragment>
</navigation>

Ardından, etkinliğinizi güncelleyebilirsiniz:

Kotlin

class MainActivity : AppCompatActivity() {

    // No need to load the start destination, handled automatically by the Navigation component
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Java

public class MainActivity extends AppCompatActivity {

    // No need to load the start destination, handled automatically by the Navigation component
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

Etkinlik için artık navigateToProductDetail() yöntemi gerekmiyor. Sonraki bölümünde, gezinme için NavController alanını kullanacak şekilde ProductListFragment uygulamasını güncelliyoruz. devam edebilir.

Bağımsız değişkenleri güvenli bir şekilde iletin

Gezinme bileşeninde, Güvenli Bağımsız Değişkenler için basit nesne ve derleyici sınıfları oluşturan bir web sitesi, hedefler ve işlemler için belirtilen bağımsız değişkenlerdir.

Eklenti uygulandıktan sonra, sayfanızdaki bir hedefte tanımlanan tüm bağımsız değişkenler gezinme grafiği, Gezinme bileşeni çerçevesinin bir Hedef hedefe tür güvenli bağımsız değişkenler sağlayan Arguments sınıfı. Bir işlem tanımlamak, eklentinin bir Directions yapılandırması oluşturmasına neden olur NavController ürününe kullanıcının hedefe nasıl gideceğini bildirmek için kullanılabilecek sınıf belirleniyor. Bir işlem gerekli bir hedefe yönlendirdiğinde bağımsız değişkenlerin olmadığı durumlarda, oluşturulan Directions sınıfı gerekli değildir.

Parçanın içinde NavController ve oluşturulan Directions sınıfını kullanarak Aşağıda gösterildiği gibi, hedef hedefe tür için güvenli bağımsız değişkenler sağlayın örnek:

Kotlin

class ProductListFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // In this example a callback is passed to respond to an item clicked in a RecyclerView
        productAdapter = ProductAdapter(productClickCallback)
        binding.productsList.setAdapter(productAdapter)
    }
    ...

    // The callback makes the call to the NavController to make the transition.
    private val productClickCallback = ProductClickCallback { product ->
        val directions = ProductListDirections.navigateToProductDetail(product.id)
        findNavController().navigate(directions)
    }
}

Java

public class ProductListFragment extends Fragment  {
    ...
    @Override
    public void onViewCreated(@NonNull View view,
            @Nullable Bundle savedInstanceState) {
        // In this example a callback is passed to respond to an item clicked in a RecyclerView
        productAdapter = new ProductAdapter(productClickCallback);
        binding.productsList.setAdapter(productAdapter);
    }
    ...

    // The callback makes the call to the activity to make the transition.
    private ProductClickCallback productClickCallback = product -> {
        ProductListDirections.ViewProductDetails directions =
                ProductListDirections.navigateToProductDetail(product.getId());
        NavHostFragment.findNavController(this).navigate(directions);
    };
}

Üst Düzey Gezinme

Uygulamanızda DrawerLayout kullanılıyorsa birçok yapılandırma mantığınız olabilir çekmecenizin açılıp kapatılmasını ve diğer hedefler.

Bunun sonucunda elde ettiğiniz etkinlik aşağıdaki gibi görünebilir:

Kotlin

class MainActivity : AppCompatActivity(),
    NavigationView.OnNavigationItemSelectedListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val toolbar: Toolbar = findViewById(R.id.toolbar)
        setSupportActionBar(toolbar)

        val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
        val navView: NavigationView = findViewById(R.id.nav_view)
        val toggle = ActionBarDrawerToggle(
                this,
                drawerLayout,
                toolbar,
                R.string.navigation_drawer_open, 
                R.string.navigation_drawer_close
        )
        drawerLayout.addDrawerListener(toggle)
        toggle.syncState()

        navView.setNavigationItemSelectedListener(this)
    }

    override fun onBackPressed() {
        val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START)
        } else {
            super.onBackPressed()
        }
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        // Handle navigation view item clicks here.
        when (item.itemId) {
            R.id.home -> {
                val homeFragment = HomeFragment()
                show(homeFragment)
            }
            R.id.gallery -> {
                val galleryFragment = GalleryFragment()
                show(galleryFragment)
            }
            R.id.slide_show -> {
                val slideShowFragment = SlideShowFragment()
                show(slideShowFragment)
            }
            R.id.tools -> {
                val toolsFragment = ToolsFragment()
                show(toolsFragment)
            }
        }
        val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
        drawerLayout.closeDrawer(GravityCompat.START)
        return true
    }
}

private fun show(fragment: Fragment) {

    val drawerLayout = drawer_layout as DrawerLayout
    val fragmentManager = supportFragmentManager

    fragmentManager
            .beginTransaction()
            .replace(R.id.main_content, fragment)
            .commit()

    drawerLayout.closeDrawer(GravityCompat.START)
}

Java

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

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

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this,
                drawer,
                toolbar,
                R.string.navigation_drawer_open,
                R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        navigationView.setNavigationItemSelectedListener(this);
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.home) {
            Fragment homeFragment = new HomeFragment();
            show(homeFragment);
        } else if (id == R.id.gallery) {
            Fragment galleryFragment = new GalleryFragment();
            show(galleryFragment);
        } else if (id == R.id.slide_show) {
            Fragment slideShowFragment = new SlideShowFragment();
            show(slideShowFragment);
        } else if (id == R.id.tools) {
            Fragment toolsFragment = new ToolsFragment();
            show(toolsFragment);
        }

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    private void show(Fragment fragment) {

        DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
        FragmentManager fragmentManager = getSupportFragmentManager();

        fragmentManager
                .beginTransaction()
                .replace(R.id.main_content, fragment)
                .commit();

        drawerLayout.closeDrawer(GravityCompat.START);
    }
}

Gezinme bileşenini projenize ekleyip bir gezinme grafiğindeki her bir içerik hedefini ekleyin (ör. Ana Sayfa, Galeri, Slayt Gösterisi ve Araçlar'ı seçin). Emin olun menü öğesi id değerlerinizin ilişkili hedef id değerleriyle eşleştiğinden, aşağıdaki gibidir:

<!-- activity_main_drawer.xml -->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showIn="navigation_view">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/home"
            android:icon="@drawable/ic_menu_camera"
            android:title="@string/menu_home" />
        <item
            android:id="@+id/gallery"
            android:icon="@drawable/ic_menu_gallery"
            android:title="@string/menu_gallery" />
        <item
            android:id="@+id/slide_show"
            android:icon="@drawable/ic_menu_slideshow"
            android:title="@string/menu_slideshow" />
        <item
            android:id="@+id/tools"
            android:icon="@drawable/ic_menu_manage"
            android:title="@string/menu_tools" />
    </group>
</menu>
<!-- activity_main_graph.xml -->
<navigation 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:id="@+id/main_graph"
    app:startDestination="@id/home">

    <fragment
        android:id="@+id/home"
        android:name="com.example.HomeFragment"
        android:label="Home"
        tools:layout="@layout/home" />

    <fragment
        android:id="@+id/gallery"
        android:name="com.example.GalleryFragment"
        android:label="Gallery"
        tools:layout="@layout/gallery" />

    <fragment
        android:id="@+id/slide_show"
        android:name="com.example.SlideShowFragment"
        android:label="Slide Show"
        tools:layout="@layout/slide_show" />

    <fragment
        android:id="@+id/tools"
        android:name="com.example.ToolsFragment"
        android:label="Tools"
        tools:layout="@layout/tools" />

</navigation>

Menünüz ve grafiğinizdeki id değerlerini eşleştirirseniz Bu etkinliğin, aşağıdakilere göre gezinmeyi otomatik olarak işlemesi için NavController menü öğesine dokunun. Ayrıca NavController, DrawerLayout ve Yukarı ve Geri düğmesinin davranışının uygun şekilde işlenmesi.

MainActivity cihazınız daha sonra NavController cihazını Toolbar ve NavigationView.

Örnek için aşağıdaki snippet'e bakın:

Kotlin

class MainActivity : AppCompatActivity()  {

    val drawerLayout by lazy { findViewById<DrawerLayout>(R.id.drawer_layout) }
    val navController by lazy {
      (supportFragmentManager.findFragmentById(R.id.main_content) as NavHostFragment).navController
    }
    val navigationView by lazy { findViewById<NavigationView>(R.id.nav_view) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val toolbar = findViewById<Toolbar>(R.id.toolbar)
        setSupportActionBar(toolbar)

        // Show and Manage the Drawer and Back Icon
        setupActionBarWithNavController(navController, drawerLayout)

        // Handle Navigation item clicks
        // This works with no further action on your part if the menu and destination id’s match.
        navigationView.setupWithNavController(navController)

    }

    override fun onSupportNavigateUp(): Boolean {
        // Allows NavigationUI to support proper up navigation or the drawer layout
        // drawer menu, depending on the situation
        return navController.navigateUp(drawerLayout)
    }
}

Java

public class MainActivity extends AppCompatActivity {

    private DrawerLayout drawerLayout;
    private NavController navController;
    private NavigationView navigationView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        drawerLayout = findViewById(R.id.drawer_layout);
        NavHostFragment navHostFragment = (NavHostFragment)
            getSupportFragmentManager().findFragmentById(R.id.main_content);
        navController = navHostFragment.getNavController();
        navigationView = findViewById(R.id.nav_view);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // Show and Manage the Drawer and Back Icon
        NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout);

        // Handle Navigation item clicks
        // This works with no further action on your part if the menu and destination id’s match.
        NavigationUI.setupWithNavController(navigationView, navController);

    }

    @Override
    public boolean onSupportNavigateUp() {
        // Allows NavigationUI to support proper up navigation or the drawer layout
        // drawer menu, depending on the situation.
        return NavigationUI.navigateUp(navController, drawerLayout);

    }
}

Aynı tekniği, hem BottomGezinmeView tabanlı gezinmede hem de ve Menü tabanlı gezinme. Görüntüleyin Gezinme Arayüzü ile kullanıcı arayüzü bileşenlerini güncelleme inceleyebilirsiniz.

Aktivite hedefi ekleyin

Uygulamanızdaki her ekran Navigasyon bileşenini kullanmak için kabloyla bağlandıktan ve arasında geçiş yapmak için artık FragmentTransactions ürününü kullanmıyorsunuz parça tabanlı hedefler, bir sonraki adım startActivity çağrısının en iyi yolu.

Öncelikle, uygulamanızda iki ayrı gezinme grafiğinizin olduğu yerleri belirleyin ve bunlar arasında geçiş yapmak için startActivity kullanıyor.

Bu örnekte iki grafik (A ve B) ve bir startActivity() çağrısı geçiş yapabilirsiniz.

Kotlin

fun navigateToProductDetails(productId: String) {
    val intent = Intent(this, ProductDetailsActivity::class.java)
    intent.putExtra(KEY_PRODUCT_ID, productId)
    startActivity(intent)
}

Java

private void navigateToProductDetails(String productId) {
    Intent intent = new Intent(this, ProductDetailsActivity.class);
    intent.putExtra(KEY_PRODUCT_ID, productId);
    startActivity(intent);

Sonra, bunları Grafiği A'da temsil eden bir etkinlik hedefiyle değiştirin. ana makine etkinliğine gidin. B Grafiği'nin başlangıç hedefini, bunları etkinlik hedefinde belirtebilirsiniz belirler.

Aşağıdaki örnekte Grafiği, product_id bağımsız değişkeni, bir işlemle birlikte. B grafiği hiçbir değişiklik içermiyor.

A ve B Grafiklerinin XML gösterimi aşağıdaki gibi görünebilir:

<!-- Graph A -->
<navigation 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:id="@+id/product_list_graph"
    app:startDestination="@id/product_list">

    <fragment
        android:id="@+id/product_list"
        android:name="com.example.android.persistence.ui.ProductListFragment"
        android:label="Product List"
        tools:layout="@layout/product_list_fragment">
        <action
            android:id="@+id/navigate_to_product_detail"
            app:destination="@id/product_details_activity" />
    </fragment>

    <activity
        android:id="@+id/product_details_activity"
        android:name="com.example.android.persistence.ui.ProductDetailsActivity"
        android:label="Product Details"
        tools:layout="@layout/product_details_host">

        <argument
            android:name="product_id"
            app:argType="integer" />

    </activity>

</navigation>
<!-- Graph B -->
<navigation 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"
    app:startDestination="@id/product_details">

    <fragment
        android:id="@+id/product_details"
        android:name="com.example.android.persistence.ui.ProductDetailsFragment"
        android:label="Product Details"
        tools:layout="@layout/product_details_fragment">
        <argument
            android:name="product_id"
            app:argType="integer" />
    </fragment>

</navigation>

Aynı mekanizmaları kullanarak grafik B'nin ana makine etkinliğine gidebilirsiniz parça hedeflere gitmek için kullanın:

Kotlin

fun navigateToProductDetails(productId: String) {
    val directions = ProductListDirections.navigateToProductDetail(productId)
    findNavController().navigate(directions)
}

Java

private void navigateToProductDetails(String productId) {
    ProductListDirections.NavigateToProductDetail directions =
            ProductListDirections.navigateToProductDetail(productId);
    Navigation.findNavController(getView()).navigate(directions);

Etkinlik hedef bağımsız değişkenlerini bir başlangıç hedef parçasına iletme

Önceki örnekte olduğu gibi hedef etkinlik ekstralar alırsa bunları doğrudan başlangıç hedefine bağımsız değişken olarak iletebilir, ancak düzenleyen kullanıcının gezinme grafiğini, düzenleyen kullanıcı adının onCreate() yöntemini kullanın, böylece intent ekstralarını parçasını değiştirin:

Kotlin

class ProductDetailsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.product_details_host)
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.main_content) as NavHostFragment
        val navController = navHostFramgent.navController
        navController
                .setGraph(R.navigation.product_detail_graph, intent.extras)
    }

}

Java

public class ProductDetailsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.product_details_host);
        NavHostFragment navHostFragment = (NavHostFragment)
            getSupportFragmentManager().findFragmentById(R.id.main_content);
        NavController navController = navHostFragment.getNavController();
        navController
                .setGraph(R.navigation.product_detail_graph, getIntent().getExtras());
    }

}

Veriler, parça bağımsız değişkenlerinden Bundle oluşturulan bağımsız değişken sınıfı şu şekildedir:

Kotlin

class ProductDetailsFragment : Fragment() {

    val args by navArgs<ProductDetailsArgs>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val productId = args.productId
        ...
    }
    ...

Java

public class ProductDetailsFragment extends Fragment {

    ProductDetailsArgs args;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        args = ProductDetailsArgs.fromBundle(requireArguments());
    }

    @Override
    public void onViewCreated(@NonNull View view,
            @Nullable Bundle savedInstanceState) {
       int productId = args.getProductId();
       ...
    }
    ...

Etkinlikleri birleştirin

Birden fazla etkinliğin aynı değeri paylaştığı durumlarda, gezinme grafiklerini birleştirebilirsiniz. aynı düzen (örneğin, tek bir parça içeren basit bir FrameLayout). İçinde Bu durumlarda her birindeki tüm öğeleri tek bir gezinme grafiği oluşturma ve tüm etkinlik hedef öğelerini parçalara ayırma hedefler.

Aşağıdaki örnekte, önceki bölümde yer alan Grafik A ve B Grafikleri birleştirilmektedir:

Birleştirmeden önce:

<!-- Graph A -->
<navigation 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:id="@+id/product_list_graph"
    app:startDestination="@id/product_list">

    <fragment
        android:id="@+id/product_list"
        android:name="com.example.android.persistence.ui.ProductListFragment"
        android:label="Product List Fragment"
        tools:layout="@layout/product_list">
        <action
            android:id="@+id/navigate_to_product_detail"
            app:destination="@id/product_details_activity" />
    </fragment>
    <activity
        android:id="@+id/product_details_activity"
        android:name="com.example.android.persistence.ui.ProductDetailsActivity"
        android:label="Product Details Host"
        tools:layout="@layout/product_details_host">
        <argument android:name="product_id"
            app:argType="integer" />
    </activity>

</navigation>
<!-- Graph B -->
<navigation 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:id="@+id/product_detail_graph"
    app:startDestination="@id/product_details">

    <fragment
        android:id="@+id/product_details"
        android:name="com.example.android.persistence.ui.ProductDetailsFragment"
        android:label="Product Details"
        tools:layout="@layout/product_details">
        <argument
            android:name="product_id"
            app:argType="integer" />
    </fragment>
</navigation>

Birleştirildikten sonra:

<!-- Combined Graph A and B -->
<navigation 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:id="@+id/product_list_graph"
    app:startDestination="@id/product_list">

    <fragment
        android:id="@+id/product_list"
        android:name="com.example.android.persistence.ui.ProductListFragment"
        android:label="Product List Fragment"
        tools:layout="@layout/product_list">
        <action
            android:id="@+id/navigate_to_product_detail"
            app:destination="@id/product_details" />
    </fragment>

    <fragment
        android:id="@+id/product_details"
        android:name="com.example.android.persistence.ui.ProductDetailsFragment"
        android:label="Product Details"
        tools:layout="@layout/product_details">
        <argument
            android:name="product_id"
            app:argType="integer" />
    </fragment>

</navigation>

Birleştirme işlemi sırasında işlem adlarını aynı tutarak işlem kolay bir şekilde yapılabilir. mevcut kod tabanınızda değişiklik yapmanıza gerek yoktur. Örneğin, navigateToProductDetail burada aynı kaldı. Tek fark bu işlem artık aynı Bir etkinlik hedefi yerine NavHost:

Kotlin

fun navigateToProductDetails(productId: String) {
    val directions = ProductListDirections.navigateToProductDetail(productId)
    findNavController().navigate(directions)
}

Java

private void navigateToProductDetails(String productId) {
    ProductListDirections.NavigateToProductDetail directions =
            ProductListDirections.navigateToProductDetail(productId);
    Navigation.findNavController(getView()).navigate(directions);

Ek Kaynaklar

Gezinmeyle ilgili daha fazla bilgi için aşağıdaki konulara bakın: