【问题标题】:Set theme for a Fragment为片段设置主题
【发布时间】:2012-03-17 04:06:35
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: android android-fragments android-theme


    【解决方案1】:

    在 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)
    }
    

    【讨论】:

    • 这对我不起作用。该片段仍然具有清单文件中指定的相同主题。
    • 在清单中指定活动的主题,而不是片段。你用的是fragment还是fragmentActivity?
    • 为我工作。在 Activity 中使用经典的 Fragment。
    • @David "在清单中设置主题用于活动"。这并不完全正确。如果您在运行时使用 FragmentTransaction 添加您的 Fragment,该主题也将应用于 Fragment。
    • 这似乎不适用于 ActionBarSherlock 库中的 SherlockFragmentActivity。
    【解决方案2】:

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

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

    在 Fragment.onCreateView 中你得到 LayoutInflater 参数,它膨胀视图,它保存了用于主题的 Context,实际上这是 Activity。所以你的膨胀视图使用了 Activity 的主题。

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

    【讨论】:

    【解决方案3】:

    为了应用我只使用过的单一样式

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

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

    【讨论】:

    • 最小 api 23 用于getContext()
    • @vigilancer 检查此答案以解决您的 min api 问题:stackoverflow.com/questions/36736244/…
    • 很好的解决方案。我在 onAttach(Context) 中添加了代码,该代码也将主题应用于所有子片段
    • 这可能会产生意想不到的后果,因为它会修改上下文的(大多数情况下是活动)主题。 Activity 的未来膨胀(例如,在旋转之后)将在任何地方使用新主题
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

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

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

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

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


      一些有用的链接:

      Custom ListView in Fragment not adhering to parent theme

      【讨论】:

        【解决方案6】:

        我尝试了 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);
        } 
        

        【讨论】:

        • 谢谢,您的解决方案救了我。我的 DialogFragment 的主题在某种程度上与其他片段不同。它使我的 EditText 变得很奇怪,因为我使用了提供的充气机。我找到了一些关于 ContextThemeWrapper 的帮助,但他们没有展示它是如何完成的。你的解决方案对我有用。非常感谢。
        【解决方案7】:

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

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

        【讨论】:

        • 它对我有用,但我想知道这种方法是否会对其他视图产生副作用。在我的情况下,上下文是 MainActivity,然后我将覆盖 MainActivity 的主题。有意义吗?
        【解决方案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】:

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

        【讨论】:

          【解决方案10】:

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

          【讨论】:

            【解决方案11】:

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

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

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

            【讨论】:

              【解决方案12】:

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

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

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-01-29
                • 1970-01-01
                • 2012-01-09
                • 2016-12-17
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多