#夏日挑战赛#鸿蒙FA开发之JSUI与JavaUI相互跳转实例 原创 精华

软通动力HOS
发布于 2022-6-14 11:49
浏览
10收藏

本文正在参加星光计划3.0–夏日挑战赛

需求背景说明

鸿蒙官方推荐使用Js或eTS方式来开发APP应用UI,但在开发过程中有可能会遇到JSUI无法实现的功能,例如地图导航、定制化视频播放器,那么这种场景下如何实现功能,这个需求就带来如下问题:
1.一个页面是否能同时使用JavaUI和JSUI,JSUI来实现简单功能,JavaUI来实现定制化功能
2.一个工程是否支持不同的UI语法,比如PageA使用JSUI,PageB使用JavaUI
带着问题我们来回顾一下鸿蒙开发支持的UI开发方式

1. Java UI

使用xml方式描述UI界面布局,应用中所有的用户界面元素都是由Component和ComponentContainer对象构成。Component是绘制在屏幕上的一个对象,用户能与之交互。ComponentContainer是一个用于容纳其他Component和ComponentContainer对象的容器。Java UI框架提供了一部分Component和ComponentContainer的具体子类,即创建用户界面(UI)的各类组件,包括一些常用的组件(比如:文本、按钮、图片、列表等)和常用的布局(比如:DirectionalLayout和DependentLayout)。用户可通过组件进行交互操作,并获得响应。
#夏日挑战赛#鸿蒙FA开发之JSUI与JavaUI相互跳转实例-鸿蒙开发者社区

2. JS UI

基于JS扩展的类Web开发范式的方舟开发框架是一种跨设备的高性能UI开发框架,支持声明式编程和跨设备多态UI。 采用类HTML和CSS Web编程语言作为页面布局和页面样式的开发语言,页面业务逻辑则支持ECMAScript规范的JavaScript语言。方舟开发框架提供的类Web编程范式,可以让开发者避免编写UI状态切换的代码,视图配置信息更加直观
#夏日挑战赛#鸿蒙FA开发之JSUI与JavaUI相互跳转实例-鸿蒙开发者社区

3. eTS UI

使用基于TS扩展的声明式开发范式的方舟开发框架,采用更接近自然语义的编程方式,让开发者可以直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,实现极简高效开发。从组件、动效和状态管理三个维度来提供UI能力,还提供了系统能力接口,实现系统能力的极简调用。
#夏日挑战赛#鸿蒙FA开发之JSUI与JavaUI相互跳转实例-鸿蒙开发者社区
根据Ability的分类来考虑,JsUI继承自AceAbility,而JavaUI使用xml方式进行渲染,它继承自Ability,所以在同一界面上使用两个语言在页面渲染器就已经决定了,JavaUI和JSUI不能在同一Page中使用。
那么问题2是否可行呢,答案是可以的。因为PageA和PageB可以用2个不同的Ability来渲染实现。
需要实现PageA是应用主页面,使用JSUI实现,PageA上有个按钮跳转到PageB,PageB展示地图导航页面,PageB使用JavaUI实现
如图:
#夏日挑战赛#鸿蒙FA开发之JSUI与JavaUI相互跳转实例-鸿蒙开发者社区
JSUI自带有router功能,可以通过router.push进行跳转,但这仅限于JSUI的不通页面,对于上述场景行不通
那么只能使用ability的startAbility能力来实现不同ability之前的跳转
使用AceInternalAbility来接收页面的跳转请求,然后通过ability的startAbility方法跳转到另一个ability,流程图如下:
#夏日挑战赛#鸿蒙FA开发之JSUI与JavaUI相互跳转实例-鸿蒙开发者社区

代码实现

MainAbility.java

    @Override
    public void onStart(Intent intent) {
               ……
               // 注册AceInternalAbility,接收首页按钮请求
        TransInternalAbility.getInstance().register(this);
        super.onStart(intent);
    }
}

