鸿蒙版瑞幸咖啡开发日记(五)咖啡详情页逻辑实现

我们先来看一下总体的效果
在这里插入图片描述

1.逻辑归纳

其实咖啡详情页需要开发的逻辑也不是很多,总体写下来还是不叫轻松的。现将所有需要实现的逻辑归纳如下:

  • 咖啡详情页的名称由上一个Slice传递后获取
  • 温度和糖度选择后,底部的菜单栏随之更新
  • 菜单栏的总价需要根据前一个Slice传递的价格不同显示不同的总价
  • 当前咖啡种类数量的选择,当减到0时会有吐司弹框提示

2.开发流程

2.1 咖啡标题

由于咖啡标题是由上一个Slice设置的参数传递过来的,因此直接通过intent获取即可!
在这里插入图片描述
当intent不为空时,获取到咖啡标题和价格后更新到对应的组件中,这里我封装了loadCoffeeInfo方法用于加载咖啡的初始信息

// 加载咖啡的详情页信息
private void loadCoffeeInfo(String coffeeTitle){
    Text coffeeTitleTxt = (Text) findComponentById(ResourceTable.Id_coffee_title);
    coffeeTitleTxt.setText(coffeeTitle);

    Text priceTxt = (Text) findComponentById(ResourceTable.Id_buy_info);
    String[] info = priceTxt.getText().split("\\+");
    priceTxt.setText(coffeeTitle+"¥"+price+"+"+info[1]+"+"+info[2]);

    Text totalPrice = (Text) findComponentById(ResourceTable.Id_total_price);
    totalPrice.setText("¥"+price);
}

我们可以观察到这里除了对咖啡详情页的咖啡大标题进行更新 ,还需要对底部菜单栏中的咖啡标题进行更新

注:这里有一个地方需要注意一下

我们这里使用了正则表达式对菜单栏的口味选择进行了字符串分割,是以+分割的,所以正则表达式应该是"\\+"

2.2 温度和糖度选择

其实这里温度和糖度选择应该从后端拿到JSON数据,这里我为了简单就自己模仿了Luckin的两组数据,需要对温度和糖度的几个按钮组件件了事件监听

  • 通过列表存放所有的按钮,对每一个按钮进行事件监听
  • 将选中的按钮的字体和背景颜色进行修改【对其他的未被选中的也进行修改】
  • 将选中的按钮信息实时更新到底部的菜单栏【我这里是封装了一个方法updateMenu,只要进行了按钮点击就会调用】
    在这里插入图片描述
private String title;
private String temperature = "热";
private String sweet = "不另外加糖";
private Integer price;
private int totalNum = 1;

/**
 * 获取用户的温度选择和口味选择
 */
private void getCoffeeChoose(){
    ShapeElement selectElement = new ShapeElement();
    selectElement.setRgbColor(new RgbColor(235,237,249));
    selectElement.setCornerRadius(vp2px(8));

    ShapeElement unselectElement = new ShapeElement();
    unselectElement.setRgbColor(new RgbColor(255,255,255));


    List<Button> temperatureBtnList = new ArrayList<>();
    Button temperatureBtn = (Button) findComponentById(ResourceTable.Id_tem1);
    Button temperatureBtn2 = (Button) findComponentById(ResourceTable.Id_tem2);
    temperatureBtnList.add(temperatureBtn);
    temperatureBtnList.add(temperatureBtn2);
    for(Button tempBtn:temperatureBtnList){
        tempBtn.setClickedListener(component-> {
            temperature = temperatureBtn.getText();

            tempBtn.setBackground(selectElement);
            tempBtn.setTextColor(new Color(0xff242995));

            for (Button curButton1 : temperatureBtnList) {
                if (curButton1 != tempBtn) {
                    curButton1.setBackground(unselectElement);
                    curButton1.setTextColor(new Color(0xff6a6a6a));
                }
            }

            updateMenu();
        });
    }


    List<Button> sweetBtnList = new ArrayList<>();
    Button sweet1 = (Button) findComponentById(ResourceTable.Id_sweet1);
    Button sweet2 = (Button) findComponentById(ResourceTable.Id_sweet2);
    Button sweet3 = (Button) findComponentById(ResourceTable.Id_sweet3);
    sweetBtnList.add(sweet1);
    sweetBtnList.add(sweet2);
    sweetBtnList.add(sweet3);

    for(Button sweetBtn:sweetBtnList){
        sweetBtn.setClickedListener(component-> {
            sweet = sweetBtn.getText();

            sweetBtn.setBackground(selectElement);
            sweetBtn.setTextColor(new Color(0xff242995));

            for (Button curButton2 : sweetBtnList) {
                if (curButton2 != sweetBtn) {
                    curButton2.setBackground(unselectElement);
                    curButton2.setTextColor(new Color(0xff6a6a6a));
                }
            }

            updateMenu();
        });
    }

}


