web-dev-qa-db-ja.com

ナビゲーションアーキテクチャコンポーネントを使用してアプリバーにタイトルを設定する方法

ナビゲーションアーキテクチャコンポーネントを試してみましたが、タイトルの設定が困難になりました。プログラムでタイトルを設定するにはどうすればよいですか?

私の質問を明確にするために、ナビゲーションホストコントローラーをホストしているMainActivityを使用してシンプルなアプリをセットアップした例を見てみましょう。MainFragmentにはボタンがあり、ボタンをクリックするとボタンが表示されますDetailFragmentに。

スタックオーバーフローに関する 複数のアプリバー の別の質問からの同じコード。

MainActivity

_public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // Setting up a back button
        NavController navController = Navigation.findNavController(this, R.id.nav_Host);
        NavigationUI.setupActionBarWithNavController(this, navController);
    }

    @Override
    public boolean onSupportNavigateUp() {
        return Navigation.findNavController(this, R.id.nav_Host).navigateUp();
    }
}
_

MainFragment

_public class MainFragment extends Fragment {

    public MainFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_main, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button buttonOne = view.findViewById(R.id.button_one);
        buttonOne.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.detailFragment));
    }

}
_

DetailFragment

_public class DetailFragment extends Fragment {

    public DetailFragment() {
        // Required empty public constructor
    }

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_detail, container, false);
    }
}
_

activity_main.xml

_<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:animateLayoutChanges="true"
    tools:context=".MainActivity">

    <com.google.Android.material.appbar.AppBarLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:animateLayoutChanges="true"
        Android:theme="@style/AppTheme.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            Android:id="@+id/toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="?attr/actionBarSize"
            Android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </com.google.Android.material.appbar.AppBarLayout>

    <fragment
        Android:id="@+id/nav_Host"
        Android:name="androidx.navigation.fragment.NavHostFragment"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_gravity="top"
        Android:layout_marginTop="?android:attr/actionBarSize"
        app:defaultNavHost="true"
        app:layout_anchor="@id/bottom_appbar"
        app:layout_anchorGravity="top"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:navGraph="@navigation/mobile_navigation" />

    <com.google.Android.material.bottomappbar.BottomAppBar
        Android:id="@+id/bottom_appbar"
        Android:layout_width="match_parent"
        Android:layout_height="?android:attr/actionBarSize"
        Android:layout_gravity="bottom" />

    <com.google.Android.material.floatingactionbutton.FloatingActionButton
        Android:id="@+id/fab"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        app:layout_anchor="@id/bottom_appbar" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
_

navigation.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/mobile_navigation"
    app:startDestination="@id/mainFragment">
    <fragment
        Android:id="@+id/mainFragment"
        Android:name="com.example.MainFragment"
        Android:label="fragment_main"
        tools:layout="@layout/fragment_main" >
        <action
            Android:id="@+id/toAccountFragment"
            app:destination="@id/detailFragment" />
    </fragment>
    <fragment
        Android:id="@+id/detailFragment"
        Android:name="com.example.DetailFragment"
        Android:label="fragment_account"
        tools:layout="@layout/fragment_detail" />
</navigation>
_

したがって、私のアプリを起動すると、タイトルは「MainActivity」になります。いつものように、MainFragmentに移動するためのボタンを含むDetailFragmentが表示されます。 DialogFragmentで、タイトルを次のように設定しました。

_getActivity().getSupportActionBar().setTitle("Detail");
_

最初の問題:MainFragmentのボタンをクリックしてDetailFragmentに移動すると、そこに移動してタイトルが変更されます詳細へ"。しかし、[戻る]ボタンをクリックすると、タイトルが "fragment_main"に変わります。そこで、次のコード行をMainFragmentに追加しました。

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

    //Showing the title 
    Navigation.findNavController(view)
      .getCurrentDestination().setLabel("Hello");
}
_

DetailFragmentからMainFragmentに戻ると、タイトルが「Hello」に変わります。しかし、ここで2番目の問題が発生します。アプリを閉じて再起動すると、タイトルが「MainActivity」に戻りますが、「Hello」と表示されているはずです代わりに、知っていますか?

では、MainFrgmentsetTitle("Hello")を追加しても機能しません。たとえば、アクティビティが開始され、タイトルが「Hello」の場合、DetailsFragmentに移動して戻るボタンをもう一度押すと、タイトルが「fragment_main」に戻ります。

唯一の解決策は、MainFragmentsetTitle("Hello")Navigation.findNavController(view).getCurrentDestination().setLabel("Hello")の両方を含めることです。

では、ナビゲーションコンポーネントを使用してフラグメントのタイトルを表示する適切な方法は何ですか?

19
Rajarshi

それは実際には次の理由による:

_Android:label="fragment_main"
_

Xmlで設定したもの。

では、ナビゲーションコンポーネントを使用してFragmentsのタイトルを表示する適切な方法は何ですか?

setTitle()はこの時点で機能します。ただし、これらのFragmentsにラベルを設定したため、Activityを再作成するときにラベルが再度表示される場合があります。解決策はおそらく_Android:label_を削除してからコードであなたのことをするでしょう:

_getActivity().getSupportActionBar().setTitle("yourtitle");
_

または:

_((AppCompatActivity) getActivity()).getSupportActionBar().setSubtitle();
_

onCreateView()内。


回避策が見つかりました:

_interface TempToolbarTitleListener {
    fun updateTitle(title: String)
}

class MainActivity : AppCompatActivity(), TempToolbarTitleListener {

    ...

    override fun updateTitle(title: String) {
        binding.toolbar.title = title
    }
}
_

次に:

_(activity as TempToolbarTitleListener).updateTitle("custom title")
_

これもチェックしてください: AndroidXナビゲーションを使用したフラグメントの動的ActionBarタイトル

2
ʍѳђઽ૯ท

質問が出されてからAPIが変更された可能性がありますが、ナビゲーショングラフラベルでアプリリソースの文字列への参照を示すことができます。

enter image description here

これは、フラグメントの静的なタイトルが必要な場合に非常に役立ちます。

1
malrok44

アプリバーを指定しない場合は、このコードをフラグメントで使用できます(デフォルトのアプリバー)。

(activity as MainActivity).supportActionBar?.title = "Your Custom Title"

ナビゲーショングラフのAndroid:label属性を忘れずに削除してください

ハッピーコード^-^

1
Alif Al-Gibran

各画面にAppBarを含めることをお勧めします。コードの重複を回避するには、タイトルをパラメーターとして、AppBarを構築するヘルパーを作成します。次に、各画面クラスでヘルパーを呼び出します。

1
polina-c

別のアプローチはこれである可能性があります:

fun Fragment.setToolbarTitle(title: String) {
    (activity as NavigationDrawerActivity).supportActionBar?.title = title
}
0
drindt

ナビゲーショングラフのxmlファイルを使用して、フラグメントのラベルを引数に設定できます。次に、親フラグメントで、SafeArgsを使用して引数を渡し、デフォルト値を指定して、タイトルがnullまたは空にならないようにします。

<!--set the fragment's title to characters name passed as an argument-->
<fragment
    Android:id="@+id/characterDetailFragment2"
    Android:name="ui.character.CharacterDetailFragment"
    Android:label="{character_name}"
    tools:layout="@layout/fragment_character_detail">
    <argument
        Android:name="character_name"
        Android:defaultValue="Name"
        app:argType="string" />
</fragment>
0