簡體   English   中英

為什么在 Android 中使用后退按鈕(物理后退按鈕)后無法更改工具欄標題?

[英]why I can't change toolbar title after using back button (physical back button) in Android?

這是要下載的項目: https ://www.dropbox.com/s/lq3p2pnwjacik7s/testApp.zip?dl=0

我正在使用 Android 導航組件,這是應用程序的屏幕截圖:

在此處輸入圖像描述

如您所見,在 MainActivity 布局中,有一個 nav_host_fragment、一個工具欄和一個底部導航視圖。

Blue Tab 的順序在圖中將是這樣的

在此處輸入圖像描述

工具欄中的標題“CUSTOM TITLE HERE”硬編碼在 destination_blue1 片段中

但是當我從 blue1 移動到 blue2,然后使用后退按鈕(物理硬件后退按鈕)返回 blue1 時,標題會更改為“fragment_blue1”,而不是“CUSTOM TITLE HERE”(硬編碼)。

“fragment_blue1”實際上是該片段的目標圖 ID 字符串。

我不明白為什么即使我將標題硬編碼為“CUSTOM TITLE HERE”,如果我使用(物理硬件后退按鈕)它也不起作用。

但是,如果我使用向上按鈕(工具欄/操作欄中的后退按鈕),則標題將根據我硬編碼的標題為“CUSTOM TITLE HERE”。

這是當我的硬編碼標題不起作用時的標題,當我使用后退按鈕(物理后退按鈕)從藍色 2 回到藍色 1 時。

在此處輸入圖像描述

這是我真實案例的簡化,我需要從片段 Blue1 動態更改標題。 我不明白為什么我在使用后退按鈕后無法更改標題。 但是當使用向上按鈕時,標題將按照我使用的代碼顯示,與目的地 ID 圖不同。

如何解決這個問題? 什么地方出了錯?

我正在使用樣式<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">這是我的 MainActivity 的代碼

class MainActivity : AppCompatActivity() {

    lateinit var navController : NavController
    lateinit var toolbar: Toolbar
    lateinit var bottomNavigationView : BottomNavigationView

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

        navController = Navigation.findNavController(this,R.id.nav_host_fragment)
        setUpViewDeclaration()
        setupBottomNavMenu()
        setupActionBar()


    }

    private fun setUpViewDeclaration() {
        toolbar = findViewById(R.id.toolbar)
        bottomNavigationView = findViewById(R.id.bottom_nav)

    }

    private fun setupBottomNavMenu() {
        bottom_nav.setupWithNavController(navController)
    }

    private fun setupActionBar() {

        // set up top hierarchy destination
        val appBarConfiguration = AppBarConfiguration(setOf(
            R.id.destination_blue1,
            R.id.destination_red1)
        )

        setSupportActionBar(toolbar)
        toolbar.setupWithNavController(navController,appBarConfiguration)

    }
}

這是 blue1 片段的代碼

class Blue1Fragment : Fragment() {

    lateinit var moveButton: Button
    lateinit var fragmentView: View

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        fragmentView = inflater.inflate(R.layout.fragment_blue1, container, false)
        moveButton = fragmentView.findViewById(R.id.move_button_1)

        // The title hard coded in here
        // this one line below seems doesn't work if using back physical button
        (activity as AppCompatActivity).supportActionBar?.title = "CUSTOM TITLE HERE" 



        moveButton.setOnClickListener {

            val nextDestination = Blue1FragmentDirections.actionToBlue2()
            Navigation.findNavController(fragmentView).navigate(nextDestination)

        }

        return fragmentView
    }


}

這是 blue2 片段的代碼:

class Blue2Fragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_blue2, container, false)
    }


}

嘗試在“onViewCreated”中設置標題

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)


}

發生這種情況是因為您添加了片段,同時添加了 onResume 而不是調用。 如果您的導航很簡單(片段之間的路由始終相同),您可以通過在 SecondFragment 中調用 onStop() 並在此方法內將工具欄標題更改為第一個片段標題來實現它。 如果您的片段動態變化(從 fr1 調用 fr2/fr3),您可以在 bundle 上傳遞標題並將其替換為您的自定義標題

//inside Blue2Fragment

override fun onStop() {
    (activity as AppCompatActivity).supportActionBar?.title = "CUSTOM TITLE HERE"
    super.onStop()
}

我不熟悉kotlin ,但是這里有一個java解決方法,通過動態更改toolbartitlesubTitle標題來解決這個問題。

首先,我們需要創建一個對象,用作帶有標題和副標題參數的MultableLiveData類型。

public class Toolbar {
    private String title, subTitle;

    public Toolbar(String title, @Nullable String subTitle) {
        this.title = title;
        this.subTitle = subTitle;
    }

    public String getTitle() {
        return title;
    }

    public String getSubTitle() {
        return subTitle;
    }
}

MainActivity中,我們將toolbar定義為MultableLiveData並在onCreate()中觀察它並在onDestroy()中移除觀察者。

public MutableLiveData<Toolbar> toolbar = new MutableLiveData<>();

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

    bottomNavigationView = (BottomNavigationView) findViewById(R.id.main_bottomnav);
    navigationView = (NavigationView) findViewById(R.id.main_sidebar);
    drawerLayout = (DrawerLayout) findViewById(R.id.main_drawer);

    setupNavigation();

    toolbar.observe(this, new Observer<Toolbar>() {
        @Override
        public void onChanged(Toolbar toolbarModel) {
            getSupportActionBar().setTitle(toolbarModel.getTitle());
            getSupportActionBar().setSubtitle(toolbarModel.getSubTitle());
        }
    });

}

@Override
protected void onDestroy() {
    toolbar.removeObservers(this);
    super.onDestroy();
}

在您的任何片段中,我們將toolbar的標題和副標題設置如下:

@Override
public void onStart() {
    super.onStart();
    ((MainActivity) requireActivity()).toolbar.postValue(new Toolbar("MyFragment Title", "MyFragment SubTitle"));
}

要么

@Override
public void onStart() {
    super.onStart();
    ((MainActivity) requireActivity()).toolbar.postValue(new Toolbar("MyFragment Title", null));
}

還要從nav_graph.xml中刪除android:label以避免標題/標簽沖突。

<fragment
    android:id="@+id/shopFragment"
    android:name="com.myapp.ShopFragment"
    android:label="TO BE REMOVED" // REMOVE THIS LINE OF CODE
    tools:layout="@layout/fragment_shop" />

我希望它有所幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM