教你實現華爲快應用深色主題適配

問題背景

大部分手機主題上會有深色模式和淺色模式之分,淺色模式通常都是「白底黑字」,深色模式則是「黑底白字」。下圖是華爲手機深色模式和淺色模式的界面效果:css

  • 圖1 淺色模式

在這裏插入圖片描述

  • 圖2 深色模式

在這裏插入圖片描述

如何在快應用中實現不一樣主題模式的適配呢?目前有兩種方案:java

  • 使用MediaQuery響應式佈局能力,自動檢測用戶的設備的系統主題模式,配置不一樣模式下的css樣式。
  • 使用device.getThemeSync,根據獲取的結果選擇不一樣模式下的css樣式。

解決方案

方案一:MediaQuery響應式佈局(推薦)

華爲快應用響應式佈局中媒體特徵(Media Feature)類型提供了prefers-color-scheme字段:檢測用戶的系統主題,支持的屬性值有light和dark模式,對應手機的淺色主題和深色主題。開發者只須要在代碼中配置兩種模式下的css樣式便可,快應用引擎會根據系統主題模式自動調用不一樣的css。具體實現代碼以下:node

<template>
    <!-- Only one root node is allowed in template. -->
    <div class="container">
        <text class="title">
            Hello {{title}}
        </text>
    </div>
</template>
 
<style>
    .container {
        flex-direction: column;
        justify-content: center;
        align-content: center;
        align-items: center;
    }
 
    .title {
        font-size: 100px;
    }
 
    /**淺色主題css */
    @media (prefers-color-scheme: light) {
        .container {
            flex-direction: column;
            justify-content: center;
            align-content: center;
            align-items: center;  
        }
 
        .title {
            font-size: 100px;
            color: #000000;
        }
    }
 
    /**深色主題css*/
    @media (prefers-color-scheme: dark) {
        .container {
            flex-direction: column;
            justify-content: center;
            align-content: center;
            align-items: center;
            background-color: #000000;
        }
        .title {
            font-size: 100px;
            color: #ffffff;
        }
    }
</style>
 
<script>
    module.exports = {
        data: {
            title: 'World',
            titleBar: ''
        },
        onInit: function () {
            this.titleBar = this.titleBarText;
            console.log("onInit titleBar= " + this.titleBar);
            this.$page.setTitleBar({ text: this.titleBar });
        },
    }
</script>

優勢:實現簡單,代碼少,開發者只須要配置響應式佈局中dark和light的css,無需手動控制調用不一樣主題模式下的css。api

方案二:使用device.getThemeSync

步驟1:獲取設備的主題模式

可以使用device.getThemeSync接口返回值得到,推薦在全局app.ux中實現並將結果保存,對外提供getThemeMode()方法方便每一個頁面的ux獲取主題結果。app

app.ux代碼以下:ide

<script>
  import device from '@system.device';
  module.exports = {
    data: {
          thememode:''
    },
     onCreate () {
      setTimeout(() => {
         let theme=device.getThemeSync();
      //{"darkMode":false,"title":"Painted Planet","titleCn":"大地彩繪","author":"EMUI","designer":"EMUI","version":"10.0.7","font":"Default","fontCn":"默認"}
       console.info("onCreate theme="+JSON.stringify(theme));
       if(theme.darkMode){
         this.thememode='darkMode';
       }else{
         this.thememode='lightMode';
       }
      }, 100);
    },
    onDestroy() {
      console.info('Application onDestroy');
    },
      getThemeMode(){
          return this.thememode;
      }
  }
</script>

步驟2:頁面適配

頁面須要實現深色和淺色主題模式下的css樣式,根據 步驟1返回的結果選擇不一樣的css樣式。下面示例代碼.container和.item是淺色主題下的css樣式, . containerDarkMode. itemDarkMode 是深色主題下的css樣式。頁面在生命週期onInit()方法中根據獲取到的設備主題模式選擇不一樣的css樣式。代碼以下:佈局

<template>
  <!-- Only one root node is allowed in template. -->
  <div class="{{containercss}}">
    <input class="{{itemcss}}" type="button" value="a組件切換頁面" onclick="jumpApage" />
    <input class="{{itemcss}}" type="button" value="router接口切換頁面" onclick="jumpRouterPage" />
  </div>
</template>
 
<style>
  .container {
    flex-direction: column;
    margin-top: 50px;
    align-content: center;
    align-items: center;
  }
 
  .containerDarkMode {
    flex-direction: column;
    margin-top: 50px;
    align-content: center;
    align-items: center;
    background-color: #000000;
  }
 
  .item {
    background-color: #00bfff;
    color: #f8f8ff;
    font-size: 37px;
    width: 50%;
    height: 100px;
    margin-bottom: 20px;
  }
 
  .itemDarkMode {
    background-color: #add8e6;
    color: #f8f8ff;
    font-size: 37px;
    width: 50%;
    height: 100px;
    margin-bottom: 20px;
  }
</style>
 
<script>
  import router from '@system.router';
  module.exports = {
    data: {
      title: 'World',
      containercss: 'container',
      itemcss: 'item'
    },
 
    onInit: function () {
      console.info("onInit");
      var thememode = this.$app.$def.getThemeMode();
      console.info("onInit thememode=" + thememode);
      if (thememode === 'darkMode') {
        console.info("change dark mode");
        this.containercss = 'containerDarkMode';
        this.itemcss = 'itemDarkMode';
      } else {
        this.containercss = 'container';
        this.itemcss = 'item';
      }
},
 
    onDestroy: function () {
      console.info("onDestroy");
    },
 
    jumpRouterPage: function () {
      router.push({
        uri: 'SwitchPage/Router',
        params: { body: " test send message" },
      })
    },
 
    jumpApage: function () {
      router.push({
        uri: 'SwitchPage/Apage',
        params: { body: " test send message" },
      })
    },
  }
</script>

此方案相對方案一稍微複雜一點,須要開發者本身去控制css樣式選擇。flex

欲瞭解更多詳情,請參見:ui

快應用開發指導文檔:https://developer.huawei.com/consumer/cn/doc/development/quickApp-Guides/quickapp-whitepaperthis


原文連接:https://developer.huawei.com/consumer/cn/forum/topic/0201404994231590237?fid=18

原做者:Mayism

相關文章
相關標籤/搜索