У меня есть следующие две темы:
<!-- Base application theme. -->
<style name = "Theme.MyDemoApp" parent = "Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name = "colorPrimary">@color/purple_500</item>
<item name = "colorPrimaryVariant">@color/purple_700</item>
<item name = "colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name = "colorSecondary">@color/teal_200</item>
<item name = "colorSecondaryVariant">@color/teal_700</item>
<item name = "colorOnSecondary">@color/purple_500</item>
</style>
<!-- Base application theme with a prominent app bar incl. image -->
<style name = "Theme.MyDemoApp.Prominent.Image" parent = "Theme.MyDemoApp">
<!-- Transparent status bar, so that the image extents to the status bar-->
<item name = "android:statusBarColor">@android:color/transparent</item>
<item name = "android:windowTranslucentNavigation">true</item>
</style>
Тема Theme.MyDemoApp
используется в моем приложении или на самом деле во всем моем приложении.
Одно действие открывает специальный фрагмент. Фрагмент использует заметную панель приложения с изображением, где изображение также отображается в строке состояния.
Поэтому я создал собственную тему под названием Theme.MyDemoApp.Prominent.Image
, которая позволяет отображать изображение в строке состояния.
Поскольку фрагмент будет вызываться из разных действий И фрагментов, я хочу установить Theme.MyDemoApp.Prominent.Image
на фрагмент.
Я просмотрел много решений, чтобы установить тему на фрагмент, например:
1)
@Override
public void onAttach(@NonNull Context context) {
context.setTheme(R.style.Theme_MyDemoApp_Prominent_Image);
super.onAttach(context);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//create ContextThemeWrapper from the original Activity Context with the custom theme
final Context contextThemeWrapper = new ContextThemeWrapper(getActivity(), R.style.Theme_MyDemoApp_Prominent_Image);
//clone the inflater using the ContextThemeWrapper
LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);
return inflater.inflate(R.layout.fragment_demo_appbar_image, container, false);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getContext().getTheme().applyStyle(R.style.Theme_MyDemoApp_Prominent_Image, true);
return inflater.inflate(R.layout.fragment_demo_appbar_image, container, false);
}
Установка темы прямо в xml файле фрагмента
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android = "http://schemas.android.com/apk/res/android"
xmlns:app = "http://schemas.android.com/apk/res-auto"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
style = "@style/Theme.MyDemoApp.Prominent.Image"
android:theme = "@style/Theme.MyDemoApp.Prominent.Image"
>
<!-- bla bla bla bla -->
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Однако НИ ОДНО из вышеперечисленных опробованных решений не сработало для меня. Тема не изменится, так как строка состояния не прозрачна. Если я помещу параметры темы фрагмента в тему активности, это сработает как шарм, но это не то, что я планирую делать.....
В чем может быть проблема и есть идеи, как правильно установить тему в моем фрагменте?
опубликовано как ответ с некоторыми пояснениями
попробуй return localInflater.inflate(...
через 2. попробуй
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//create ContextThemeWrapper from the original Activity Context with the custom theme
final Context contextThemeWrapper =
new ContextThemeWrapper(getActivity(), R.style.Theme_MyDemoApp_Prominent_Image);
//clone the inflater using the ContextThemeWrapper
LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);
return localInflater.inflate(R.layout.fragment_demo_appbar_image, container, false);
}
редактировать: теперь я вижу проблему более четко...
вы пытаетесь установить statusBarColor
и windowTranslucentNavigation
- это параметры для Activity
, а не Fragment
. поэтому ваша тема должна быть применена к Activity
, установка темы на Fragment
или View
слой/уровень (что-то вроде дочернего элемента Fragment
, который является дочерним элементом Activity
) с помощью Context
обертывания или установки программно/с помощью XML просто «слишком низкая», хостинг Activity
просто не будет применять эти атрибуты
поэтому вам нужно настроить Theme
для всего Activity
- полупрозрачная строка состояния, когда отображается ваш Fragment
, и возвращающийся к цвету по умолчанию (черный?) при его отсоединении. но вы можете установить Theme
для всего Activity
программно, только вызвав setTheme( перед вызовом super.onCreate(, так что только в самом начале, когда вы, вероятно, не будете уверены, что полупрозрачный-статус-Fragment
будет показан... (например, это может отображаться при щелчке во время выполнения)
поэтому вам нужно перезапустить Activity
, затем, с некоторой дополнительной настройкой флага setTheme(
, также ваш Fragment
должен появиться, затем при запуске ... вы можете использовать Bundle
, переданный для Intent
, начиная это Activity
снова сразу после finish()
вызова
Я действительно считаю, что это слишком много усилий, и ваш Fragment
должен быть на самом деле другим Activity
с этой темой прозрачного статуса, настроенной с помощью XML, опционально это может быть какое-то расширение какой-то прозрачной темы активности вместо вашей "Theme.MyDemoApp"
Спасибо за подробный ответ. :) Теперь понятно, почему мой подход не сработал. Вы упомянули, что я должен заменить фрагмент действием (которое отлично работает, кстати, благодаря вам), но не будут ли фрагменты лучше, даже в этом случае, если подход фрагмента сработает? Потому что я вызываю фрагмент или теперь активность из разных фрагментов, и поскольку фрагменты предназначены для повторного использования кода, я решил пойти на это. Потому что теперь у меня есть много фрагментов и одно «случайное» действие в этом случае, что выглядит странно.
ну, Fragment
s - это "кусочки Activity
", и ваша цель - изменить параметр Activity
, а не какую-то его внутреннюю часть, поэтому для этого вам нужно иметь специально стилизованный Activity
. Обратите внимание, что у вас по-прежнему может быть вся ваша логика как Fragment
, и вы по-прежнему можете открыть ее в любом Activity
, но строка состояния не изменится, как «решает Activity
». Но в некоторых случаях вы можете вместо этого запустить какую-то "dummy-transparent-Activity", передав ей свой Fragment
(или некоторые данные, указывающие на Fragment
init внутри), тогда статусная база будет прозрачной
И вот вам идея фрагментации и повторного использования - ваш Fragment
может быть прикреплен несколькими способами/цвета статусбара, но вам, вероятно, нужен только прозрачный (такой новый Activity
), а также фиктивный-прозрачный-Activity
может взять и запустить какой-то другой Fragment
показывает его с полупрозрачной/без строки состояния
@snachmsm спасибо за вклад, к сожалению, это не удалось. Кажется, проблема в
android:statusBarColor
иandroid:windowTranslucentNavigation
, потому что кажется, что атрибуты цвета будут изменены (если я переопределю их в своей теме фрагмента), но не цвет строки состояния