设置片段主题


117

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

在清单中设置主题无效:

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

通过查看以前的博客,似乎我不得不使用ContextThemeWrapper。谁能推荐我一个编码示例?我什么都找不到

Answers:


187

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

如果要为Fragment设置主题,请在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);
}

30
这对我不起作用。该片段仍然具有清单文件中指定的相同主题。
Giorgi 2013年

1
在清单中,指定活动的主题,而不是片段。您正在使用fragment或fragmentActivity吗?
David

1
为我工作。活动中具有经典片段。
David

8
@David“清单中的设置主题用于活动”。这并非完全正确。如果您使用FragmentTransaction在运行时添加您的片段,则该主题也将应用于片段。
sebster

4
对于ActionBarSherlock库中的SherlockFragmentActivity,这似乎不起作用。
toobsco42 2013年

18

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

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

在Fragment.onCreateView中,您将获得LayoutInflater参数,该参数会放大视图,并且包含用于主题的Context,实际上这是Activity。因此,您的膨胀视图使用Activity的主题。

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


正如google docs所指出的那样:“ ...返回与给定Context相关联的全新LayoutInflater对象的品牌...”- developer.android.com/reference/android/view/…
克里斯-

Davids代码解决方案非常有用的补充。谢谢!
muetzenflo

13

为了应用单一样式,我只使用了

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

在扩大onCreateView()片段的根视图之前先进入片段,它对我有用。


1
分钟api 23getContext()
警惕2016年

@vigilancer检查此答案以解决您的最小api问题:stackoverflow.com/questions/36736244/…–
rm8x

1
很好的解决方案。我在onAttach(Context)中添加了代码,该代码也将主题应用于所有子片段
crysxd

这可能会带来意想不到的后果,因为它修改了上下文(在大多数情况下为活动)主题。活动的未来膨胀(例如,轮换之后)将在各处使用新主题
-Irhala,

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.Builder则请检查传递给构建器的上下文。希望这可以帮助!:)


9

确保已android:minSdkVersion="11"设置清单。这可能就是为什么大卫的榜样对您不起作用的原因。

此外,设置android:theme="@android:style/Theme.Holo.Light"该属性<application>标签和NOT<activity>标签。

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

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

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


一些有用的链接:

片段中的自定义ListView不坚持父主题


8

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

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

为了解决这个问题,我做了一个小小的改动,并将inflater.inflate中的container参数替换为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);
} 

谢谢,您的解决方案救了我。我的DialogFragment的主题与其他片段有所不同。因为使用了提供的充气机,所以它使EditText变得很奇怪。我发现了一些有关ContextThemeWrapper的帮助,但是他们没有显示如何完成。您的解决方案对我有用。非常感谢。
富国道

4

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

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

2

创建一个Java类,然后在onCreate方法中使用您想要更改主题的布局,然后像平常一样在清单中提及它


1

如果您只想为特定片段应用样式,则只需在调用onCreateView()或之前添加此行onAttach()

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

而如果你想设置透明状态栏然后设置fitsSystemWindows你的根布局的特性,

android:fitsSystemWindows="false"

1

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

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

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


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

-1

你可以在onAttach上尝试棒棒糖

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

并将其设置为ondettach中的默认值

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.