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:
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.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.
Etkinlik hedefi ekle -
startActivity()
aramayı şununla değiştir: işlemlerdir.Etkinlikleri birleştirme: Şu durumlarda gezinme grafiklerini birleştirin: Ortak bir düzene sahip birden çok etkinlik vardır.
Ö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:
- Gezinme Arayüzü ile kullanıcı arayüzü bileşenlerini güncelleme - Üst uygulama çubuğu, gezinme çekmecesi ve daha fazlası ile gezinmeyi ve alt gezinme menüsünde
- Testte Gezinme: Uygulamanız için gezinme iş akışlarını nasıl test edeceğinizi öğrenin