private int vp2px(int vp) {
    return AttrHelper.vp2px(vp, this);
}

/**
 * 更新购物车信息
 */
private void updateMenu(){
    Text priceTxt = (Text) findComponentById(ResourceTable.Id_buy_info);
    String[] info = priceTxt.getText().split("\\+");
    priceTxt.setText(info[0]+"+"+temperature+"¥0+"+sweet+"¥0");
}

这里有几个小技巧:

  1. 将vp转化为px,可以直接调用我封装好的方法【比如通过Java代码设置ShapceElement的圆角半径就需要px】
  2. 设置文本颜色时可以调用setTextColor(new Color(0xff242995));【里面必须传递Color对象,Color对象里面可以传递16进制的颜色(但是注意一下前面有两个ff),也可以直接使用封装好的COLOR.RED等】
  3. 对于未被选中的按钮我们使用了两层for循环判断当前点击的按钮是否是自身【这里我自己也思考过时间复杂度O(n^2)的问题,但是细细一想这里的n这么小,对时间复杂度几乎没有什么影响了】

2.3 数量选择

对于数量选择,对加和减两个图片设置点击监听事件,判断当前是否减为0,如果为0需要使用吐司弹框提示

// 加载咖啡的详情页信息
private void loadCoffeeInfo(String coffeeTitle){
	......

    // 获取已点数量
    Text txt_num = (Text) findComponentById(ResourceTable.Id_num2);

    //获取加减
    Component btn_minus = findComponentById(ResourceTable.Id_minus2);
    Component btn_add = findComponentById(ResourceTable.Id_add2);

    btn_add.setClickedListener(component -> {
        int num = Integer.parseInt(txt_num.getText()) + 1;
        txt_num.setText(num + "");
        totalNum = num;
    });

    btn_minus.setClickedListener(component -> {
        int num = Integer.parseInt(txt_num.getText());
        if (num == 1){
            ShowToastUtil.showToast(this,"再减就没有啦");
        }else{
            txt_num.setText(num - 1 + "");
            totalNum = num - 1;
        }
    });


    // TO DO...
    // 实际开发中应该需要根据MainSlice传过来的CoffeeId加载页面内容【如轮播图,内容详情】
}
package com.amx.luckin.utils;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.TextAlignment;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;

import static ohos.agp.components.ComponentContainer.LayoutConfig.MATCH_CONTENT;
import static ohos.agp.components.ComponentContainer.LayoutConfig.MATCH_PARENT;

public class ShowToastUtil {

    public static void showToast(Context context, String str) {

        // 创建文本组件
        Text text = new Text(context);
        text.setWidth(MATCH_CONTENT);
        text.setHeight(MATCH_CONTENT);
        text.setText(str); // 显示文本内容
        text.setTextSize(60); // 字号
        text.setPadding(30,10,30,10); // 内边距
        text.setMultipleLine(true); // 可多行显示文本内容
        text.setTextColor(Color.WHITE); // 文字颜色为白色
        text.setTextAlignment(TextAlignment.CENTER); // 居中显示
        // 文本组件使用灰色圆角背景
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(0x888888FF));
        element.setShape(ShapeElement.RECTANGLE);
        element.setCornerRadius(15); // 圆角半径
        text.setBackground(element);

