为片段设置主题

时间:2012-02-27 17:13:46

标签: android android-fragments android-theme

我正在尝试为片段设置主题。

在清单中设置主题不起作用:

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

从以前的博客看,似乎我必须使用ContextThemeWrapper。任何人都可以参考我的编码示例吗?我找不到任何东西。

12 个答案:

答案 0 :(得分:160)

在清单中设置主题通常用于活动。

如果要为Fragment设置Theme,请在片段的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);
}

答案 1 :(得分:10)

Fragment从其Activity中获取主题。每个片段都被分配了它所在的Activity的主题。

主题应用于Fragment.onCreateView方法,您的代码创建视图,实际上是使用主题的对象。

在Fragment.onCreateView中,您获得了LayoutInflater参数,该参数可以扩展视图,并且它保存用于主题的Context,实际上这是Activity。因此,您的虚增视图使用了Activity的主题。

要覆盖主题,您可以调用LayoutInflater.cloneInContext,在文档中提及它可能用于更改主题。您可以在此处使用ContextThemeWrapper。 然后使用克隆的inflater创建片段的视图。

答案 2 :(得分:10)

我还试图让我的片段对话框显示与其活动不同的主题,并遵循this solution。就像评论中提到的一些人一样,我没有让它工作,对话框一直显示清单中指定的主题。结果问题是我在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,那么请检查传递给构建器的上下文。希望这可以帮助! :)

答案 3 :(得分:9)

确保您的清单中设置了android:minSdkVersion="11"。这可能是David's示例不适合您的原因。

另外,为android:theme="@android:style/Theme.Holo.Light"标记设置<application>属性,为<activity>标记设置 NOT

另一个可能的问题可能是您在使用ContextThemeWrapper()时获取上下文的方式。如果您使用getActivity().getApplicationContext()之类的内容,请将其替换为getActivity()

通常,Theme.Holo应该应用于链接到MainActivity的Fragment。

请注意,如果要为片段应用不同的主题,请使用ContextThemeWrapper。如果您在MainActivity中提供了添加片段的代码,那么它可能会有所帮助。


一些有用的链接:

Custom ListView in Fragment not adhering to parent theme

答案 4 :(得分:9)

对于应用单一样式我只使用

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

在片段之前的onCreateView()膨胀片段的根视图,它对我有效。

答案 5 :(得分:5)

我尝试了大卫建议它确实有效的解决方案,但并非在所有场景中都有效: 1.对于添加到堆栈的第一个片段具有活动的主题而不是onCrateView中定义的那个,但是在我添加到堆栈的第二个片段上,正确的它们被应用在片段上。

2.在正确显示它们的第二个片段上,我做了以下操作,我通过清理内存强制关闭App,重新打开App,当用片段重新创建Activity时片段改变了它们错误的它们活动,而不是在片段的onCrateView中设置的。

为了解决这个问题,我做了一个小改动,用inflater.inflate替换了容器参数。

我不知道inflater在某些情况下使用容器视图中的上下文。

注意 - 即时通讯使用android.support.v4.app.Fragment&amp; 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);
} 

答案 6 :(得分:2)

创建一个java类,然后使用你想要在onCreate方法中更改主题的布局。然后在清单中提及它正常

答案 7 :(得分:1)

我在片段的布局文件中使用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>

            <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"></TextView>
        </LinearLayout>

答案 8 :(得分:1)

如果您只想为特定片段应用样式,则只需在调用片段的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"

答案 9 :(得分:0)

在调用充气机之前,我通过在片段上下文中设置主题来使其工作。

注意:这是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);
}

我希望这可以帮助一些人,加油!

答案 10 :(得分:-1)

你可以尝试这个棒棒糖 在onAttach

final Window window = activity.getWindow(); window.setStatusBarColor(myStatusBarColor)

并在ondettach

中将其设置回默认值

答案 11 :(得分:-1)

我知道它有点晚了,但它可能对其他人有所帮助,因为这对我有所帮助。您还可以尝试在片段的onCreatView函数内添加下面的代码行

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