鴻蒙開源第三方元件——SkinSprite晝夜模式切換元件

語言: CN / TW / HK

前言

本元件是基於安卓平臺的晝夜模式切換元件SkinSprite,實現了其核心功能的鴻蒙化遷移和重構。目前程式碼已經開源到 https://gitee.com/archermind-ti/skinsprite ,歡迎各位下載使用並提出寶貴意見!

背景

安卓版本的SkinSprite為晝夜模式切換提供了一種全新的思路,並且無需使用者重啟應用。 本元件是SkinSprite的鴻蒙化版本,名為SkinSprite,實現了其核心功能。

設計目標

接入元件後,可以不需要修改佈局檔案,僅修改Ability或AbilitySlice的繼承,即可實現晝夜模式切換。

元件效果展示

目前SkinSprite主要有白天場景和黑夜場景兩種效果,下面將分別展示白天場景和黑夜場景的效果。

白天場景

day

黑夜場景

night

library解析

  1. 工程結構對比 鴻蒙 安卓

從對比圖中,可以看出兩庫基本結構保持一致,庫實現了安卓側的主要功能。相較於安卓側,主要少了SkinnableToolbar的實現,Toolbar在鴻蒙中沒有對應實現,但你可以通過控制元件組合,來實現Toolbar的功能。

  1. 佈局檔案解析 程式碼實現上,安卓使用LayoutInflaterCompat.setFactory(LayoutInflater, LayoutInflaterFactory)方法為佈局解析器新增佈局解析的工廠介面實現,從而實現替換原控制元件使其變成支援晝夜模式切換的控制元件。 在鴻蒙版本中,使用多層代理從而實現xml檔案解析時,將支援的控制元件的名稱轉換成支援晝夜模式切換的控制元件的名稱。主要是對LayoutScatter(佈局解析器)、ResourceManager(資源管理器)、SolidXml(Xml描述實體)和Node(xml標籤)的代理,在代理Node的時候,將原標籤名稱替換為對應晝夜模式切換的控制元件的名稱。

  2. 晝夜切換控制元件 Skinnable介面:

public interface Skinnable {
    /**
     * called by activity when UiMode changed
     */
    void applyDayNight();

    /**
     * indicate that if it can be changed by {@link SkinnableAbility}
     * @return true if it works
     */
    boolean isSkinnable();

    void setSkinnable(boolean skinnable);
}

該介面主要定義晝夜模式切換的基本功能。支援晝夜模式切換的控制元件都需要實現該介面,並修改控制元件上有顏色的部分,例如:背景和文字顏色。 目前,主要實現控制元件有:SkinnableButtonSkinnableDepentLayoutSkinnableDirectionalLayoutSkinnableStackLayoutSkinnableText

sample

public class MainAbilitySlice extends SkinnableAbilitySlice {

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        setReUIComponent(ResourceTable.Layout_ability_main);
        setSkinnableCallback(new SkinnableAbility.SkinnableCallback() {
            @Override
            public void beforeApplyDayNight() {
                new ToastDialog(MainAbilitySlice.this).setText("即將切換").show();
            }

            @Override
            public void onApplyDayNight() {
                new ToastDialog(MainAbilitySlice.this).setText("切換完成").show();
            }
        });

        findComponentById(ResourceTable.Id_btn_change).setClickedListener(component -> {
            int currentNightMode = wrapColorMode(getColorMode());
            switch (currentNightMode) {
                case Configuration.DARK_MODE: {
                    setDayNightMode(Configuration.LIGHT_MODE);
                    // Night mode is not active, we're in day time
                    break;
                }
                case Configuration.LIGHT_MODE: {
                    setDayNightMode(Configuration.DARK_MODE);
                    // Night mode is active, we're at night!
                    break;
                }
            }
        });

        Component component = SkinnableComponentLayoutScatter.getInstance(this).parse(ResourceTable.Layout_ability_main, null, false);
        if (component instanceof Skinnable) {
            new ToastDialog(MainAbilitySlice.this).setText("解析完成").show();
        }
    }

    private int wrapColorMode(int colorMode) {
        if (Configuration.AUTO_MODE == colorMode) {
            return getResourceManager().getConfiguration().getSystemColorMode();
        }
        return colorMode;
    }

    @Override
    protected int getDayNightStatusColor() {
        return getColor(ResourceTable.Color_statusColor);
    }
}

ability_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:background_element="$color:colorAccent"
    ohos:orientation="vertical"
    ohos:padding="16vp">

    <Text
        ohos:id="$+id:tv_wait_for_change"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$color:textColor"
        ohos:text="$string:mainability_HelloWorld"
        ohos:text_color="$color:colorPrimary"
        ohos:text_size="50px"
        ohos:top_margin="66vp"
        />

    <Button
        ohos:id="$+id:btn_change"
        ohos:height="48vp"
        ohos:width="match_parent"
        ohos:background_element="$color:colorPrimaryDark"
        ohos:text="change theme"
        ohos:text_color="$color:textColor"
        ohos:top_margin="50vp"/>
</DirectionalLayout>

作者:誠邁科技 馮仁杰