Skip to content

CustomThemeStyle_tc

Kongzue edited this page Nov 16, 2023 · 1 revision

🌐 View English Document | 简体中文文档

🎽自訂 DialogX 主題

DialogX 支持自訂 DialogX 的主題效果,你可以在 https://github.com/kongzue/DialogX 的項目原始碼中看到由我已經實現的三套主題,這些主題都是可選的,支持獨立從外部進行引入使用,但因為是預置的主題,不一定能完全滿足開發者的實際需求,在保證整體框架不會臃腫的情況下,DialogX 提供了專用的主題介面用於提供更豐富的主題可訂製性。

要製作自訂主題,首先你需要了解 DialogX 主題介面,該介面是一個 jar 包,你可以在這裡下載到它:點擊下載DialogXInterface.jar,其原始碼在:點擊查看 DialogXInterface 介面原始碼

或者手動引入:

MavenCentral 源:

最新版本: DialogXInterface Release
implementation 'com.kongzue.dialogx.style:DialogXInterface:5'

DialogX 提供了一個介面 DialogXStyle,開發者只需要實現其中的方法並重寫相關代碼即可完成自訂主題的製作。

此文件適用於 DialogXInterface 版本:5

DialogXStyle 介面解析

以下以 iOS 主題樣式為例,介紹重寫 DialogXStyle 介面後的範例原始碼:

public class IOSStyle extends DialogXStyle {
    
    public static IOSStyle style() {
        return new IOSStyle();
    }
    
    @Override
    public int layout(boolean light) {
        return light ? R.layout.layout_dialogx_ios : R.layout.layout_dialogx_ios_dark;
    }
    
    @Override
    public int enterAnimResId() {
        return R.anim.anim_dialogx_ios_enter;
    }
    
    @Override
    public int exitAnimResId() {
        return 0;
    }
    
    @Override
    public int[] verticalButtonOrder() {
        return new int[]{BUTTON_OK, SPLIT, BUTTON_OTHER, SPLIT, BUTTON_CANCEL};
    }
    
    @Override
    public int[] horizontalButtonOrder() {
        return new int[]{BUTTON_CANCEL, SPLIT, BUTTON_OTHER, SPLIT, BUTTON_OK};
    }
    
    @Override
    public int splitWidthPx() {
        return 1;
    }
    
    @Override
    public int splitColorRes(boolean light) {
        return light ? R.color.dialogxIOSSplitLight : R.color.dialogxIOSSplitDark;
    }
    
    @Override
    public BlurBackgroundSetting messageDialogBlurSettings() {
        return new BlurBackgroundSetting() {
            @Override
            public boolean blurBackground() {
                return true;
            }
            
            @Override
            public int blurForwardColorRes(boolean light) {
                return light ? R.color.dialogxIOSBkgLight : R.color.dialogxIOSBkgDark;
            }
            
            @Override
            public int blurBackgroundRoundRadiusPx() {
                return dip2px(15);
            }
        };
    }
    
