鸿蒙版瑞幸咖啡开发日记(六)详情页与首页联动

首先我们来看一下最终的实现效果【添加不同的咖啡后,自动更新价格和数量,并且添加到首页底部的已点菜单栏中】
在这里插入图片描述

1.需实现的功能总结

  • 点击加入购物车后,首页对应的咖啡右边的数量进行更新,并且底部菜单栏中的总数量进行更新
  • 实时计算所有已点咖啡的预计到手价格
  • 将所有的已点咖啡展示在底部菜单栏中,点击后显示,再次点击后隐藏【当然这里还需要隐藏配送费6元,再买24.6…

2.详细功能开发

2.1 添加已点咖啡到菜单栏

  1. 首先我们编写菜单栏中的已点咖啡的模板文件template_ordered.xml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="110vp"
    ohos:width="match_parent"
    ohos:orientation="horizontal">

    <Image
        ohos:left_margin="15vp"
        ohos:layout_alignment="vertical_center"
        ohos:height="20vp"
        ohos:width="20vp"
        ohos:image_src="$media:choose"
        ohos:scale_mode="zoom_center"
        ohos:clip_alignment="center"/>

    <Image
        ohos:left_margin="20vp"
        ohos:id="$+id:coffee_img"
        ohos:height="90vp"
        ohos:width="90vp"
        ohos:image_src="$media:coffee1"
        ohos:scale_mode="stretch"
        ohos:clip_alignment="center"
        ohos:layout_alignment="center"/>

    <DirectionalLayout
        ohos:left_margin="14vp"
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:orientation="vertical">

        <Text
            ohos:top_margin="5vp"
            ohos:id="$+id:coffee_title"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:text="厚乳拿铁"
            ohos:text_color="#313131"
            ohos:text_size="20fp"
            ohos:text_alignment="center"/>

        <Text
            ohos:id="$+id:coffee_taste"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:text="热/不另外加糖"
            ohos:text_color="#313131"
            ohos:text_size="12fp"
            ohos:text_alignment="center"/>

        <DirectionalLayout
            ohos:height="26vp"
            ohos:width="match_parent"
            ohos:top_margin="28vp"
            ohos:orientation="horizontal">

            <Text
                ohos:id="$+id:coffee_price"
                ohos:height="match_content"
                ohos:width="match_content"
                ohos:text="¥16"
                ohos:text_color="#dd5810"
                ohos:text_size="18fp"
                ohos:text_alignment="center"/>

            <DirectionalLayout
                ohos:height="match_parent"
                ohos:width="match_parent"
                ohos:alignment="right"
                ohos:orientation="horizontal">

                <Image
                    ohos:height="32vp"
                    ohos:width="32vp"
                    ohos:image_src="$media:minus"
                    ohos:layout_alignment="vertical_center"
                    ohos:padding="5vp"
                    ohos:scale_mode="stretch"/>

                <Text
                    ohos:id="$+id:coffee_num"
                    ohos:height="match_content"
                    ohos:width="match_content"
                    ohos:left_margin="2vp"
                    ohos:right_margin="2vp"
                    ohos:text="1"
                    ohos:text_alignment="vertical_center"
                    ohos:text_size="20fp"/>

                <Image
                    ohos:height="32vp"
                    ohos:width="32vp"
                    ohos:image_src="$media:plus"
                    ohos:layout_alignment="vertical_center"
                    ohos:padding="5vp"
                    ohos:scale_mode="stretch"/>
            </DirectionalLayout>
        </DirectionalLayout>
    </DirectionalLayout>
</DirectionalLayout>
  1. 将详情页的信息渲染到模板中

当我们在详情页点击添加购物车后,需要将已点咖啡添加到菜单栏中,其实这里的逻辑还是比较复杂的,主要是要对PageSlice的生命周期有一定的基础,不然无从下手,大家可以先思考一下,你拿到回调的信息后如何渲染到已点咖啡的模板中!
在这里插入图片描述

可能你会想为什么不能在回调方法onResult中渲染模板,你可以尝试一下,是不行的,因为这里我们无法获取模板中的组件【比如说通过findComponentById获得组件】,只能对模板中的信息进行修改更新。所以我们另辟蹊径,通过pageSlice的生命周期渲染模板
【如图所示:我们如何渲染模板呢?】
在这里插入图片描述
我们知道:

  • 常见的生命周期中加载界面为onStart(第一次) → onActive
  • 当我们从两一个界面切回到当前界面时生命周期为 onForeground → onActive
  • 那么添加了回调方法onResult后,为onResult→ onForeground → onActive
    在这里插入图片描述
    因此,我们可以在onResult方法中获取到回调信息,在onForeground中对模板信息进行渲染
@Override
public void onForeground(Intent intent) {
    super.onForeground(intent);
    
    // 更新每一个咖啡后面紧跟的咖啡数量
    DirectionalLayout curCoffee = everyCoffee.get(curClickCoffee);
    Text textNum = (Text) curCoffee.findComponentById(ResourceTable.Id_num);
    int num = Integer.parseInt(textNum.getText()) + totalNum;
    textNum.setText(num + "");

    // 更新总数量
    int curTotalNum = Integer.parseInt(txt_totalNum.getText());
    txt_totalNum.setText(curTotalNum + totalNum + "");

    // 更新当前总价
    countCartPrice(totalNum * price,true);

    // 加载已点咖啡到核算栏
    if (!isCoffeeExist.contains(title)){
        initCoffeeOrder();
        isCoffeeExist.add(title);
    }else{
        updateCoffeeOrder(true);
    }
}

