鸿蒙版瑞幸咖啡开发日记之咖啡详情页
这里我们首先看一下最终的效果图,几乎与原版是一样的,有一点点小小的区别在于顶部轮播图小圆点的切换。
1.整体布局思路
- 首先除顶部外,其余部分均采用了ScrollView进行展示,因为用户需要向下拖动查看内容
- 其次由于底部结算栏是一直固定在底部的,所以整体布局我是使用了相对布局
DependentLayout
进行布局,由中间滑动界面Scrollview和底部结算栏DirectionLayout组成
2.具体开发流程
我打算从整体思路为基点,阐述具体的开发流程,因此从中间滑动内容和底部结算栏分别进行描述。
2.1 中间滑动内容
2.1.1 顶部轮播图的开发
从演示内容来看,顶部是一个轮播图,图片是我在网上随便找的哈,你也根据自己的喜好自己更改哦【彩蛋:最近是情人节,所以我喝了瑞幸的狠狠爱你可可鸳鸯】
轮播图可以通过鸿蒙提供的PageSlider
进行开发:
- 首先构造轮播图的图片模板文件
template_coffee_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="230vp"
ohos:width="match_parent"
ohos:orientation="vertical">
<Image
ohos:id="$+id:coffee_image"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:scale_mode="stretch"
ohos:clip_alignment="center"/>
</DirectionalLayout>
- 由于PageSlider需要我们进行适配,所以我们需要构造自己的适配器
CoffeeImagePageSliderProvider
【这里可以去看官方文档:鸿蒙PageSlider组件】
当然,你也可以看完我的PageSlider开发流程,再给你总结一个脑图,亲妈教学一步到位(#^ . ^#)
public class CoffeeImagePageSliderProvider extends PageSliderProvider {
private List<Integer> images;
private AbilitySlice abilitySlice;
public CoffeeImagePageSliderProvider(List<Integer> images, AbilitySlice abilitySlice) {
this.images = images;
this.abilitySlice = abilitySlice;
}
@Override
public int getCount() {
return images.size();
}
@Override
public Object createPageInContainer(ComponentContainer componentContainer, int i) {
DirectionalLayout template = (DirectionalLayout) LayoutScatter.getInstance(abilitySlice).parse(ResourceTable.Layout_template_coffee_detail, null, false);
Image detailImage = (Image) template.findComponentById(ResourceTable.Id_coffee_image);
int pixel = images.get(i);
detailImage.setPixelMap(pixel);
componentContainer.addComponent(template);
return template;
}
@Override
public void destroyPageFromContainer(ComponentContainer componentContainer, int i, Object o) {
//滑出屏幕的组件进行移除
componentContainer.removeComponent((Component) o);
}
@Override
public boolean isPageMatchToObject(Component component, Object o) {
return true;
}
}
总结:
我们可以看到自己的适配器Provider继承了
PageSliderProvider
,因此我们只需要重写父类里面的四个方法即可:
getCount():主要是获取轮播图总共有几张图片
createPageInContainer():将图片渲染到刚刚1.中的提到模板后,将图片添加到容器中
destroyPageFromContainer():滑出屏幕的组件进行移除
isPageMatchToObject():设置为true
- 回到我们需要加载轮播图的Slice界面中,设置适配器和拿到PageSlider组件
public class CoffeeDetailSlice extends AbilitySlice {
private int[] images = {
ResourceTable.Media_lunbo2,
ResourceTable.Media_lunbo4};
private CoffeeImagePageSliderProvider coffeeDetailImageProvider;
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_coffee_detail);
// 从Layout_coffee_detail中拿到展示轮播图的组件PageSlider
PageSlider ps = (PageSlider) this.findComponentById(ResourceTable.Id_coffee_detail_pageSlider);
// 初始化自己的适配器CoffeeImagePageSliderProvider
coffeeDetailImageProvider = new CoffeeImagePageSliderProvider(initPage(),this);
// 给PageSlider进行适配器设置
ps.setProvider(coffeeDetailImageProvider);
}
private List<Integer> initPage() {
List<Integer> imagesArray = new ArrayList<>();
for (int image : images) {
imagesArray.add(image);
}
return imagesArray;
}
}
- OK到这里,我们的轮播图就开发完成了,你可以启动真机或者模拟器运行查看最终的结果!是不是很炫酷啊,所以我这里给您总结一下开发流程:
2.1.2 收藏口味
大家还记得我们的总体布局是使用的DependentLayout嘛,因此如果我们不知道位置关系,它会自动件覆盖显示,我们这里的收藏口味图标在屏幕右侧,因此我们右对齐显示就行,另外,我给大家计算记下尺寸关系
- 上面的轮播图片我们设置的高度为230vp,而我们这里的爱心布局高度是50vp,我们正好要显示在中间,因此距离顶部的高度
top_margin
应该是230 - 50/2 = 205vp - 设置布局的背景模板
star_taste.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:shape="oval">
<solid ohos:color="#fff"/>
</shape>
- 进行图片的设置
<DependentLayout
ohos:id="$+id:star_dl"
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="$graphic:star_taste"
ohos:align_parent_right="true"
ohos:right_margin="30vp"
ohos:top_margin="205vp">
<Image
ohos:image_src="$media:star"
ohos:center_in_parent="true"
ohos:scale_mode="stretch"
ohos:height="30vp"
ohos:width="30vp"/>
</DependentLayout>
- 有了图片的设置,文字那也很简单了,只要计算距离顶部的尺寸后,设置一下即可
<Text
ohos:align_parent_right="true"
ohos:right_margin="26vp"
ohos:top_margin="260vp"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="收藏口味"
ohos:text_color="#6a6a6a"
ohos:text_alignment="center"
ohos:text_size="16fp"/>
2.1.3 详情页咖啡名称
名称就是一个简单的文本组件设置,但是这里注意是相对布局,所以指明一下位置below="$id:coffee_detail_pageSlider"
即可
<Text
ohos:id="$+id:coffee_title"
ohos:below="$id:coffee_detail_pageSlider"
ohos:margin="8vp"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="狠狠爱你可可鸳鸯"
ohos:text_size="24fp"
ohos:text_color="#323232"
ohos:text_weight="600"
ohos:text_alignment="center"/>
2.1.4 口味和温度选择
- 这里温度的选择我是使用了一个
DirectionalLayout
作为整体布局组件,然后里面套了一个Text和两个Button,这里也要注意是相对布局,所以要设置位于上面的咖啡名称下面
- 两个按钮的背景文件如下:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:shape="rectangle">
<corners ohos:radius="8vp"/>
<solid ohos:color="#ebedf9"/>
</shape>
- 整个温度选择布代码如下:
<!--温度选择-->
<DirectionalLayout
ohos:id="$+id:temperature_choose"
ohos:below="$id:coffee_title"
ohos:height="40vp"
ohos:width="match_parent"
ohos:orientation="horizontal"
ohos:left_margin="8vp"
ohos:top_margin="10vp">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="温度"
ohos:text_size="18fp"
ohos:text_color="#323232"
ohos:text_weight="600"
ohos:text_alignment="center"/>
<Button
ohos:left_margin="20vp"
ohos:height="match_parent"
ohos:width="90vp"
ohos:text="冰"
ohos:text_size="14fp"
ohos:text_color="#6a6a6a"
ohos:text_alignment="center"/>
<Button
ohos:background_element="$graphic:temperature_choose"
ohos:left_margin="7vp"
ohos:height="match_parent"
ohos:width="90vp"
ohos:text="热"
ohos:text_size="14fp"
ohos:text_color="#242995"
ohos:text_alignment="center"/>
</DirectionalLayout>
- 有了温度选择,口味选择一样的道理
<!--糖度选择-->
<DirectionalLayout
ohos:id="$+id:sweet_choose"
ohos:below="$id:temperature_choose"
ohos:height="40vp"
ohos:width="match_parent"
ohos:orientation="horizontal"
ohos:left_margin="8vp"
ohos:top_margin="10vp">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="糖度"
ohos:text_size="18fp"
ohos:text_color="#323232"
ohos:text_weight="600"
ohos:text_alignment="center"/>
<Button
ohos:background_element="$graphic:temperature_choose"
ohos:left_margin="20vp"
ohos:height="match_parent"
ohos:width="90vp"
ohos:text="不另外加糖"
ohos:text_size="14fp"
ohos:text_color="#242995"
ohos:text_alignment="center"/>
<Button
ohos:left_margin="7vp"
ohos:height="match_parent"
ohos:width="90vp"
ohos:text="半糖"
ohos:text_size="14fp"
ohos:text_color="#6a6a6a"
ohos:text_alignment="center"/>
<Button
ohos:left_margin="7vp"
ohos:height="match_parent"
ohos:width="90vp"
ohos:text="标准糖"
ohos:text_size="14fp"
ohos:text_color="#6a6a6a"
ohos:text_alignment="center"/>
</DirectionalLayout>
2.1.5 商品详情介绍
我这里,主要是使用了一个DirectionalLayout作为整体布局组件,然后垂直方向一个Text组件和四个Image组件,其次就是为了美观一些padding的设置了
<DirectionalLayout
ohos:below="$id:sweet_choose"
ohos:padding="3vp"
ohos:top_margin="4vp"
ohos:left_margin="14vp"
ohos:right_margin="14vp"
ohos:height="match_content"
ohos:width="match_parent"
ohos:orientation="vertical"
ohos:background_element="$graphic:common_background">
<Text
ohos:bottom_margin="6vp"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="商品详情"
ohos:text_size="15vp"
ohos:text_color="#333"
ohos:text_alignment="center"/>
<Image
ohos:height="600vp"
ohos:width="match_parent"
ohos:image_src="$media:detail1"
ohos:scale_mode="stretch"/>
<Image
ohos:height="400vp"
ohos:width="match_parent"
ohos:image_src="$media:detail2"
ohos:scale_mode="stretch"/>
<Image
ohos:height="340vp"
ohos:width="match_parent"
ohos:image_src="$media:detail3"
ohos:scale_mode="stretch"/>
<Image
ohos:height="600vp"
ohos:width="match_parent"
ohos:image_src="$media:detail4"
ohos:scale_mode="stretch"/>
</DirectionalLayout>
2.2 底部结算栏
2.2.1 整体布局方式
- 从上到下是垂直布局,也就是上面一层信息和下面的两个按钮
- 上面一层中的
价格与选择信息
和右边的数量选择
是水平布局 - 价格和选择信息是垂直布局
- 两个按钮是水平布局
2.2.2 具体开发
<!--底部购买栏-->
<DirectionalLayout
ohos:height="110vp"
ohos:width="match_parent"
ohos:orientation="vertical"
ohos:left_padding="15vp"
ohos:right_margin="15vp"
ohos:top_padding="15vp"
ohos:bottom_padding="2vp"
ohos:align_parent_bottom="true">
<DependentLayout
ohos:height="44vp"
ohos:width="match_parent"
ohos:orientation="horizontal">
<DirectionalLayout
ohos:height="44vp"
ohos:width="240vp"
ohos:orientation="vertical">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="¥18"
ohos:text_color="#dd5810"
ohos:text_weight="700"
ohos:text_size="18fp"
ohos:text_alignment="center"/>
<Text
ohos:top_margin="3vp"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="厚乳拿铁¥18+热¥0+不另外加糖¥0"
ohos:text_color="#727272"
ohos:text_size="13fp"
ohos:text_alignment="center"/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="80vp"
ohos:align_parent_right="true"
ohos:orientation="horizontal">
<Image
ohos:id="$+id:minus"
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:layout_alignment="vertical_center"
ohos:id="$+id: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:id="$+id:add"
ohos:height="32vp"
ohos:width="32vp"
ohos:image_src="$media:plus"
ohos:layout_alignment="vertical_center"
ohos:padding="5vp"
ohos:scale_mode="stretch"/>
</DirectionalLayout>
</DependentLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="horizontal"
ohos:alignment="vertical_center"
ohos:padding="2vp">
<Button
ohos:background_element="$graphic:btn_buy_now"
ohos:left_margin="17vp"
ohos:height="34vp"
ohos:width="140vp"
ohos:text="立即购买"
ohos:text_size="18fp"
ohos:text_color="#bfa179"
ohos:text_alignment="center"/>
<Button
ohos:background_element="$graphic:btn_add_cart"
ohos:left_margin="10vp"
ohos:height="34vp"
ohos:width="140vp"
ohos:text="加入购物车"
ohos:text_size="18fp"
ohos:text_color="#fff"
ohos:text_alignment="center"/>
</DirectionalLayout>
</DirectionalLayout>
3.整体布局文件
整个布局的文件是coffee_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">
<!--中间滑动内容-->
<ScrollView
ohos:rebound_effect="true"
ohos:height="670vp"
ohos:width="360vp"
ohos:bottom_margin="110vp">
<DependentLayout
ohos:height="match_content"
ohos:width="match_parent"
ohos:orientation="vertical">
<PageSlider
ohos:id="$+id:coffee_detail_pageSlider"
ohos:height="match_content"
ohos:width="match_parent"
ohos:orientation="horizontal"/>
<DependentLayout
ohos:id="$+id:star_dl"
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="$graphic:star_taste"
ohos:align_parent_right="true"
ohos:right_margin="30vp"
ohos:top_margin="205vp">
<Image
ohos:image_src="$media:star"
ohos:center_in_parent="true"
ohos:scale_mode="stretch"
ohos:height="30vp"
ohos:width="30vp"/>
</DependentLayout>
<Text
ohos:align_parent_right="true"
ohos:right_margin="26vp"
ohos:top_margin="260vp"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="收藏口味"
ohos:text_color="#6a6a6a"
ohos:text_alignment="center"
ohos:text_size="16fp"/>
<Text
ohos:id="$+id:coffee_title"
ohos:below="$id:coffee_detail_pageSlider"
ohos:margin="8vp"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="狠狠爱你可可鸳鸯"
ohos:text_size="24fp"
ohos:text_color="#323232"
ohos:text_weight="600"
ohos:text_alignment="center"/>
<!--温度选择-->
<DirectionalLayout
ohos:id="$+id:temperature_choose"
ohos:below="$id:coffee_title"
ohos:height="40vp"
ohos:width="match_parent"
ohos:orientation="horizontal"
ohos:left_margin="8vp"
ohos:top_margin="10vp">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="温度"
ohos:text_size="18fp"
ohos:text_color="#323232"
ohos:text_weight="600"
ohos:text_alignment="center"/>
<Button
ohos:left_margin="20vp"
ohos:height="match_parent"
ohos:width="90vp"
ohos:text="冰"
ohos:text_size="14fp"
ohos:text_color="#6a6a6a"
ohos:text_alignment="center"/>
<Button
ohos:background_element="$graphic:temperature_choose"
ohos:left_margin="7vp"
ohos:height="match_parent"
ohos:width="90vp"
ohos:text="热"
ohos:text_size="14fp"
ohos:text_color="#242995"
ohos:text_alignment="center"/>
</DirectionalLayout>
<!--糖度选择-->
<DirectionalLayout
ohos:id="$+id:sweet_choose"
ohos:below="$id:temperature_choose"
ohos:height="40vp"
ohos:width="match_parent"
ohos:orientation="horizontal"
ohos:left_margin="8vp"
ohos:top_margin="10vp">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="糖度"
ohos:text_size="18fp"
ohos:text_color="#323232"
ohos:text_weight="600"
ohos:text_alignment="center"/>
<Button
ohos:background_element="$graphic:temperature_choose"
ohos:left_margin="20vp"
ohos:height="match_parent"
ohos:width="90vp"
ohos:text="不另外加糖"
ohos:text_size="14fp"
ohos:text_color="#242995"
ohos:text_alignment="center"/>
<Button
ohos:left_margin="7vp"
ohos:height="match_parent"
ohos:width="90vp"
ohos:text="半糖"
ohos:text_size="14fp"
ohos:text_color="#6a6a6a"
ohos:text_alignment="center"/>
<Button
ohos:left_margin="7vp"
ohos:height="match_parent"
ohos:width="90vp"
ohos:text="标准糖"
ohos:text_size="14fp"
ohos:text_color="#6a6a6a"
ohos:text_alignment="center"/>
</DirectionalLayout>
<DirectionalLayout
ohos:below="$id:sweet_choose"
ohos:padding="3vp"
ohos:top_margin="4vp"
ohos:left_margin="14vp"
ohos:right_margin="14vp"
ohos:height="match_content"
ohos:width="match_parent"
ohos:orientation="vertical"
ohos:background_element="$graphic:common_background">
<Text
ohos:bottom_margin="6vp"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="商品详情"
ohos:text_size="15vp"
ohos:text_color="#333"
ohos:text_alignment="center"/>
<Image
ohos:height="600vp"
ohos:width="match_parent"
ohos:image_src="$media:detail1"
ohos:scale_mode="stretch"/>
<Image
ohos:height="400vp"
ohos:width="match_parent"
ohos:image_src="$media:detail2"
ohos:scale_mode="stretch"/>
<Image
ohos:height="340vp"
ohos:width="match_parent"
ohos:image_src="$media:detail3"
ohos:scale_mode="stretch"/>
<Image
ohos:height="600vp"
ohos:width="match_parent"
ohos:image_src="$media:detail4"
ohos:scale_mode="stretch"/>
</DirectionalLayout>
</DependentLayout>
</ScrollView>
<!--底部购买栏-->
<DirectionalLayout
ohos:height="110vp"
ohos:width="match_parent"
ohos:orientation="vertical"
ohos:left_padding="15vp"
ohos:right_margin="15vp"
ohos:top_padding="15vp"
ohos:bottom_padding="2vp"
ohos:align_parent_bottom="true">
<DependentLayout
ohos:height="44vp"
ohos:width="match_parent"
ohos:orientation="horizontal">
<DirectionalLayout
ohos:height="44vp"
ohos:width="240vp"
ohos:orientation="vertical">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="¥18"
ohos:text_color="#dd5810"
ohos:text_weight="700"
ohos:text_size="18fp"
ohos:text_alignment="center"/>
<Text
ohos:top_margin="3vp"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="厚乳拿铁¥18+热¥0+不另外加糖¥0"
ohos:text_color="#727272"
ohos:text_size="13fp"
ohos:text_alignment="center"/>
</DirectionalLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="80vp"
ohos:align_parent_right="true"
ohos:orientation="horizontal">
<Image
ohos:id="$+id:minus"
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:layout_alignment="vertical_center"
ohos:id="$+id: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:id="$+id:add"
ohos:height="32vp"
ohos:width="32vp"
ohos:image_src="$media:plus"
ohos:layout_alignment="vertical_center"
ohos:padding="5vp"
ohos:scale_mode="stretch"/>
</DirectionalLayout>
</DependentLayout>
<DirectionalLayout
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="horizontal"
ohos:alignment="vertical_center"
ohos:padding="2vp">
<Button
ohos:background_element="$graphic:btn_buy_now"
ohos:left_margin="17vp"
ohos:height="34vp"
ohos:width="140vp"
ohos:text="立即购买"
ohos:text_size="18fp"
ohos:text_color="#bfa179"
ohos:text_alignment="center"/>
<Button
ohos:background_element="$graphic:btn_add_cart"
ohos:left_margin="10vp"
ohos:height="34vp"
ohos:width="140vp"
ohos:text="加入购物车"
ohos:text_size="18fp"
ohos:text_color="#fff"
ohos:text_alignment="center"/>
</DirectionalLayout>
</DirectionalLayout>
</DependentLayout>