    private int dip2px(float dpValue) {
        final float scale = Resources.getSystem().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
    
    @Override
    public HorizontalButtonRes overrideHorizontalButtonRes() {
        return new HorizontalButtonRes() {
            @Override
            public int overrideHorizontalOkButtonBackgroundRes(int visibleButtonCount, boolean light) {
                if (visibleButtonCount == 1) {
                    return light ? R.drawable.button_dialogx_ios_bottom_light : R.drawable.button_dialogx_ios_bottom_night;
                } else {
                    return light ? R.drawable.button_dialogx_ios_right_light : R.drawable.button_dialogx_ios_right_night;
                }
            }
            
            @Override
            public int overrideHorizontalCancelButtonBackgroundRes(int visibleButtonCount, boolean light) {
                return light ? R.drawable.button_dialogx_ios_left_light : R.drawable.button_dialogx_ios_left_night;
            }
            
            @Override
            public int overrideHorizontalOtherButtonBackgroundRes(int visibleButtonCount, boolean light) {
                return light ? R.drawable.button_dialogx_ios_center_light : R.drawable.button_dialogx_ios_center_night;
            }
        };
    }
    
    @Override
    public VerticalButtonRes overrideVerticalButtonRes() {
        return new VerticalButtonRes() {
            @Override
            public int overrideVerticalOkButtonBackgroundRes(int visibleButtonCount, boolean light) {
                return light ? R.drawable.button_dialogx_ios_center_light : R.drawable.button_dialogx_ios_center_night;
            }
            
            @Override
            public int overrideVerticalCancelButtonBackgroundRes(int visibleButtonCount, boolean light) {
                return light ? R.drawable.button_dialogx_ios_bottom_light : R.drawable.button_dialogx_ios_bottom_night;
            }
            
            @Override
            public int overrideVerticalOtherButtonBackgroundRes(int visibleButtonCount, boolean light) {
                return light ? R.drawable.button_dialogx_ios_center_light : R.drawable.button_dialogx_ios_center_night;
            }
        };
    }
    
    @Override
    public WaitTipRes overrideWaitTipRes() {
        return new WaitTipRes() {
            @Override
            public int overrideWaitLayout(boolean light) {
                return 0;
            }
            
            @Override
            public int overrideRadiusPx() {
                return -1;
            }
            
            @Override
            public boolean blurBackground() {
                return true;
            }
            
            @Override
            public int overrideBackgroundColorRes(boolean light) {
                return light ? R.color.dialogxIOSWaitBkgDark : R.color.dialogxIOSWaitBkgLight;
            }
            
            @Override
            public int overrideTextColorRes(boolean light) {
                return 0;
            }
            
            @Override
            public ProgressViewInterface overrideWaitView(Context context, boolean light) {
                return new ProgressView(context).setLightMode(light);
            }
        };
    }
    
    @Override
    public BottomDialogRes overrideBottomDialogRes() {
        return new BottomDialogRes() {
            
            @Override
            public boolean touchSlide() {
                return false;
            }
            
            @Override
            public int overrideDialogLayout(boolean light) {
                //return light ? R.layout.layout_dialogx_bottom_material : R.layout.layout_dialogx_bottom_material_dark;
                return light ? R.layout.layout_dialogx_bottom_ios : R.layout.layout_dialogx_bottom_ios_dark;
            }
            
            @Override
            public int overrideMenuDividerDrawableRes(boolean light) {
                return light ? R.drawable.rect_dialogx_ios_menu_split_divider : R.drawable.rect_dialogx_ios_menu_split_divider_night;
            }
            
            @Override
            public int overrideMenuDividerHeight(boolean light) {
                return 1;
            }
            
            @Override
            public int overrideMenuTextColor(boolean light) {
                return light ? R.color.dialogxIOSBlue : R.color.dialogxIOSBlueDark;
            }
            
            @Override
            public float overrideBottomDialogMaxHeight() {
                return 0f;
            }
            
            @Override
            public int overrideMenuItemLayout(boolean light, int index, int count, boolean isContentVisibility) {
                if (light) {
                    if (index == 0) {
                        return isContentVisibility ? R.layout.item_dialogx_ios_bottom_menu_center_light : R.layout.item_dialogx_ios_bottom_menu_top_light;
                    } else if (index == count - 1) {
                        return R.layout.item_dialogx_ios_bottom_menu_bottom_light;
                    } else {
                        return R.layout.item_dialogx_ios_bottom_menu_center_light;
                    }
                } else {
                    if (index == 0) {
                        return isContentVisibility ? R.layout.item_dialogx_ios_bottom_menu_center_dark : R.layout.item_dialogx_ios_bottom_menu_top_dark;
                    } else if (index == count - 1) {
                        return R.layout.item_dialogx_ios_bottom_menu_bottom_dark;
                    } else {
                        return R.layout.item_dialogx_ios_bottom_menu_center_dark;
                    }
                }
            }
            
            @Override
            public int overrideSelectionMenuBackgroundColor(boolean light) {
                return 0;
            }
            
            @Override
            public boolean selectionImageTint(boolean light) {
                return true;
            }
            
            @Override
            public int overrideSelectionImage(boolean light, boolean isSelected) {
                return 0;
            }
            
            @Override
            public int overrideMultiSelectionImage(boolean light, boolean isSelected) {
                return 0;
            }
        };
    }
    
    @Override
    public PopTipSettings popTipSettings() {
        return new PopTipSettings() {
            @Override
            public int layout(boolean light) {
                return light ? R.layout.layout_dialogx_poptip_ios : R.layout.layout_dialogx_poptip_ios_dark;
            }
            
            @Override
            public ALIGN align() {
                return ALIGN.TOP;
            }
            
            @Override
            public int enterAnimResId(boolean light) {
                return R.anim.anim_dialogx_ios_top_enter;
            }
            
            @Override
            public int exitAnimResId(boolean light) {
                return R.anim.anim_dialogx_ios_top_exit;
            }
            
            @Override
            public boolean tintIcon() {
                return false;
            }
        };
    }
    
    @Override
    public PopNotificationSettings popNotificationSettings() {
        return new PopNotificationSettings() {
            @Override
            public int layout(boolean light) {
                return light ? R.layout.layout_dialogx_popnotification_ios : R.layout.layout_dialogx_popnotification_ios_dark;
            }
            
            @Override
            public PopNotificationSettings.ALIGN align() {
                return ALIGN.TOP;
            }
            
            @Override
            public int enterAnimResId(boolean light) {
                return com.kongzue.dialogx.R.anim.anim_dialogx_notification_enter;
            }
            
            @Override
            public int exitAnimResId(boolean light) {
                return com.kongzue.dialogx.R.anim.anim_dialogx_notification_exit;
            }
            
            @Override
            public boolean tintIcon() {
                return false;
            }
            
            @Override
            public BlurBackgroundSetting blurBackgroundSettings() {
                return new BlurBackgroundSetting() {
                    @Override
                    public boolean blurBackground() {
                        return true;
                    }
                    
                    @Override
                    public int blurForwardColorRes(boolean light) {
                        return light ? R.color.dialogxIOSNotificationBkgLight : R.color.dialogxIOSNotificationBkgDark;
                    }
                    
                    @Override
                    public int blurBackgroundRoundRadiusPx() {
                        return dip2px(18);
                    }
                };
            }
        };
    }
    
    @Override
    public PopMenuSettings popMenuSettings() {
        return new PopMenuSettings() {
            @Override
            public int layout(boolean light) {
                return light ? R.layout.layout_dialogx_popmenu_ios : R.layout.layout_dialogx_popmenu_ios_dark;
            }
            
            @Override
            public BlurBackgroundSetting blurBackgroundSettings() {
                return new BlurBackgroundSetting() {
                    @Override
                    public boolean blurBackground() {
                        return true;
                    }
                    
                    @Override
                    public int blurForwardColorRes(boolean light) {
                        return light ? R.color.dialogxIOSBkgLight : R.color.dialogxIOSBkgDark;
                    }
                    
                    @Override
                    public int blurBackgroundRoundRadiusPx() {
                        return dip2px(15);
                    }
                };
            }
            
            @Override
            public int backgroundMaskColorRes() {
                return R.color.black20;
            }
            
            @Override
            public int overrideMenuDividerDrawableRes(boolean light) {
                return light ? R.drawable.rect_dialogx_ios_menu_split_divider : R.drawable.rect_dialogx_ios_menu_split_divider_night;
            }
            
            @Override
            public int overrideMenuDividerHeight(boolean light) {
                return 1;
            }
            
            @Override
            public int overrideMenuTextColor(boolean light) {
                return 0;
            }
            
            @Override
            public int overrideMenuItemLayoutRes(boolean light) {
                return light ? R.layout.item_dialogx_ios_popmenu_light : R.layout.item_dialogx_ios_popmenu_dark;
            }
            
            @Override
            public int overrideMenuItemBackgroundRes(boolean light, int index, int count, boolean isContentVisibility) {
                if (light) {
                    if (index == 0) {
                        return R.drawable.button_dialogx_ios_top_light;
                    } else if (index == count - 1) {
                        return R.drawable.button_dialogx_ios_bottom_light;
                    } else {
                        return R.drawable.button_dialogx_ios_center_light;
                    }
                } else {
                    if (index == 0) {
                        return R.drawable.button_dialogx_ios_top_night;
                    } else if (index == count - 1) {
                        return R.drawable.button_dialogx_ios_bottom_night;
                    } else {
                        return R.drawable.button_dialogx_ios_center_night;
                    }
                }
            }
            
            @Override
            public int overrideSelectionMenuBackgroundColor(boolean light) {
                return 0;
            }
            
            @Override
            public boolean selectionImageTint(boolean light) {
                return false;
            }
            
            @Override
            public int paddingVertical() {
                return 0;
            }
        };
    }
}

大部分介面都可以 return null 來使用默認樣式不做修改,以下會逐一介紹相關介面的方法。

設置時,使用以下方法即可:

DialogX.globalStyle = new IOSStyle();

修改消息對話框 layout 布局

@Override
public int layout(boolean light) {
    return light ? R.layout.layout_dialogx_ios : R.layout.layout_dialogx_ios_dark;
}

重寫 layout 方法用於設置預設的消息對話框的 layout 布局文件,其中 light 參數用於判斷是否為亮色模式,你可以在這裡查看亮色默認主題布局文件的實現暗色默認主題布局文件的實現,請參照 Demo 布局的格式進行布局設計,不建議修改或去掉布局中的含有 id 的組件。

修改預設對話框啟動、關閉動畫效果

@Override
public int enterAnimResId() {
    return R.anim.anim_dialogx_ios_enter;
}

@Override
public int exitAnimResId() {
    return 0;
}

你可以自訂消息對話框的啟動、關閉動畫效果,當你return 0時則採用默認實現,要自訂動畫文件,可以參考:預設對話框啟動動畫文件預設對話框關閉動畫文件

修改默認按鈕排序

在特殊情況下,你可以調整對話框的按鈕布局順序,例如,在橫向時,我們一般採用“其他、取消、確定”的邏輯,在縱向時,我們可以調整為“確定、其他、取消”的順序,要修改按鈕排序順序,你可以重寫以下介面。

@Override
public int[] verticalButtonOrder() {
    return new int[]{BUTTON_OTHER, BUTTON_CANCEL, BUTTON_OK};
}

@Override
public int[] horizontalButtonOrder() {
    return new int[]{BUTTON_OK, BUTTON_OTHER, BUTTON_CANCEL};
}

另外,如果需要分隔線,可以使用在按鈕間加入“SPLIT”,例如在 iOS 的主題樣式中,按鈕排序之間加入了分隔線:

@Override
public int[] verticalButtonOrder() {
    return new int[]{BUTTON_OK, SPLIT, BUTTON_OTHER, SPLIT, BUTTON_CANCEL};
}

若需要調整分隔線的寬度和顏色,可以重寫以下介面進行設置,這些設置也可以使用 return 0不進行設置。

@Override
public int splitWidthPx() {
    return 1;
}

@Override
public int splitColorRes(boolean light) {
    return light ? R.color.dialogxIOSSplitLight : R.color.dialogxIOSSplitDark;
}

在 Material 主題風格中,按鈕之間並不是分隔線,而是一段空白的間距,你可以使用“SPACE”設置間距,如下:

@Override
public int[] horizontalButtonOrder() {
    return new int[]{BUTTON_OTHER, SPACE, BUTTON_CANCEL, BUTTON_OK};
}

自訂按鈕樣式

一些主題要求我們在顯示按鈕時提供不同的樣式,你可以透過兩個介面來進行自訂:當對話框按鈕處於橫向/縱向時,或者當按鈕顯示數量為1個、2個或3個時,呈現不同的樣式。

例如 iOS 主題,橫向且只顯示一個按鈕(OkButton)時,需要左下角和右下角都為圓角的按鈕樣式,當顯示多個按鈕時則為僅右下角為圓角的按鈕樣式,如果需要基於不同的情況進行相應按鈕樣式調整,你可以重寫以下介面:

@Override
public HorizontalButtonRes overrideHorizontalButtonRes() {
    return new HorizontalButtonRes() {
        @Override
        public int overrideHorizontalOkButtonBackgroundRes(int visibleButtonCount, boolean light) {
            if (visibleButtonCount == 1) {
                return light ? R.drawable.button_dialogx_ios_bottom_light : R.drawable.button_dialogx_ios_bottom_night;
            } else {
                return light ? R.drawable.button_dialogx_ios_right_light : R.drawable.button_dialogx_ios_right_night;
            }
        }
        
        @Override
        public int overrideHorizontalCancelButtonBackgroundRes(int visibleButtonCount, boolean light) {
            return light ? R.drawable.button_dialogx_ios_left_light : R.drawable.button_dialogx_ios_left_night;
        }
        
        @Override
        public int overrideHorizontalOtherButtonBackgroundRes(int visibleButtonCount, boolean light) {
            return light ? R.drawable.button_dialogx_ios_center_light : R.drawable.button_dialogx_ios_center_night;
        }
    };
}
@Override
public VerticalButtonRes overrideVerticalButtonRes() {
    return new VerticalButtonRes() {
        @Override
        public int overrideVerticalOkButtonBackgroundRes(int visibleButtonCount, boolean light) {
            return light ? R.drawable.button_dialogx_ios_center_light : R.drawable.button_dialogx_ios_center_night;
        }
        
        @Override
        public int overrideVerticalCancelButtonBackgroundRes(int visibleButtonCount, boolean light) {
            return light ? R.drawable.button_dialogx_ios_bottom_light : R.drawable.button_dialogx_ios_bottom_night;
        }
        
        @Override
        public int overrideVerticalOtherButtonBackgroundRes(int visibleButtonCount, boolean light) {
            return light ? R.drawable.button_dialogx_ios_center_light : R.drawable.button_dialogx_ios_center_night;
        }
    };
}

其中visibleButtonCount參數為當前顯示按鈕的數量,light參數為當前對話框的亮/暗色模式。

drawable 只接受 xml 配置,可以定義不同狀態時的按鈕樣式效果,如有需要請參考 iOS drawable 樣式

overrideHorizontalButtonResoverrideVerticalButtonRes返回值return null時默認不進行樣式修改設置。

模糊背景

預設對話框支持模糊化背景,如果需要模糊的背景效果,你可以重寫以下介面:

@Override
public BlurBackgroundSetting messageDialogBlurSettings() {
    return new BlurBackgroundSetting() {
        @Override
        public boolean blurBackground() {
            return true;
        }
        
        @Override
        public int blurForwardColorRes(boolean light) {
            return light ? R.color.dialogxIOSBkgLight : R.color.dialogxIOSBkgDark;
        }
        
        @Override
        public int blurBackgroundRoundRadiusPx() {
            return dip2px(15);
        }
    };
}

如果不需要可以return null進行默認處理。

此介面需要重寫一個BlurBackgroundSetting,其中包含三個子介面,分別是blurBackground()用於判斷是否開啟模糊,blurForwardColorRes(boolean light)用於處理前景色(建議設置一定的透明度保證可以看到背後的模糊效果),blurBackgroundRoundRadiusPx()用於給定模糊效果的圓角半徑,單位為像素(Px)。

修改等待/提示框的樣式

如果需要修改等待/提示框的樣式效果,你可以重寫這個介面:

@Override
public WaitTipRes overrideWaitTipRes() {
    return new WaitTipRes() {
        @Override
        public boolean blurBackground() {
            return true;
        }
        
        @Override
        public int overrideBackgroundColorRes(boolean light) {
            return 0;
        }
        
        @Override
        public int overrideTextColorRes(boolean light) {
            return light ? R.color.white : R.color.black;
        }
        @Override
        public ProgressViewInterface overrideWaitView(Context context, boolean light) {
            return new ProgressView(context).setLightMode(light);
        }
    };
}

此介面return null時採用默認樣式。

WaitTipRes介面中第一個子介面blurBackground()用於判斷是否需要模糊背景效果

第二個介面overrideBackgroundColorRes(boolean light)用於重新設置前景色

第三個介面overrideTextColorRes(boolean light)用於設置在亮/暗色時的文字顏色,注意,此顏色也將修改進度動畫的顏色。

第四個介面overrideWaitView(Context context, boolean light)比較特殊,當return null時使用默認動畫效果,如果需要自訂動畫,則需要一個實現了 ProgressViewInterface 介面的 View 組件,具體方法請參考下一章節。

自訂等待提示動畫組件 ProgressViewInterface

ProgressViewInterface 的介面定義如下:

public interface ProgressViewInterface {
    
