Как изменить тему панели инструментов и BottomNavigationBar в действии

Итак, я попытался создать нижнюю панель навигации и навигационный ящик в 1 действии (я использовал новый шаблон ящика действий и объединил его с тегом нижнего навигационного представления, который я получил из нижнего навигационного действия). Я хочу изменить тему как для панели инструментов, так и для нижнего навигационного ящика во время выполнения (поэтому я подумал об использовании setTheme для активности), но setTheme не работает (цвет не меняется). Я пытался установить тему для каждого атрибута на XML (в теге контейнера AppBarLayout и BottomNavigationView), и он работает. Но когда я пытался программно, я устанавливал активность в их контексте, но это ничего не делало.

содержат_основной_контейнер.xml

<androidx.constraintlayout.widget.ConstraintLayout
    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/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?attr/actionBarSize"
    android:theme="@style/AppNightTheme"
    tools:context=".MainContainerActivity">

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="0dp"
        android:layout_marginStart="0dp"
        app:itemBackground="?colorPrimary"
        app:itemIconTint="@drawable/nav_item_color"
        app:itemTextColor="@drawable/nav_item_color"
        android:background="?colorPrimary"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>

app_bar_main_container.xml

<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"
    tools:context=".MainContainerActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar_toolbar"
        android:theme="@style/AppNightTheme"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        android:layout_height="wrap_content"
        android:layout_width="match_parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize" />

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

    <include layout="@layout/content_main_container"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

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

что я пробовал на MainContainerActivity.kt

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        sharedPreferences  = getSharedPreferences("preferences", 0)
        if(sharedPreferences.getBoolean("DayTheme",true)){
            setTheme(R.style.AppDayTheme)
        }
        else{
            setTheme(R.style.AppNightTheme)
        }
        setContentView(R.layout.activity_main_container)
        toolbar = findViewById(R.id.toolbar)
        toolbar.title = ""
        setSupportActionBar(toolbar)



        homeFragment = HomeFragment()
        discoverFragment = DiscoverFragment()
        notificationFragment = NotificationFragment()
        settingFragment = SettingFragment()

        if(savedInstanceState != null){
            when(savedInstanceState.getInt("last_fragment")){
                R.id.navigation_discover -> {
                    val fragmentTransaction = fragmentManager.beginTransaction()
                    fragmentTransaction.replace(R.id.container, discoverFragment)
                    fragmentTransaction.addToBackStack(null)
                    fragmentTransaction.commit()
                }
                R.id.navigation_home -> {
                    val fragmentTransaction = fragmentManager.beginTransaction()
                    fragmentTransaction.replace(R.id.container, homeFragment)
                    fragmentTransaction.addToBackStack(null)
                    fragmentTransaction.commit()
                }
                R.id.navigation_favorites -> {
                }
                R.id.navigation_notifications -> {
                    val fragmentTransaction = fragmentManager.beginTransaction()

                    fragmentTransaction.replace(R.id.container, notificationFragment)
                    fragmentTransaction.addToBackStack(null)
                    fragmentTransaction.commit()
                }

                R.id.navigation_settings -> {
                    val fragmentTransaction = fragmentManager.beginTransaction()
                    fragmentTransaction.replace(R.id.container, settingFragment)
                    fragmentTransaction.addToBackStack(null)
                    fragmentTransaction.commit()
                }
                else -> false
            }
        }
        else{
            val fragmentTransaction = fragmentManager.beginTransaction()
            val homeFragment = HomeFragment()
            fragmentTransaction.replace(R.id.container,homeFragment)
            fragmentTransaction.addToBackStack(null)
            fragmentTransaction.commit()
        }

        val bottomNav : BottomNavigationView = findViewById(R.id.bottom_nav_view)
        bottomNav.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener)

        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)
    }

person DKVV    schedule 06.09.2019    source источник


Ответы (3)


Прежде всего, привет и добро пожаловать в stackoverflow!

Что касается вопроса, я уверен, что вам нужно перезапустить свою деятельность после смены темы. Для API 11 и выше:

Activity.recreate()

Для API до 11:

Intent intent = getIntent();
finish();
startActivity(intent);

Надеюсь, я был полезен!

Редактировать Вы не можете изменить темы ToolBar и BottomNavigationView во время выполнения. Вы можете изменить только цвет фона и цвет заголовка. Для панели инструментов

toolbar.setBackgroundColor(newColor); 
toolbar.setTitleTextColor(titleColor);

Для BottomNavigationView,

navigation.setBackgroundColor();
navigation.setItemTextColor();
person Rodrigo Fernandes    schedule 06.09.2019
comment
да, бро, я уже сделал это, для фрагмента внутри цвет уже изменен, но для панели инструментов и нижней навигации он не меняется - person DKVV; 06.09.2019
comment
Я просто немного исследовал и лучше проанализировал ваш код. Вы не можете программно изменить панель инструментов и BottomNavigationView. Код, который вы показали, изменяет тему контекста, а не темы контейнера или панели инструментов. Тем не менее, вы выполняете setTheme для одного и того же действия 3 раза подряд. Вы можете изменить цвет фона и цвет заголовка только во время выполнения. - person Rodrigo Fernandes; 06.09.2019

Чтобы программно установить действие, вы должны установить его перед setContentView(). Но если вы хотите изменить его после запуска действия, вам необходимо воссоздать или перезапустить действие.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setTheme(R.style.AppDayTheme); // (for Custom theme)
    setContentView(R.layout.your_activity);
}
person Ankit    schedule 06.09.2019
comment
да, бро, фрагмент внутри изменился в соответствии с темой, но цвет нижней навигации и панели инструментов не меняется - person DKVV; 06.09.2019
comment
colorPrimary в вашем стиле будет установлен как цвет панели инструментов и нижней панели навигации - person Ankit; 06.09.2019

вы можете использовать тег атрибута в attrs.xml для использования в теге цвета. помните, если у вас есть две темы, которые должны быть по умолчанию и вторичными, поэтому вам нужно объявить два цветовых тега, используя один и тот же тег атрибута, как этот

Шаг 1: определение тега атрибута

<attr name="toolbarcolor" format="color"></attr>

используйте тег атрибута, чтобы определить выбор двух цветов

Шаг 2: определите названия цветов

 <color name="toolbarcolordefualt">#F36C63</color>
<color name="toolbarcolorsecondary">#4CAF50</color>

Шаг 3: определение стиля

 <style name="AppTheme.Default" parent="Theme.AppCompat.Light.NoActionBar">
   <item name="toolbarcolor">@color/toolbarcolordefualt</item>
 </style>  

 <style name="AppTheme.secondary" parent="Theme.AppCompat.Light.NoActionBar">
  <item name="toolbarcolor">@color/toolbarcolorsecondary</item>

use that attribute to your toolbar

<androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:background="?attr/toolbarcolor"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"/>

все остальное вам просто нужно поддерживать, какая тема должна отображаться, используя sharedpreference в функции settheme()

А для нижней навигационной панели вы можете использовать ее в соответствии с вашими общими настройками, используя условие if else

getWindow().setNavigationBarColor(getResources().getColor(R.color.anycolor));
person Black mamba    schedule 06.09.2019