Установить тему для фрагмента

Я пытаюсь установить тему для фрагмента.

Настройка темы в манифесте не работает:

android:theme="@android:style/Theme.Holo.Light"

От взгляда на предыдущие блоги кажется, что я должен использовать ContextThemeWrapper. Может ли кто-нибудь ссылаться на закодированный пример? Я ничего не могу найти.

Ответ 1

Настройка темы в манифесте обычно используется для Activity.

Если вы хотите установить Theme for Fragment, добавьте следующий код в onCreateView() фрагмента:

@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.yourCustomTheme);

    // clone the inflater using the ContextThemeWrapper
    LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);

    // inflate the layout using the cloned inflater, not default inflater
    return localInflater.inflate(R.layout.yourLayout, container, false);
}

Ответ 2

Фрагмент берет свою тему из своей деятельности. Каждому фрагменту присваивается тема действия, в котором он существует.

Тема применяется в методе Fragment.onCreateView, где ваш код создает представления, которые фактически являются объектами, в которых используется тема.

В Fragment.onCreateView вы получаете параметр LayoutInflater, который раздувает представления и содержит контекст, используемый для темы, на самом деле это Activity. Так что ваши раздутые взгляды используют тему деятельности.

Чтобы переопределить тему, вы можете вызвать LayoutInflater.cloneInContext, которая упоминает в Документах, что она может использоваться для изменения темы. Вы можете использовать ContextThemeWrapper здесь. Затем используйте клонированный инфлатер для создания фрагментов.

Ответ 3

Я также пытался открыть диалог своего фрагмента с другой темой в своей деятельности и следовать этому решению. Как и некоторые люди, упомянутые в комментариях, я не получал его на работу, и диалог продолжал показывать тему, указанную в манифесте. Проблема заключалась в том, что я строил диалог с помощью AlertDialog.Builder в методе onCreateDialog и поэтому не использовал метод onCreateView, как показано в ответе, с которым я связан. И когда я создавал экземпляр AlertDialog.Builder, я проходил в контексте с помощью getActivity(), когда я должен был использовать экземпляр ConstextThemeWrapper вместо этого.

Вот код моего onCreateDialog:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Create ContextThemeWrapper from the original Activity Context
    ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(getActivity(), android.R.style.Theme_DeviceDefault_Light_Dialog);
    LayoutInflater inflater =   getActivity().getLayoutInflater().cloneInContext(contextThemeWrapper);
    // Now take note of the parameter passed into AlertDialog.Builder constructor
    AlertDialog.Builder builder = new AlertDialog.Builder(contextThemeWrapper);
    View view = inflater.inflate(R.layout.set_server_dialog, null);
    mEditText = (EditText) view.findViewById(R.id.txt_server);
    mEditText.requestFocus();  // Show soft keyboard automatically
    mEditText.setOnEditorActionListener(this);
    builder.setView(view);
    builder.setTitle(R.string.server_dialog);
    builder.setPositiveButton(android.R.string.ok, this);
    Dialog dialog = builder.create();
    dialog.setCanceledOnTouchOutside(false);
    return dialog;
}

Первоначально я создавал AlertDialog.Builder следующим образом:

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

который я изменил на:

AlertDialog.Builder builder = new AlertDialog.Builder(contextThemeWrapper);

После этого изменения диалог фрагмента был показан с правильной темой. Поэтому, если у кого-то есть аналогичная проблема, и он использует использование AlertDialog.Builder, тогда проверьте контекст, передаваемый строителю. Надеюсь это поможет!:)

Ответ 4

Убедитесь, что в манифесте установлен android:minSdkVersion="11". Это может быть причиной того, что пример Дэвида не сработал для вас.

Также установите атрибут android:theme="@android:style/Theme.Holo.Light" для тега <application> и НЕ тег <activity>.

Другая возможная проблема может заключаться в том, как вы получаете свой контекст при использовании ContextThemeWrapper(). Если вы используете что-то вроде getActivity().getApplicationContext(), просто замените его на getActivity().