    //停止載入動畫
    void noLoading();
    
    //切換至完成狀態
    void success();
    
    //切換至警告狀態
    void warning();
    
    //切換至錯誤狀態
    void error();
    
    //切換至進度(取值 0f-1f)
    void progress(float progress);
    
    //切換至載入狀態
    void loading();
    
    //不同狀態切換時,銜接動畫完成後執行
    ProgressViewInterface whenShowTick(Runnable runnable);
    
    //設置顏色
    ProgressViewInterface setColor(int color);
}

需要在自訂的 View 中實現這些方法,以實現在等待提示框處於不同狀態時調整顯示的樣式。

需要注意的是,默認等待提示框在載入中到完成/警告/錯誤等狀態時,會有銜接過渡的過程,這個過程導致目標狀態可能會延後幾十到幾百毫秒後才真正切換,因此有一個whenShowTick(Runnable runnable)介面需要實現,在銜接過程結束後執行runnable.run()即可,若無銜接過程,直接在重寫後的方法中執行runnable.run()即可。

在亮暗色模式切換後,等待提示框組件應該遵循顏色的變化調整顏色,這個顏色會從setColor(int color)介面中給出,注意此處的參數color是色值,並非資源值,建議直接賦值給畫筆 Paint 進行繪製操作。

如需參照 Demo,您可以查看 iOS 樣式的 ProgressView 實現:ProgressView.java

自訂底部對話框/菜單樣式

底部對話框是 DialogX 中第二個具有豐富功能的組件,您可以實現overrideBottomDialogRes()方法以自訂底部對話框的樣式細節。

同樣的,當return null 時使用默認樣式(Material 主題)。

以下基於 iOS 樣式的配置進行講解:

@Override
public BottomDialogRes overrideBottomDialogRes() {
    return new BottomDialogRes() {
    
        @Override
        public boolean touchSlide() {
            return false;
        }
    
        @Override
        public int overrideDialogLayout(boolean light) {
            return light ? R.layout.layout_dialogx_bottom_ios : R.layout.layout_dialogx_bottom_ios_dark;
        }
    
        @Override
        public int overrideMenuDividerDrawableRes(boolean light) {
            return light ? R.drawable.rect_dialogx_ios_menu_split_divider : R.drawable.rect_dialogx_ios_menu_split_divider_night;
        }
    
        @Override
        public int overrideMenuDividerHeight(boolean light) {
            return 1;
        }
    
        @Override
        public int overrideMenuTextColor(boolean light) {
            return light ? R.color.dialogxIOSBlue : R.color.dialogxIOSBlueDark;
        }
    
        @Override
        public float overrideBottomDialogMaxHeight() {
            return 0f;
        }
    
        @Override
        public int overrideMenuItemLayout(boolean light, int index, int count, boolean isContentVisibility) {
            if (light) {
                if (index == 0) {
                    return isContentVisibility ? R.layout.item_dialogx_ios_bottom_menu_center_light : R.layout.item_dialogx_ios_bottom_menu_top_light;
                } else if (index == count - 1) {
                    return R.layout.item_dialogx_ios_bottom_menu_bottom_light;
                } else {
                    return R.layout.item_dialogx_ios_bottom_menu_center_light;
                }
            } else {
                if (index == 0) {
                    return isContentVisibility ? R.layout.item_dialogx_ios_bottom_menu_center_dark : R.layout.item_dialogx_ios_bottom_menu_top_dark;
                } else if (index == count - 1) {
                    return R.layout.item_dialogx_ios_bottom_menu_bottom_dark;
                } else {
                    return R.layout.item_dialogx_ios_bottom_menu_center_dark;
                }
            }
        }
        @Override
        public int overrideSelectionMenuBackgroundColor(boolean light) {
            return 0;
        }
        @Override
        public boolean selectionImageTint(boolean light) {
            return true;
        }
    
        @Override
        public int overrideSelectionImage(boolean light, boolean isSelected) {
            return 0;
        }
    };
}

touchSlide() 介面定義了是否支持滑動關閉操作。

overrideDialogLayout(boolean light)介面用於設置底部對話框的布局,如需修改布局樣式,請參照 底部對話框默認亮色布局 和 底部對話框默認暗色布局,請參照 Demo 布局的格式進行布局設計,不建議修改或去掉布局中的含有 id 的組件,當return 0時使用默認實現。

overrideMenuDividerDrawableRes(boolean light)用於修改底部選單分隔線的樣式,可以自訂實行 drawable 資源,具體實現可以參考底部選單分隔線默認實現的 drawable 文件,當return 0時使用默認實現。

overrideMenuDividerHeight(boolean light)用於修改預設分隔線的粗細,單位像素。

overrideMenuTextColor(boolean light)用於修改默認菜單文字的顏色,值採用為 color 的資源 ID。

overrideBottomDialogMaxHeight()用於設置默認情況下,當底部對話框內容大於螢幕可顯示高度時,默認啟動後顯示的高度比例,值為浮點型,例如設置為 0.6f 時,則當內容大於可顯示高度時,啟動後對話框只從螢幕底部彈出 0.6×螢幕高度的大小,需要再次向上拖拽才能展開全部對話框,此功能需要和 touchSlide() 配合使用。

overrideMenuItemLayout(boolean light, int index, int count, boolean isContentVisibility)介面用於定義菜單條目的布局樣式。其中參數layout用於判斷亮/暗色模式,參數index為當前菜單項的索引值,count為菜單數量,isContentVisibility用於確認當菜單顯示時,是否還有其他內容顯示(例如對話框標題、正文或自訂布局),例如當使用 iOS 樣式時,第一條菜單默認採用左上角和右上角都為圓角的樣式,當顯示菜單標題、正文或自訂布局時,則第一條菜單使用無圓角樣式。當index == count - 1時為最後一個菜單,使用 iOS 樣式時,最後一個菜單應該採用左下角和右下角都為圓角的樣式。菜單的布局請參照 底部選單亮色樣式參考布局底部選單暗色樣式參考布局 。此介面return 0時使用默認實現。

overrideSelectionMenuBackgroundColor(boolean light)介面用於定義已選中的菜單默認背景顏色,例如在使用 MIUI 主題樣式且開啟了單選模式時,默認打開菜單後會選中上次已選擇的條目,此介面用預設定已選中菜單的背景顏色。

selectionImageTint(boolean light)介面用於確定使用此主題時,預設會不會重定義圖示的顏色,若開啟,那麼所有菜單圖示會根據主題的亮/暗色的文字顏色重新覆蓋顏色,若關閉,則使用圖示原本的顏色。

overrideSelectionImage(boolean light, boolean isSelected)用於設置默認菜單已選擇/未選擇時的圖示資源,可使用 mipmap 圖像或者 drawable 資源。

自訂 PopTip 樣式

以下是 iOS 主題樣式的 PopTip 介面實現:

@Override
public PopTipSettings popTipSettings() {
    return new PopTipSettings() {
        @Override
        public int layout(boolean light) {
            return light?R.layout.layout_dialogx_poptip_ios :R.layout.layout_dialogx_poptip_ios_dark;
        }
        
        @Override
        public ALIGN align() {
            return ALIGN.TOP;
        }
        
        @Override
        public int enterAnimResId(boolean light) {
            return R.anim.anim_dialogx_ios_top_enter;
        }
        
        @Override
        public int exitAnimResId(boolean light) {
            return R.anim.anim_dialogx_ios_top_exit;
        }
    };
}

同樣的,當return null 時使用默認樣式。

此介面包含的子介面如下:

layout(boolean light)PopTip 的默認布局樣式,請參考具體布局實現:PopTip 默認亮色布局PopTip 默認暗色布局

align()介面用於判斷 PopTip 的彈出規則,支持的值如下:

ALIGN {
    CENTER:螢幕中央彈出
    TOP:螢幕頂端彈出(非安全區)
    BOTTOM:螢幕底部彈出(非安全區)
    TOP_INSIDE:螢幕頂端安全區內彈出
    BOTTOM_INSIDE:螢幕底部安全區內彈出
}

enterAnimResId(boolean light)設置啟動動畫效果。

exitAnimResId(boolean light)設置關閉動畫效果。

其他提示

自訂 DialogX 主題是 DialogX 組件中較難的操作,建議多參考現有提供的主題實現原始碼:

Material 主題原始碼

iOS 主題原始碼

Kongzue 主題原始碼

MIUI 主題原始碼

您也可以加入 DialogX 的 討論群 獲得第一時間的技術支援。

自訂主題的部分設置

對主題全局設置進行覆寫

你可以透過覆寫部分設置來調整一些由主題定義的全局設置,例如 PopTip 的圖示染色是由主題設置定義的,每次調整也可以透過方法進行設置,但要對 PopTip 的圖示染色功能進行全局設置,可以直接覆寫介面設置來實現,參考代碼:

//在設置主題時:
DialogX.globalStyle = new MaterialStyle(){
    @Override
    public PopTipSettings popTipSettings() {
        return new PopTipSettings() {
            @Override
            public boolean tintIcon() {
                return false;       //禁用圖示染色
            }
        };
    }
};

即可完成調整。

對主題布局進行覆寫

要自訂部分對話框的布局,你可以直接在你的 app 的 res/layout 中創建一個主題資源相同名稱的 xml 布局,並拷貝其內容進行修改。

例如對於 IOS 主題的 PopTip 布局,在設置好主題後,你可以編寫一個名稱為 layout_dialogx_poptip_ios.xml 以及暗色主題文件 layout_dialogx_poptip_ios_dark.xml 的布局文件,內容請參考 layout_dialogx_poptip_ios.xmllayout_dialogx_poptip_ios_dark.xml 拷貝其內容進行修改,編譯後會自動覆蓋主題的布局文件,得到你想要的運行結果。

Clone this wiki locally