鸿蒙主题切换器:基于Cordova与动态资源管理的实现
·
鸿蒙主题切换器:基于Cordova与动态资源管理的实现
本文将介绍如何开发一个能够动态切换鸿蒙主题颜色的Cordova应用,结合鸿蒙的ResourceManager API和跨设备同步技术,实现类似《鸿蒙跨端U同步》中多设备显示一致性的主题切换功能。
一、技术架构概述
我们的主题切换器将采用以下技术架构:
- Cordova框架:作为跨平台应用的基础
- 自定义Cordova插件:桥接JS与鸿蒙原生API
- 鸿蒙ResourceManager:动态管理主题资源
- U同步技术:实现多设备主题同步
二、自定义Cordova插件实现
首先,我们需要创建一个自定义Cordova插件来调用鸿蒙的ResourceManager API。
1. 插件JavaScript接口 (www/HarmonyThemeSwitcher.js)
var exec = require('cordova/exec');
var HarmonyThemeSwitcher = {
setThemeColor: function(color, successCallback, errorCallback) {
exec(successCallback, errorCallback, 'HarmonyThemeSwitcher', 'setThemeColor', [color]);
},
getCurrentTheme: function(successCallback, errorCallback) {
exec(successCallback, errorCallback, 'HarmonyThemeSwitcher', 'getCurrentTheme', []);
},
registerThemeChangeListener: function(callback) {
exec(callback, null, 'HarmonyThemeSwitcher', 'registerThemeChangeListener', []);
}
};
module.exports = HarmonyThemeSwitcher;
2. 鸿蒙原生实现 (HarmonyThemeSwitcher.java)
package org.apache.cordova.harmonytheme;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import ohos.app.Context;
import ohos.app.AbilityContext;
import ohos.global.resource.ResourceManager;
import ohos.global.resource.Resource;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class HarmonyThemeSwitcher extends CordovaPlugin {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, "HarmonyThemeSwitcher");
private CallbackContext themeChangeCallback;
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if ("setThemeColor".equals(action)) {
String color = args.getString(0);
this.setThemeColor(color, callbackContext);
return true;
} else if ("getCurrentTheme".equals(action)) {
this.getCurrentTheme(callbackContext);
return true;
} else if ("registerThemeChangeListener".equals(action)) {
this.registerThemeChangeListener(callbackContext);
return true;
}
return false;
}
private void setThemeColor(String color, CallbackContext callbackContext) {
try {
AbilityContext context = (AbilityContext) cordova.getContext();
ResourceManager resourceManager = context.getResourceManager();
// 这里简化处理,实际应修改资源文件或使用动态资源管理
int colorValue = parseColor(color);
// 保存主题设置
saveThemePreference(color);
// 通知所有设备主题变更
notifyThemeChanged(color);
callbackContext.success(color);
} catch (Exception e) {
HiLog.error(LABEL, "setThemeColor error: " + e.getMessage());
callbackContext.error(e.getMessage());
}
}
private void getCurrentTheme(CallbackContext callbackContext) {
try {
String currentTheme = loadThemePreference();
callbackContext.success(currentTheme);
} catch (Exception e) {
callbackContext.error(e.getMessage());
}
}
private void registerThemeChangeListener(CallbackContext callbackContext) {
this.themeChangeCallback = callbackContext;
// 保持回调活跃
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
pluginResult.setKeepCallback(true);
callbackContext.sendPluginResult(pluginResult);
}
// 模拟U同步通知主题变更
private void notifyThemeChanged(String newColor) {
if (themeChangeCallback != null) {
PluginResult result = new PluginResult(PluginResult.Status.OK, newColor);
result.setKeepCallback(true);
themeChangeCallback.sendPluginResult(result);
}
}
// 解析颜色字符串
private int parseColor(String color) {
// 实现颜色解析逻辑
return 0; // 返回实际颜色值
}
// 保存主题偏好设置
private void saveThemePreference(String color) {
// 实现保存逻辑
}
// 加载主题偏好设置
private String loadThemePreference() {
// 实现加载逻辑
return "#FFFFFF"; // 默认返回白色
}
}
三、前端界面实现
创建一个简单的HTML界面来切换和显示主题:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>鸿蒙主题切换器</title>
<style>
body {
transition: background-color 0.3s ease;
padding: 20px;
}
.color-picker {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 20px 0;
}
.color-option {
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
border: 2px solid #eee;
}
.device-list {
margin-top: 30px;
}
.device-item {
padding: 10px;
margin: 5px 0;
background: #f5f5f5;
border-radius: 5px;
}
</style>
</head>
<body>
<h1>鸿蒙主题切换器</h1>
<div>
<h3>当前主题颜色: <span id="currentTheme">#FFFFFF</span></h3>
</div>
<div class="color-picker">
<div class="color-option" style="background: #FF5252;" data-color="#FF5252"></div>
<div class="color-option" style="background: #FF4081;" data-color="#FF4081"></div>
<div class="color-option" style="background: #E040FB;" data-color="#E040FB"></div>
<div class="color-option" style="background: #7C4DFF;" data-color="#7C4DFF"></div>
<div class="color-option" style="background: #536DFE;" data-color="#536DFE"></div>
<div class="color-option" style="background: #448AFF;" data-color="#448AFF"></div>
<div class="color-option" style="background: #40C4FF;" data-color="#40C4FF"></div>
<div class="color-option" style="background: #18FFFF;" data-color="#18FFFF"></div>
<div class="color-option" style="background: #64FFDA;" data-color="#64FFDA"></div>
<div class="color-option" style="background: #69F0AE;" data-color="#69F0AE"></div>
<div class="color-option" style="background: #B2FF59;" data-color="#B2FF59"></div>
<div class="color-option" style="background: #EEFF41;" data-color="#EEFF41"></div>
</div>
<div class="device-list">
<h3>已连接设备</h3>
<div id="devicesContainer">
<!-- 设备列表将通过JS动态生成 -->
</div>
</div>
<script src="cordova.js"></script>
<script>
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
console.log('Cordova已准备好');
// 获取当前主题
HarmonyThemeSwitcher.getCurrentTheme(
function(currentColor) {
document.getElementById('currentTheme').textContent = currentColor;
document.body.style.backgroundColor = currentColor;
},
function(error) {
console.error('获取当前主题失败:', error);
}
);
// 注册主题变更监听器
HarmonyThemeSwitcher.registerThemeChangeListener(function(newColor) {
document.getElementById('currentTheme').textContent = newColor;
document.body.style.backgroundColor = newColor;
console.log('主题已更新为:', newColor);
});
// 设置颜色选择器点击事件
const colorOptions = document.querySelectorAll('.color-option');
colorOptions.forEach(option => {
option.addEventListener('click', function() {
const color = this.getAttribute('data-color');
HarmonyThemeSwitcher.setThemeColor(
color,
function(success) {
console.log('主题颜色已设置为:', color);
},
function(error) {
console.error('设置主题颜色失败:', error);
}
);
});
});
// 模拟发现设备
simulateDeviceDiscovery();
}
// 模拟U同步设备发现
function simulateDeviceDiscovery() {
const devices = [
{ id: 'device1', name: '我的手机', theme: '#FFFFFF' },
{ id: 'device2', name: '我的平板', theme: '#FFFFFF' },
{ id: 'device3', name: '我的手表', theme: '#FFFFFF' }
];
const devicesContainer = document.getElementById('devicesContainer');
devicesContainer.innerHTML = '';
devices.forEach(device => {
const deviceElement = document.createElement('div');
deviceElement.className = 'device-item';
deviceElement.innerHTML = `
<h4>${device.name}</h4>
<p>主题颜色: <span class="device-theme">${device.theme}</span></p>
`;
devicesContainer.appendChild(deviceElement);
});
}
</script>
</body>
</html>
四、鸿蒙U同步实现多设备主题同步
为了实现类似游戏中多设备显示一致性的功能,我们需要利用鸿蒙的分布式能力来同步主题设置。
1. 修改HarmonyThemeSwitcher.java添加分布式能力
// 在HarmonyThemeSwitcher类中添加以下方法
private void setupDistributedDataSync() {
try {
AbilityContext context = (AbilityContext) cordova.getContext();
// 创建分布式数据管理器
DistributedDataManager distributedDataManager = DistributedDataManager.getInstance(context);
// 创建主题同步回调
DistributedDataManager.SyncCallback syncCallback = new DistributedDataManager.SyncCallback() {
@Override
public void onSyncCompleted(String deviceId, String key, SyncStatus status) {
if (status == SyncStatus.SUCCESS) {
HiLog.info(LABEL, "主题同步成功到设备: " + deviceId);
} else {
HiLog.warn(LABEL, "主题同步到设备 " + deviceId + " 失败");
}
}
};
// 注册主题同步
distributedDataManager.registerSyncCallback("app_theme_color", syncCallback);
} catch (Exception e) {
HiLog.error(LABEL, "设置分布式数据同步失败: " + e.getMessage());
}
}
private void syncThemeToAllDevices(String color) {
try {
AbilityContext context = (AbilityContext) cordova.getContext();
DistributedDataManager distributedDataManager = DistributedDataManager.getInstance(context);
// 将主题颜色同步到所有设备
distributedDataManager.putString("app_theme_color", color);
distributedDataManager.sync("app_theme_color", DistributedDataManager.SyncMode.PUSH);
} catch (Exception e) {
HiLog.error(LABEL, "同步主题到所有设备失败: " + e.getMessage());
}
}
// 在setThemeColor方法中调用同步
private void setThemeColor(String color, CallbackContext callbackContext) {
try {
// ...原有代码...
// 同步到所有设备
syncThemeToAllDevices(color);
callbackContext.success(color);
} catch (Exception e) {
HiLog.error(LABEL, "setThemeColor error: " + e.getMessage());
callbackContext.error(e.getMessage());
}
}
2. 添加设备发现和状态更新
// 在前端JavaScript中添加设备状态更新功能
function updateDeviceTheme(deviceId, themeColor) {
const devices = document.querySelectorAll('.device-item');
devices.forEach(device => {
if (device.dataset.id === deviceId) {
const themeSpan = device.querySelector('.device-theme');
if (themeSpan) {
themeSpan.textContent = themeColor;
device.style.backgroundColor = themeColor + '20'; // 添加透明度
}
}
});
}
// 模拟设备主题更新
function simulateDeviceThemeUpdates() {
const devices = [
{ id: 'device1', name: '我的手机' },
{ id: 'device2', name: '我的平板' },
{ id: 'device3', name: '我的手表' }
];
// 每隔一段时间随机更新一个设备的主题
setInterval(() => {
const randomDevice = devices[Math.floor(Math.random() * devices.length)];
const randomColor = '#' + Math.floor(Math.random()*16777215).toString(16);
updateDeviceTheme(randomDevice.id, randomColor);
}, 5000);
}
// 在onDeviceReady中调用
simulateDeviceThemeUpdates();
五、动态资源管理实现
为了实现真正的主题切换,我们需要在鸿蒙端实现动态资源管理:
1. 创建资源管理工具类
public class DynamicResourceManager {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, "DynamicResourceManager");
private static DynamicResourceManager instance;
private ResourceManager resourceManager;
private Map<String, Integer> dynamicColors = new HashMap<>();
private DynamicResourceManager(AbilityContext context) {
this.resourceManager = context.getResourceManager();
}
public static synchronized DynamicResourceManager getInstance(AbilityContext context) {
if (instance == null) {
instance = new DynamicResourceManager(context);
}
return instance;
}
public void addDynamicColor(String colorName, String colorValue) {
try {
int color = Color.parseColor(colorValue);
dynamicColors.put(colorName, color);
} catch (Exception e) {
HiLog.error(LABEL, "添加动态颜色失败: " + e.getMessage());
}
}
public int getColor(String colorName) {
if (dynamicColors.containsKey(colorName)) {
return dynamicColors.get(colorName);
}
try {
return resourceManager.getElement(colorName).getColor();
} catch (Exception e) {
HiLog.error(LABEL, "获取颜色资源失败: " + e.getMessage());
return 0; // 返回默认颜色
}
}
public void applyDynamicTheme() {
// 这里可以实现更复杂的主题应用逻辑
// 例如更新所有Activity的界面等
}
}
2. 修改插件使用动态资源
// 在HarmonyThemeSwitcher.java中修改setThemeColor方法
private void setThemeColor(String color, CallbackContext callbackContext) {
try {
AbilityContext context = (AbilityContext) cordova.getContext();
DynamicResourceManager drm = DynamicResourceManager.getInstance(context);
// 添加动态颜色
drm.addDynamicColor("primary_color", color);
drm.addDynamicColor("secondary_color", calculateSecondaryColor(color));
drm.applyDynamicTheme();
// 保存和同步
saveThemePreference(color);
syncThemeToAllDevices(color);
callbackContext.success(color);
} catch (Exception e) {
HiLog.error(LABEL, "setThemeColor error: " + e.getMessage());
callbackContext.error(e.getMessage());
}
}
private String calculateSecondaryColor(String primaryColor) {
// 实现计算辅助颜色的逻辑
return "#" + Integer.toHexString(Color.parseColor(primaryColor) & 0x00FFFFFF | 0x77000000);
}
六、总结与扩展
通过上述实现,我们创建了一个完整的鸿蒙主题切换器,具有以下特点:
- 跨平台能力:基于Cordova框架,可扩展至其他平台
- 动态主题切换:利用鸿蒙ResourceManager实现实时主题变更
- 多设备同步:借助鸿蒙分布式能力实现主题跨设备同步
- 可扩展性:可轻松添加更多主题属性和样式
进一步改进方向:
- 实现更复杂的主题系统,包括字体、间距等更多属性
- 添加主题持久化功能,记录用户偏好
- 优化分布式同步性能,减少网络开销
- 添加主题预览和自定义主题创建功能
这个实现展示了如何结合Cordova的跨平台能力和鸿蒙的原生特性,创造出既灵活又强大的应用功能。
更多推荐



所有评论(0)