Как установить заголовок на панели приложения с помощью компонента Navigation Architecture - PullRequest
0 голосов
/ 26 сентября 2018

Я опробовал компонент архитектуры навигации и теперь испытываю трудности с настройкой заголовка.Как установить заголовок программно, а также как он работает?

Чтобы прояснить вопрос, давайте рассмотрим пример, где я настроил простое приложение с 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, который содержит кнопку для перехода к DetailFragmentDialogFragment я установил заголовок следующим образом:

getActivity().getSupportActionBar().setTitle("Detail");

Первая проблема: Итак, нажав кнопку на MainFragment, чтобы перейти к DetailFragment, он действительно идет тудаи название меняется на «Деталь».Но при нажатии кнопки «Назад» заголовок изменится на «gment_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».Но тут возникает вторая проблема , когда я закрываю приложение и запускаю снова, название меняется на «MainActivity», хотя вместо этого должно отображаться «Hello», знаете?

Хорошо,тогда добавление setTitle("Hello") в MainFrgment тоже не работает.Например, начинается действие, и заголовок «Привет», перейдите к DetailsFragment и снова нажмите кнопку «Назад», заголовок возвращается к «фрагмент_основе».

Единственное решение состоит в том, чтобы оба setTitle("Hello") вместе с Navigation.findNavController(view).getCurrentDestination().setLabel("Hello") в MainFragment.

Итак, как правильно отображать заголовок для фрагментов с помощью Навигационного компонента?

Ответы [ 3 ]

0 голосов
/ 30 июня 2019

Я бы предложил включить AppBar на каждом экране.Чтобы избежать дублирования кода, создайте помощник, который создает AppBar, принимая заголовок в качестве параметра.Затем вызовите помощника в каждом классе экрана.

0 голосов
/ 01 июля 2019

Поскольку другие все еще участвуют в ответе на этот вопрос, позвольте мне ответить на мой собственный вопрос , поскольку API изменились с тех пор.

Сначала удалите android:label из фрагментов, которыеВы хотите изменить заголовок из navigation.xml (он же Навигационный график).

Теперь вы можете изменить заголовок с помощью Fragment, вызвав

(requireActivity() as MainActivity).title = "My title"

Нопредпочтительный способ использования API NavController.addOnDestinationChangedListener изнутри MainActivity.Пример:

NavController.OnDestinationChangedListener { controller, destination, arguments ->
    title = when (destination) {
        R.id.someFragment -> "My title"
        else -> "Default title"
    }

//    if (destination == R.id.someFragment) {
//        title = "My title"
//    } else {
//        title = "Default Title"        
//    }
}
0 голосов
/ 26 сентября 2018

Это на самом деле из-за:

android:label="fragment_main"

, который вы установили в xml.

Так, как правильно отображать заголовок для Fragment s, используяКомпонент навигации?

setTitle() работает на этом этапе.Но, поскольку вы устанавливаете метку для этих Fragment s, она может снова отобразить метку при воссоздании Activity.Решением, вероятно, будет удаление android:label и выполнение ваших действий с кодом:

((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("your title");

Или:

((AppCompatActivity) getActivity()).getSupportActionBar().setSubtitle("your subtitle");

In 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")

Проверьте это тоже: Динамический заголовок ActionBar из фрагмента с помощью навигации AndroidX

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...