Обычно Theme.Holo следует применять к фрагментам, связанным с MainActivity.

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


Некоторые полезные ссылки:

Пользовательский ListView в фрагменте, не придерживаясь родительской темы

Ответ 5

Для применения одного стиля я использовал только

getContext().getTheme().applyStyle(styleId, true);

в onCreateView() фрагмента до, раздувающего корневой вид фрагмента, и он работает для меня.

Ответ 6

Я попробовал решение, которое предложил Дэвид, но не во всех сценариях:
1. для первого фрагмента, который добавлен в стек, есть тема активности, а не та, которая определена в onCrateView, но во втором фрагменте, который я добавляю в стек, исправляю их, применяется к фрагменту.

2. На втором фрагменте, что они были отображены правильно, я сделал следующее: я заставил приложение закрыться, очистив память, откройте приложение и когда активность была воссоздана с фрагментом. Фрагмент изменил их неправильные активность, а не то, что было установлено в onCrateView фрагмента.

Чтобы исправить проблему, я сделал небольшое изменение и заменил аргумент контейнера из файла inflater.inflate нулевым.

Я не знаю, как надуватель использует в некоторых сценариях контекст из представления контейнера.

Заметьте, что im использует android.support.v4.app.Fragment и android.support.v7.app.AppCompatActivity.

@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.yourCustomTheme);

// clone the inflater using the ContextThemeWrapper 
LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);

// inflate the layout using the cloned inflater, not default inflater 
return localInflater.inflate(R.layout.yourLayout, null, false);
} 

Ответ 7

Создайте класс java, а затем используйте макет, который вы хотите изменить тему в методе onCreate. Затем укажите его в манифесте как обычный

Ответ 8

Я решил проблему с помощью android:theme = "@style/myTheme" в файле макета фрагмента. Например, это меняет стиль LinearLayout и его содержимое, но не что-либо вне LinearLayout. Таким образом, для того, чтобы украсить весь фрагмент любым стилем, примените тему к внешнему наиболее родительскому макету.

           <LinearLayout 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:theme = "@style/myTheme" >

            <TextView
                android:id="@+id/tc_buttom_text1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Time elapsed"/>

            <TextView
                android:id="@+id/tc_buttom_text2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="00:00:00 00"/>
        </LinearLayout>

Ответ 9

Если вы просто хотите применить стиль для определенного фрагмента, просто добавьте эти строки перед вызовом onCreateView() или onAttach() фрагмента,

getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
getActivity().getWindow().setStatusBarColor(Color.TRANSPARENT);

и если вы хотите установить прозрачную строку состояния, тогда установите false в свойство fitsSystemWindows вашего корневого макета,

android:fitsSystemWindows="false"

Ответ 10

Я заставил его работать, установив тему в контексте фрагмента перед вызовом инфлятора.

ПРИМЕЧАНИЕ. Это пример Xamarin.Android в сочетании с MvvmCross. Я не уверен на 100%, будет ли это работать и для программистов на Java. Но вы можете попробовать :)

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    Context.SetTheme(Theme);

    base.OnCreateView(inflater, container, savedInstanceState);

    var view = this.BindingInflate(FragmentLayoutId, container, false);

    // Doing some other stuff

    return view;
}

Код метода расширения SetTheme

public static void SetTheme(this Context context, AppThemeStyle themeStyle)
{
    var themeStyleResId = themeStyle == AppThemeStyle.Dark ? Resource.Style.AppTheme : Resource.Style.AppTheme_Light;

    context.SetTheme(themeStyleResId);
}

Я надеюсь, что это поможет некоторым людям, ура!

Ответ 11

вы можете попробовать это для леденца in onAttach

final Окно окна = activity.getWindow(); window.setStatusBarColor(myStatusBarColor)

и установите значение по умолчанию в ondettach

Ответ 12

Я знаю, что немного поздно, но это может помочь кому-то еще, потому что это помогло мне. Вы также можете попробовать добавить строку кода ниже внутри функции onCreatView фрагмента

    inflater.context.setTheme(R.style.yourCustomTheme)