Logic implementation of coffee detail page of Hongmeng Ruixing coffee development diary

Let's first look at the overall effect

1. Logical induction

In fact, there is not much logic to develop in the coffee details page, and it is not easy to write it down as a whole. The logic to be realized is summarized as follows:

  • The name of the coffee details page is obtained after the previous Slice is passed
  • When the temperature and sugar content are selected, the menu bar at the bottom is updated
  • The total price of the menu bar needs to display different total prices according to the prices passed by the previous Slice
  • For the selection of current coffee type and quantity, when it is reduced to 0, there will be a toast pop-up prompt

2. Development process

2.1 coffee title

Since the coffee title is passed from the parameters set by the previous Slice, you can get it directly through intent!

When intent is not empty, get the coffee title and price and update them to the corresponding component. Here I encapsulate the loadcoffee info method to load the initial information of coffee

// Load coffee details page information
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);
}

We can see that in addition to updating the coffee title on the coffee details page, we also need to update the coffee title in the menu bar at the bottom

Note: here is a place to pay attention to

Here, we use regular expression to segment the string for the taste selection of the menu bar, which is divided by +. Therefore, the regular expression should be "\ \ +"

2.2 selection of temperature and sugar content

In fact, the JSON data should be obtained from the back-end for the selection of temperature and sugar content. Here, in order to simply imitate the two groups of data of Luckin, I need to monitor the events of several button components of temperature and sugar content

  • Store all the buttons in the list and listen to the events of each button
  • Modify the font and background color of the selected button [also modify other unselected buttons]
  • Update the selected button information to the bottom menu bar in real time [I encapsulate a method updateMenu here, which will be called as long as the button is clicked]
private String title;
private String temperature = "heat";
private String sweet = "No extra sugar";
private Integer price;
private int totalNum = 1;

/**
 * Get the user's temperature selection and taste selection
 */
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);
}

/**
 * Update shopping cart information
 */
private void updateMenu(){
    Text priceTxt = (Text) findComponentById(ResourceTable.Id_buy_info);
    String[] info = priceTxt.getText().split("\\+");
    priceTxt.setText(info[0]+"+"+temperature+"¥0+"+sweet+"¥0");
}

Here are some tips:

  1. To convert vp to px, you can directly call my encapsulated method [for example, px is required to set the fillet radius of ShapceElement through Java code]
  2. When setting the text Color, you can call setTextColor(new Color(0xff242995)); [Color object must be passed inside. Hexadecimal Color can be passed inside the Color object (but note that there are two FF in front), or encapsulated COLOR.RED can be used directly]
  3. For the unselected button, we use a two-layer for loop to judge whether the button currently clicked is itself [here I have also thought about the time complexity O(n^2), but when I think about it carefully, the N here is so small that it has little impact on the time complexity]

2.3 quantity selection

For the quantity selection, set the click monitoring event for the plus and minus pictures, and judge whether it is reduced to 0. If it is 0, you need to use the toast pop-up prompt

// Load coffee details page information
private void loadCoffeeInfo(String coffeeTitle){
	......

    // Get the number of points
    Text txt_num = (Text) findComponentById(ResourceTable.Id_num2);

    //Get addition and subtraction
    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,"No more");
        }else{
            txt_num.setText(num - 1 + "");
            totalNum = num - 1;
        }
    });


    // TO DO...
    // In the actual development, the page content should be loaded according to the CoffeeId transmitted by MainSlice [such as the rotation diagram, content details]
}
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) {

        // Create text component
        Text text = new Text(context);
        text.setWidth(MATCH_CONTENT);
        text.setHeight(MATCH_CONTENT);
        text.setText(str); // Display text content
        text.setTextSize(60); // Font size
        text.setPadding(30,10,30,10); // padding 
        text.setMultipleLine(true); // Text content can be displayed in multiple lines
        text.setTextColor(Color.WHITE); // The text color is white
        text.setTextAlignment(TextAlignment.CENTER); // Center display
        // Text components use a gray rounded background
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(0x888888FF));
        element.setShape(ShapeElement.RECTANGLE);
        element.setCornerRadius(15); // Fillet radius
        text.setBackground(element);

        // Create an oriented layout and add text components
        DirectionalLayout layout = new DirectionalLayout(context);
        layout.setWidth(MATCH_PARENT);
        layout.setHeight(MATCH_CONTENT);
        layout.setAlignment(LayoutAlignment.CENTER); // Centered content
        layout.addComponent(text);

        // Create Toast dialog box
        ToastDialog toastDialog = new ToastDialog(context);
        toastDialog.setComponent(layout); // Using custom components
        toastDialog
                .setTransparent(true) // Set background transparency
                .setDuration(3000) // Display time 3000 ms
                .setAlignment(LayoutAlignment.BOTTOM + LayoutAlignment.HORIZONTAL_CENTER) // Show below center
                .setOffset(0, 60) // 200px distance from bottom edge
                .show();
    }
}

2.4 return after settlement

When you click Add to the shopping cart, return to the previous Slice and carry the results
We return the previously set global variable as a parameter to the previous Slice, return intent through setResult, and finally close the current interface through 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();  // Close current page
    });
}

3. Overall code

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 = "heat";
    private String sweet = "No extra sugar";
    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();  // Load the carousel map
        getCoffeeChoose(); // Get coffee selection

        addChartNow(); // add to cart

    }

    // Load coffee details page information
    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);

        // Get the number of points
        Text txt_num = (Text) findComponentById(ResourceTable.Id_num2);

        //Get addition and subtraction
        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,"No more");
            }else{
                txt_num.setText(num - 1 + "");
                totalNum = num - 1;
            }
        });


        // TO DO...
        // In the actual development, the page content should be loaded according to the CoffeeId transmitted by MainSlice [such as the rotation diagram, content details]
    }


    // Load the rotation chart component PageSlider
    private void loadPageSlider(){
        //Get the sliding page component object according to the id
        PageSlider ps = (PageSlider) this.findComponentById(ResourceTable.Id_coffee_detail_pageSlider);
        //Create an adapter object and send the current interface object and the encapsulated collection
        CoffeeImagePageSliderProvider coffeeDetailImageProvider = new CoffeeImagePageSliderProvider(initPage(), this);
        //Load the adapter onto the sliding assembly to complete the synchronous assembly
        ps.setProvider(coffeeDetailImageProvider);
    }

    /**
     * Get the user's temperature selection and taste selection
     */
    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);
    }

    /**
     * Update shopping cart information
     */
    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();  // Close current page
        });
    }

    private List<Integer> initPage() {
        List<Integer> imagesArray = new ArrayList<>();
        for (int image : images) {
            imagesArray.add(image);
        }
        return imagesArray;
    }
}

Keywords: harmonyos

Added by getmizanur on Tue, 15 Feb 2022 07:16:53 +0200