// 计算已点菜单价格
private void countCartPrice(int price, boolean isadd) {
    int total = Integer.parseInt(txt_price.getText().substring(1));
    if (isadd) {
        total = total + price;
    } else {
        total = total - price;
    }
    txt_price.setText("¥"+total);
}

private void initCoffeeOrder(){
    DirectionalLayout tempOrder = (DirectionalLayout) LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_template_ordered, null, false);
    Text tempTitle = (Text) tempOrder.findComponentById(ResourceTable.Id_coffee_title);
    Text tempPrice = (Text) tempOrder.findComponentById(ResourceTable.Id_coffee_price);
    Text tempTaste = (Text) tempOrder.findComponentById(ResourceTable.Id_coffee_taste);
    Text tempNum = (Text) tempOrder.findComponentById(ResourceTable.Id_coffee_num);

    getUITaskDispatcher().asyncDispatch(() -> {
        tempTitle.setText(title);
        tempPrice.setText("¥"+price);
        tempTaste.setText(temperature+"/"+sweet);
        tempNum.setText(totalNum + "");
        coffeeOrdered.addComponent(tempOrder);
    });

    tempOrderCoffee.put(curClickCoffee, tempOrder);
}

/**
 * 更新 底部的已点咖啡
 * @param isAdd:判断是否点击的是添加按钮
 */
private void updateCoffeeOrder(boolean isAdd){
    DirectionalLayout curClickOrderCoffee = tempOrderCoffee.get(curClickCoffee);
    Text tempNum = (Text) curClickOrderCoffee.findComponentById(ResourceTable.Id_coffee_num);
    int num = Integer.parseInt(tempNum.getText());
    if (isAdd){
        tempNum.setText(num + totalNum + "");
    } else {
        tempNum.setText(num - 1 + "");
    }
}

我们观察一下,做了哪些事:

  • 更新首页中每一个咖啡后面的数量信息【用原来的数量 + 回调信息中的数量】
  • 更新菜单栏中的总数量【用原来的数量 + 回调信息中的数量】
  • 更新当前的预计到手总价【用原来的总价 + 回调信息中的数量 * 回调信息中的单价】
  • 加载加载已点咖啡到核算栏,但是这里又有个小细节
    • 当我们这一类咖啡已经点过了,我们只更新已点咖啡的数量【包括首页中的底部菜单栏中的
    • 当我们第一次点这类咖啡,我们渲染模板后添加到容器中
    • 所以这里我使用了一个HashSet作为容器,用咖啡的名称作为判断的哈希依据
  • 这里还有一个细节,不知道大家注意没有!!!就是我们如何准确获取到每一个首页中的咖啡,对其右侧数量进行更新

我是使用了一个List作为容器,直接获取当前列表中的点击的第curClickCoffee个咖啡模板
在这里插入图片描述
包括,底部的菜单中的已点咖啡我们也用一个HashMap容器进行包裹
在这里插入图片描述
在这里插入图片描述
我们再重新回过头来看,这不是一切都清晰明了了!当我们需要更新模板中的信息时,只要根据 curClickCoffee 获取当前点击的模板,然后对其中表示数量的文本组进行数量更新

2.2 已点咖啡是否展示

我们平时使用APP时,可以点击核算栏【菜单栏】后会展示详细我们已点的咖啡,就是2.1节我们渲染的模板,再次点击后会隐藏

 // 显示所有的已点咖啡
 private void showCartCoffee(){
     Component cartDL = findComponentById(ResourceTable.Id_cart_dl);
     Component coffeeOrder = findComponentById(ResourceTable.Id_coffee_order);
     Component discount =findComponentById(ResourceTable.Id_discount_txt);
     cartDL.setClickedListener(component -> {
         if (!isShowCoffeeMenu){
             discount.setVisibility(Component.HIDE);
             coffeeOrder.setVisibility(Component.VISIBLE);
             cartDL.setMarginTop(vp2px(28));
             isShowCoffeeMenu = !isShowCoffeeMenu;
         }else {
             discount.setVisibility(Component.VISIBLE);
             coffeeOrder.setVisibility(Component.HIDE);
             isShowCoffeeMenu = !isShowCoffeeMenu;
             cartDL.setMarginTop(0);
         }
     });
 }

这里又有细节哦,我们点击显示已点开发后,中间的优惠信息会被隐藏,这时候需要我们cartDL.setMarginTop(vp2px(28))设置一个边距,不然下面的信息会跑上去【因为文本被隐藏了】,再次点击后我们重新显示优惠信息,将已点咖啡隐藏……中间的一切通过一个boolean变量控制是否显示已点咖啡

2.3 陷阱提示

我们回想喝多种品类的咖啡,因此我们点击首页不同的咖啡 右边对应的+按钮时,会发现上一次点击的咖啡温度和糖度,以及数量会被保存下来!这是一个小Bug,当时我思考了很久为什么?我们可以看一下这个Bug!!
在这里插入图片描述
添加第二类咖啡的时候,温度、糖度和数量都没被重置!

这里因为回调的时候虽然使用了terminate销毁了当前界面,但是我们使用setText设置的文本信息已经被保存在了xml文件中,换句话说我们xml文件中的文本已经变成了你点击后的值,并不会在下一次重新点击后重新换回来,我们重新加载slice,只是加载了xml文件;【但是你的xml文件已经被改动过了对吧!】

考虑到用户可能会喜欢统一的温度和糖度,所以这两个不更改,只对已点数量进行修改【因为调用terminate会自动调用onStop销毁页面,所以我们直接通过生命周期的onStop方法在每一次销毁前,将已点数量恢复到 1 即可】
在这里插入图片描述

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值