Android Dialog custom Theme

问题描述:如何对一个对话框设置 主题风格

解决思路:

     一.查看dialog的构造器如下图1-1、1-2

复制代码
 /**
     * Create a Dialog window that uses a custom dialog style.
     * 
     * @param context The Context in which the Dialog should run. In particular, it
     *                uses the window manager and theme from this context to
     *                present its UI.
     * @param theme A style resource describing the theme to use for the 
     * window. See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">Style 
     * and Theme Resources</a> for more information about defining and using 
     * styles.  This theme is applied on top of the current theme in 
     * <var>context</var>.  If 0, the default dialog theme will be used.
     */
    public Dialog(Context context, int theme) {
        this(context, theme, true);
    }
复制代码

                                                                      图1-1

 

复制代码
 Dialog(Context context, int theme, boolean createContextWrapper) {
        if (theme == 0) {
            TypedValue outValue = new TypedValue();
            context.getTheme().resolveAttribute(com.android.internal.R.attr.dialogTheme,
                    outValue, true);
            theme = outValue.resourceId;
        }

        mContext = createContextWrapper ? new ContextThemeWrapper(context, theme) : context;
        mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        Window w = PolicyManager.makeNewWindow(mContext);
        mWindow = w;
        w.setCallback(this);
        w.setWindowManager(mWindowManager, null, null);
        w.setGravity(Gravity.CENTER);
        mUiThread = Thread.currentThread();
        mListenersHandler = new ListenersHandler(this);
    }
复制代码

                                                        图1-2

发现,我们可以指定Dialog的主题。问题很简单是不是就解决了呢?答案是不一定,原因是:

    二、Dialog的结构包括三部分:title、content area、action buttons。对于title和action buttons 没什么好说的,直接调用系统的Api就行,而对于content area就不一样了,

           1.你可以直接调用系统的Api设置内容,指定的主题应该也会应用上去(没有严格验证)。

           2.也可以自定义内容,这个时候就要注意了。对于自定义的内容就不能应用到指定的theme了。

              对于自定义内容的一般会这样调用LayoutInflater.from(context).inflate(...),而context中是有主题内容的context中settheme如下图1-3

复制代码
 /**
     * Set the base theme for this context.  Note that this should be called
     * before any views are instantiated in the Context (for example before
     * calling {@link android.app.Activity#setContentView} or
     * {@link android.view.LayoutInflater#inflate}).
     *
     * @param resid The style resource describing the theme.
     */
    public abstract void setTheme(int resid);
复制代码

                                     图1-3

如源码中所说,设置主题一定要早于setcontentview 和 layoutinflater inflate。所以,我们推测,在dialog中自定义content area ,并用LayoutInflater.from(context).inflate(...)装载view时,view就会用context'中得主题。问题来了,如果想对dialog中自定义的content area怎么应用theme呢?

看图1-1,当指定dialog的主题后,会调用图1-2中得方法,mContext = createContextWrapper ? new ContextThemeWrapper(context, theme) : context;

也就是 mContext = new ContextThemeWrapper(context, theme) ,所以我们推测,可以在原context的基础上调用new ContextThemeWrapper(context, theme)生成带有指定theme的新的context,新的context'与原有context仅有theme不一样,这样一来。

    三、我们就可以通过

        AlertDialog.Builder builder = new Builder(context);

        ContextThemeWrapper themeContext = new ContextThemeWrapper(context, theme);

        LayoutInflater.from(themeContext).inflate(...)

来让自定义content area 的dialog 应用指定主题。

 

   四、对于activity中显示的dialog,还用一种简单的方法来让dialog(不管是否自定义content area)应用指定theme,那就是设置activity的theme即可。

但是原理和上面的一样,不再赘述。

 

posted @ 2014-11-28 10:06  爬山蜗牛  阅读(421)  评论(0编辑  收藏  举报