首先我们来看一下最终的实现效果【添加不同的咖啡后,自动更新价格和数量,并且添加到首页底部的已点菜单栏中】
1.需实现的功能总结
- 点击
加入购物车 后,首页对应的咖啡右边的数量进行更新,并且底部菜单栏中的总数量进行更新 - 实时计算所有已点咖啡的预计到手价格
- 将所有的已点咖啡展示在底部菜单栏中,点击后显示,再次点击后隐藏【当然这里还需要隐藏配送费6元,再买24.6…】
2.详细功能开发
2.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>
- 将详情页的信息渲染到模板中
当我们在详情页点击添加购物车 后,需要将已点咖啡添加到菜单栏中,其实这里的逻辑还是比较复杂的,主要是要对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);
}
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 即可】
|