TransInternalAbility.java

    private static final String BUNDLE_NAME = "cn.pmagroup.ble.pmap30";
    private static final String MAP_ABILITY_NAME = "cn.pmagroup.ble.pmap30.ability.MapAbility";
    private static final String ABILITY_NAME = "cn.pmagroup.ble.pmap30.ability.TransInternalAbility";
    private static final int SUCCESS = 0;
    private static final int ERROR = 1;
    private static final int PULL_MAP_PAGE = 1001;
    // 定义日志标签
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, "MY_TAG");
    private static TransInternalAbility instance;
    private Ability ability;
    private TransInternalAbility() {
        super(BUNDLE_NAME, ABILITY_NAME);
    }
    public static TransInternalAbility getInstance() {
        if (instance == null) {
            synchronized (TransInternalAbility.class) {
                if (instance == null) {
                    instance = new TransInternalAbility();
                }
            }
        }
        return instance;
    }
    public static void register(Ability ability) {
        HiLog.info(LABEL, "DataHandlerAbility: register");
        if (ability == null) {
            HiLog.info(LABEL, "register abilityContext is null");
        } else {
            HiLog.info(LABEL, "register " + ability.getBundleName());
            if (instance == null) {
                instance = new TransInternalAbility();
            }
            instance.onRegister(ability);
        }
    }
    /**
     * init Internal ability
     */
    public void onRegister(Ability ability) {
        this.ability = ability;
        this.setInternalAbilityHandler(this::onRemoteRequest);
    }
    private boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
        HiLog.info(LABEL, "DataHandlerAbility: onRemoteRequest");
        String dataString = data.readString();
        switch (code) {
            case PULL_MAP_PAGE: {
                reply.writeString("{ code: 0 }");
                // 拉起地图导航JavaUI ability
                this.pullMapPage();
                break;
            }
            default: {
                reply.writeString("service not defined");
                return false;
            }
        }
        return true;
    }
    // 拉起地图导航JavaUI ability
    private void pullMapPage() {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder().withBundleName(BUNDLE_NAME)
                .withAbilityName(MAP_ABILITY_NAME).build();
        intent.setOperation(operation);
        this.ability.startAbilityForResult(intent, PULL_MAP_PAGE);
    }
}

MapAbility.java

    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, "MAP_ABILITY");
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(MapAbilitySlice.class.getName());
    }
}

MapAbilitySlice.java

    private static final int TOAST_DURATION = 3500;
    private static final String BUNDLE_NAME = "cn.pmagroup.ble.pmap30";
    private static final String CONTROL_ABILITY = "cn.pmagroup.ble.pmap30.ability.MainAbility";
    private static final int VP2PX_VALUE = 64;
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, "MAP_ABILITY_SLICE");
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_map_ability);
        this.initComponents();
    }
    private void initComponents() {
        Button btnGoBack = (Button) findComponentById(ResourceTable.Id_btn_goBack);
        ShapeElement background = new ShapeElement();
        background.setRgbColor(new RgbColor(0, 125, 255));
        background.setCornerRadius(25);
        btnGoBack.setBackground(background);
        // 在组件中增加对点击事件的检测
        btnGoBack.setClickedListener(component -> {
            // 此处添加按钮被点击需要执行的操作
            LogUtil.debug("JavaUI", "btnGoBack click");
            this.showToast(this, "返回控制页面");
            this.goBack2ControlPage();
        });
    }
    private void goBack2ControlPage() {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder().withBundleName(BUNDLE_NAME)
                .withAbilityName(CONTROL_ABILITY).build();
        intent.setOperation(operation);
        startAbility(intent);
    }
    @Override
    public void onActive() {
        super.onActive();
    }


    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}

map_ability.xml(Layout文件)

<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:alignment="center"
    ohos:orientation="vertical">
    <Text
        ohos:id="$+id:text_helloworld"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$graphic:background_ability_test"
        ohos:layout_alignment="horizontal_center"
        ohos:text="$string:testability_HelloWorld"
        ohos:text_size="40vp"
        />
    <Button
        ohos:id="$+id:btn_goBack"
        ohos:height="40vp"
        ohos:width="match_parent"
        ohos:text="返回"
        ohos:text_size="20vp"
        ohos:focus_border_enable="true"
        />
</DirectionalLayout>

更多原创内容请关注软通动力OpenHarmony学院

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
10
收藏 10
回复
举报
4条回复
按时间正序
/
按时间倒序
芒果爱学习
芒果爱学习

感谢分享

回复
2022-6-14 14:13:45
粉粉gg
粉粉gg

干货满满,感谢分享

回复
2022-6-14 14:16:07
软通小精灵
软通小精灵

感谢大家对软通的支持

1
回复
2022-6-14 14:17:54
芳芳爱学习
芳芳爱学习

感谢老师分享

回复
2022-6-15 14:15:20
回复
    相关推荐