126

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

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

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

从查看以前的博客来看,似乎我必须使用 ContextThemeWrapper。任何人都可以向我推荐一个编码示例吗?我什么也找不到。

4

12 回答 12

208

在 manifest 中设置 Theme 通常用于 Activity。

如果要为 Fragment 设置 Theme,请在 Fragment 的 onGetLayoutInflater() 中添加以下代码:

override fun onGetLayoutInflater(savedInstanceState: Bundle?): LayoutInflater {
    val inflater = super.onGetLayoutInflater(savedInstanceState)
    val contextThemeWrapper: Context = ContextThemeWrapper(requireContext(), R.style.yourCustomTheme)
    return inflater.cloneInContext(contextThemeWrapper)
}
于 2013-03-19T10:04:05.113 回答
25

Fragment 的主题来自其 Activity。每个片段都被分配了它所在的 Activity 的主题。

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

在 Fragment.onCreateView 你得到 LayoutInflater 参数,它膨胀视图,它包含用于主题的 Context,实际上这是 Activity。因此,您的膨胀视图使用 Activity 的主题。

要覆盖主题,您可以调用LayoutInflater.cloneInContext,它在 Docs 中提到它可以用于更改主题。你可以在这里使用 ContextThemeWrapper。然后使用克隆的 inflater 创建片段的视图。

于 2013-03-28T08:35:34.880 回答
18

为了应用我刚刚使用的单一样式

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

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

于 2016-01-08T21:30:14.913 回答
12

我还试图让我的片段对话框以与其活动不同的主题显示,并遵循这个解决方案。就像评论中提到的一些人一样,我没有让它工作,并且对话框一直以清单中指定的主题显示。问题原来是我正在使用AlertDialog.BuilderonCreateDialog方法构建对话框,因此没有使用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.Builderthen 检查传递给构建器的上下文。希望这可以帮助!:)

于 2014-07-18T23:24:30.657 回答
9

确保您已android:minSdkVersion="11"在清单中设置。这可能是大卫的例子对你不起作用的原因。

另外,设置标签的属性android:theme="@android:style/Theme.Holo.Light"<application>不是标签<activity>

另一个可能的问题可能是您在使用ContextThemeWrapper(). 如果您使用类似的东西,getActivity().getApplicationContext()只需将其替换为getActivity()

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

请注意,当您想为 Fragment 应用不同的主题时,您使用 ContextThemeWrapper。如果您从 MainActivity 中提供一段代码,它可能会有所帮助,您可以在其中添加片段。


一些有用的链接:

片段中的自定义 ListView 不遵守父主题

于 2013-03-24T22:57:57.903 回答
8

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

2.在它们正确显示的第二个片段上,我做了以下操作,我通过清理内存强制关闭应用程序,重新打开应用程序,当使用片段重新创建活动时,片段将它们更改为错误的Activity 和 Fragment 的 onCrateView 中设置的不一样。

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

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

注意 - 我正在使用 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);
} 
于 2016-03-23T13:02:45.850 回答
8

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

    inflater.context.setTheme(R.style.yourCustomTheme)
于 2019-02-28T07:09:00.947 回答
7

我解决了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>
于 2017-08-29T07:23:59.143 回答
2

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

于 2015-06-19T09:46:37.173 回答
2

如果您只想为特定片段应用样式,那么只需在调用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"
于 2018-08-06T09:09:24.927 回答
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);
}

我希望这可以帮助一些人,干杯!

于 2019-06-14T10:32:37.487 回答
-1

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

最终窗口窗口 = activity.getWindow(); window.setStatusBarColor(myStatusBarColor)

并在 ondettach 中将其设置回默认值

于 2016-01-13T23:26:00.613 回答