        // 创建定向布局,并加入文本组件
        DirectionalLayout layout = new DirectionalLayout(context);
        layout.setWidth(MATCH_PARENT);
        layout.setHeight(MATCH_CONTENT);
        layout.setAlignment(LayoutAlignment.CENTER); // 居中内容
        layout.addComponent(text);

        // 创建Toast对话框
        ToastDialog toastDialog = new ToastDialog(context);
        toastDialog.setComponent(layout); // 使用自定义组件
        toastDialog
                .setTransparent(true) // 设置背景透明
                .setDuration(3000) // 显示时间 3000毫秒
                .setAlignment(LayoutAlignment.BOTTOM + LayoutAlignment.HORIZONTAL_CENTER) // 居中下方显示
                .setOffset(0, 60) // 距离底边距200px距离
                .show();
    }
}

2.4 结算后返回

当点击加入购物车后返回上一级Slice并携带结果
我们将前面设置的全局变量当做参数返回给上一个Slice,并通过setResult将intent返回,最终通过terminate关闭当前界面后返回

private void addChartNow(){
    Button addChartBtn = (Button) findComponentById(ResourceTable.Id_add_chart);
    addChartBtn.setClickedListener(component -> {
        Intent intent = new Intent();
        intent.setParam("price", price);
        intent.setParam("title", title);
        intent.setParam("temperature", temperature);
        intent.setParam("sweet", sweet);
        intent.setParam("totalNum", totalNum);
        setResult(intent);
        terminate();  // 关闭当前页面
    });
}

3.整体代码

package com.amx.luckin.slice;

import com.amx.luckin.ResourceTable;
import com.amx.luckin.provider.CoffeeImagePageSliderProvider;
import com.amx.luckin.utils.ShowToastUtil;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;


import java.util.ArrayList;
import java.util.List;

public class CoffeeDetailSlice extends AbilitySlice {

    private final int[] images = {
            ResourceTable.Media_lunbo2,
            ResourceTable.Media_lunbo4};

    private String title;
    private String temperature = "热";
    private String sweet = "不另外加糖";
    private Integer price;
    private int totalNum = 1;

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_coffee_detail);

        if (intent != null){
            title = (String) intent.getParams().getParam("coffeeTitle");
            price = (Integer) intent.getParams().getParam("coffeePrice");
            loadCoffeeInfo(title);
        }

        loadPageSlider();  // 加载轮播图
        getCoffeeChoose(); // 获取咖啡选择

        addChartNow(); // 加入购物车

    }

    // 加载咖啡的详情页信息
    private void loadCoffeeInfo(String coffeeTitle){
        Text coffeeTitleTxt = (Text) findComponentById(ResourceTable.Id_coffee_title);
        coffeeTitleTxt.setText(coffeeTitle);

        Text priceTxt = (Text) findComponentById(ResourceTable.Id_buy_info);
        String[] info = priceTxt.getText().split("\\+");
        priceTxt.setText(coffeeTitle+"¥"+price+"+"+info[1]+"+"+info[2]);

        Text totalPrice = (Text) findComponentById(ResourceTable.Id_total_price);
        totalPrice.setText("¥"+price);

        // 获取已点数量
        Text txt_num = (Text) findComponentById(ResourceTable.Id_num2);

        //获取加减
        Component btn_minus = findComponentById(ResourceTable.Id_minus2);
        Component btn_add = findComponentById(ResourceTable.Id_add2);

        btn_add.setClickedListener(component -> {
            int num = Integer.parseInt(txt_num.getText()) + 1;
            txt_num.setText(num + "");
            totalNum = num;
        });

        btn_minus.setClickedListener(component -> {
            int num = Integer.parseInt(txt_num.getText());
            if (num == 1){
                ShowToastUtil.showToast(this,"再减就没有啦");
            }else{
                txt_num.setText(num - 1 + "");
                totalNum = num - 1;
            }
        });


        // TO DO...
        // 实际开发中应该需要根据MainSlice传过来的CoffeeId加载页面内容【如轮播图,内容详情】
    }


    // 加载轮播图组件PageSlider
    private void loadPageSlider(){
        //根据id获得滑动页面组件对象
        PageSlider ps = (PageSlider) this.findComponentById(ResourceTable.Id_coffee_detail_pageSlider);
        //创建适配器对象,将当前界面对象和封装好的集合发送过去
        CoffeeImagePageSliderProvider coffeeDetailImageProvider = new CoffeeImagePageSliderProvider(initPage(), this);
        //将适配器加载至滑动组件上,完成同步组装
        ps.setProvider(coffeeDetailImageProvider);
    }

    /**
     * 获取用户的温度选择和口味选择
     */
    private void getCoffeeChoose(){
        ShapeElement selectElement = new ShapeElement();
        selectElement.setRgbColor(new RgbColor(235,237,249));
        selectElement.setCornerRadius(vp2px(8));

        ShapeElement unselectElement = new ShapeElement();
        unselectElement.setRgbColor(new RgbColor(255,255,255));


        List<Button> temperatureBtnList = new ArrayList<>();
        Button temperatureBtn = (Button) findComponentById(ResourceTable.Id_tem1);
        Button temperatureBtn2 = (Button) findComponentById(ResourceTable.Id_tem2);
        temperatureBtnList.add(temperatureBtn);
        temperatureBtnList.add(temperatureBtn2);
        for(Button tempBtn:temperatureBtnList){
            tempBtn.setClickedListener(component-> {
                temperature = temperatureBtn.getText();

                tempBtn.setBackground(selectElement);
                tempBtn.setTextColor(new Color(0xff242995));

                for (Button curButton1 : temperatureBtnList) {
                    if (curButton1 != tempBtn) {
                        curButton1.setBackground(unselectElement);
                        curButton1.setTextColor(new Color(0xff6a6a6a));
                    }
                }

                updateMenu();
            });
        }


        List<Button> sweetBtnList = new ArrayList<>();
        Button sweet1 = (Button) findComponentById(ResourceTable.Id_sweet1);
        Button sweet2 = (Button) findComponentById(ResourceTable.Id_sweet2);
        Button sweet3 = (Button) findComponentById(ResourceTable.Id_sweet3);
        sweetBtnList.add(sweet1);
        sweetBtnList.add(sweet2);
        sweetBtnList.add(sweet3);

        for(Button sweetBtn:sweetBtnList){
            sweetBtn.setClickedListener(component-> {
                sweet = sweetBtn.getText();

                sweetBtn.setBackground(selectElement);
                sweetBtn.setTextColor(new Color(0xff242995));

                for (Button curButton2 : sweetBtnList) {
                    if (curButton2 != sweetBtn) {
                        curButton2.setBackground(unselectElement);
                        curButton2.setTextColor(new Color(0xff6a6a6a));
                    }
                }

                updateMenu();
            });
        }

    }

    private int fp2px(int fp) {
        return AttrHelper.fp2px(fp, this);
    }

    private int vp2px(int vp) {
        return AttrHelper.vp2px(vp, this);
    }

    /**
     * 更新购物车信息
     */
    private void updateMenu(){
        Text priceTxt = (Text) findComponentById(ResourceTable.Id_buy_info);
        String[] info = priceTxt.getText().split("\\+");
        priceTxt.setText(info[0]+"+"+temperature+"¥0+"+sweet+"¥0");
    }

    private void addChartNow(){
        Button addChartBtn = (Button) findComponentById(ResourceTable.Id_add_chart);
        addChartBtn.setClickedListener(component -> {
            Intent intent = new Intent();
            intent.setParam("price", price);
            intent.setParam("title", title);
            intent.setParam("temperature", temperature);
            intent.setParam("sweet", sweet);
            intent.setParam("totalNum", totalNum);
            setResult(intent);
            terminate();  // 关闭当前页面
        });
    }

    private List<Integer> initPage() {
        List<Integer> imagesArray = new ArrayList<>();
        for (int image : images) {
            imagesArray.add(image);
        }
        return imagesArray;
    }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值