网络知识 娱乐 CH12-综合项目—仿美团外卖

CH12-综合项目—仿美团外卖

文章目录

  • 目标
  • 一、项目分析
    • 目标
    • 项目概述
    • 开发环境
    • 模块说明
  • 二、效果展示
    • 目标
    • 店铺界面
    • 店铺详情界面
    • 店铺详情界面
    • 确认清空购物车的对话框
    • 菜品详情界面
    • 订单界面和支付界面
  • 三、服务器数据准备
    • 目标
    • 注意
  • 四、店铺功能业务实现
    • 目标
    • 4.1 搭建标题栏布局
    • 4.2 搭建广告栏界面布局
    • 4.3 搭建店铺界面布局
    • 4.4 搭建店铺列表条目界面布局
    • 4.5 封装店铺信息与菜品信息的实体类
      • 创建ShopBean类
      • 创建FoodBean类
    • 4.6 编写广告栏的适配器
    • 4.7 编写店铺列表适配器
    • 4.8 实现店铺界面显示功能
  • 五、店铺详情功能业务实现
    • 目标
    • 5.1 搭建店铺详情界面布局
    • 5.2 搭建菜单列表条目界面布局
    • 5.3 搭建购物车列表条目界面布局
    • 5.4 搭建确认清空购物车界面布局
    • 5.5 编写菜单列表适配器
    • 5.6 编写购物车列表适配器
    • 5.7 实现菜单显示与购物车功能
  • 六、菜品详情功能业务实现
    • 目标
    • 6.1 搭建菜品详情界面布局
    • 6.2 实现菜品界面显示功能
  • 七、订单功能业务实现
    • 目标
    • 7.1 搭建订单界面布局
    • 7.2 搭建订单列表条目界面布局
    • 7.3 搭建支付界面布局
    • 7.4 编写订单列表适配器
    • 7.5 实现订单显示与支付功能
  • 总结
  • 总结

目标

  • 了解仿美团外卖项目的分析,能够说出项目的开发环境和模块
  • 掌握服务器的搭建方式,能够独立搭建服务器
  • 掌握店铺界面的开发过程,能够实现店铺界面的显示效果
  • 掌握店铺详情界面与购物车的开发过程,能够独立实现购物车功能
  • 掌握菜品详情界面的开发过程,能够实现菜品详情界面的功能
  • 掌握订单界面的开发过程,能够实现订单界面的效果

​ 为了巩固第1~11章的Android基础知识,本章要开发一款仿美团外卖的项目,该项目与我们平常看到的美团外卖项目界面比较类似,展示的内容包括店铺、菜单、购物车、订单与支付等信息。为了让大家能够熟练掌握仿美团外卖项目中用到的知识点,接下来我们将从项目分析开始,一步一步带领大家开发仿美团外卖项目的各个功能。

一、项目分析

目标

  • 了解仿美团外卖项目的分析,能够说出项目的开发环境和模块

项目概述

​ 仿美团外卖项目是一个网上订餐项目,该项目中包含订餐的店铺、各店铺的菜单、购物车以及订单与付款等模块。在店铺列表中可以看到店铺的名称、月售数量、起送价格与配送费用、配送时间以及店铺特色等信息,点击店铺列表中的任意一个店铺,程序会进入到店铺详情界面,该界面主要用于显示店铺中的菜单信息,同时可以将想要吃的菜添加到购物车中,选完菜之后可以点击该界面中的“去结算”按钮,进入到订单界面,在该界面核对已点的菜单信息,并通过“去支付”按钮进行付款。

开发环境

操作系统:

  • Windows系统 8

开发工具:

  • JDK 8

  • Android Studio 3.2 +模拟器(天天模拟器)

  • Tomcat 8.5.59

API版本:

  • Android API 28

由于本项目使用的是在实际开发中的网络请求代码来访问Tomcat服务器上的数据,所以开发工具中的模拟器必须为第三方模拟器(如,夜神模拟器、天天模拟器),如果用Android原生模拟器,则会访问不到数据

模块说明

image-20220308164435889

二、效果展示

目标

  • 了解仿美团外卖项目的效果展示,能够说出项目中各个界面的跳转关系

店铺界面

​ 程序启动后,首先会进入店铺界面,该界面展示的是一些由店铺信息组成的列表与一个滑动的广告栏。

image-20220308164556747

店铺详情界面

点击店铺列表中任意一个条目或广告栏中的任意一张图片,程序都会跳转到对应的店铺详情界面,该界面展示的是店铺的公告信息、配送信息、菜单列表信息以及购物车信息。

image-20220308164652700

店铺详情界面

​ 点击菜单列表条目右侧的“加入购物车”按钮可以将菜品添加到购物车中,在界面左下角可以看到购物车中添加的菜品数量。

image-20220308164803361

确认清空购物车的对话框

​ 已选商品列表的右上角有一个“清空”按钮,点击该按钮会弹出一个确认清空购物车的对话框。

image-20220308164842608

菜品详情界面

​ 在店铺详情界面中,点击菜单列表的任意一个条目,程序都会跳转到菜品详情界面,菜品详情界面是一个对话框的样式。

image-20220308164919890

订单界面和支付界面

​ 在店铺详情界面中,点击“去结算”按钮会跳转到订单界面,该界面通过一个列表展示购物车中的菜品信息,点击“去支付”按钮,程序会弹出一个显示支付二维码的对话框

image-20220308165009582

三、服务器数据准备

目标

  • 掌握服务器的搭建方式,能够独立搭建服务器

image-20220308165110487

​ 上述图中,ROOT文件夹在apache-tomcat-7.0.56/webapps/目录下,表示Tomcat的根目录。order文件夹存放的是订餐项目用到的所有数据,其中,order/img文件夹存放的是图片资源,包含店铺图片和菜单图片。shop_list_data.json文件中存放的是店铺列表与店铺详情界面的数据,数据的具体内容可参考教材。

注意

​ 上述文件中的IP地址需要修改为自己电脑上的IP地址,否则访问不到Tomcat服务器中的数据。

​ 如果想要启动Tomcat服务器,可以在apache-tomcat-8.5.59bin包中找到startup.bat文件,双击该文件即可。

四、店铺功能业务实现

目标

  • 掌握店铺界面的开发过程,能够实现店铺界面的显示效果

​ 当打开仿美团外卖项目时,程序会直接进入主界面,也就是店铺列表界面。店铺列表界面从上至下分为标题栏、水平滑动广告栏和店铺列表三部分。其中,广告栏与店铺列表的数据是通过网络请求从服务器上获取的JSON数据,接下来本节将针对店铺功能的相关业务进行开发。

4.1 搭建标题栏布局

​ 在仿美团外卖项目中,大部分界面都有一个返回键和一个标题栏。为了便于代码重复利用,可以将返回键和标题栏抽取出来单独放在一个布局文件(title_bar.xml)中。

image-20220308165402039

放置界面控件 reslayouttitle_bar.xml


<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/title_bar"
    android:layout_width="match_parent"
    android:layout_height="45dp"
    android:background="@android:color/transparent">
    <TextView
        android:id="@+id/tv_back"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:background="@drawable/go_back_selector" />
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textColor="@android:color/white"
        android:textSize="20sp" />
</RelativeLayout>

创建背景选择器 drawablego_back_selector.xml


<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/iv_back_selected" android:state_pressed="true"/>
    <item android:drawable="@drawable/iv_back"/>
</selector>

4.2 搭建广告栏界面布局

​ 广告栏界面主要用于展示广告图片信息与跟随图片滑动的小圆点,当前显示的广告图片对应的小圆点颜色为白色,其余小圆点的颜色为灰色。

image-20220308165536637

放置界面控件 reslayoutadbanner.xml


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/adbanner_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <android.support.v4.view.ViewPager
        android:id="@+id/slidingAdvertBanner"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginBottom="1dp"
        android:background="@android:color/black"
        android:gravity="center" />
    <cn.itcast.order.views.ViewPagerIndicator
        android:id="@+id/advert_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:padding="10dp" />
</RelativeLayout>

自定义控件ViewPagerIndicator类 orderviewsViewPagerIndicator.java

package cn.itcast.order.views;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;

import cn.itcast.order.R;

public class ViewPagerIndicator extends LinearLayout {
    private int mCount; //小圆点的个数
    private int mIndex; //当前小圆点的位置
    private Context context;
    public ViewPagerIndicator(Context context) {
        this(context, null);
    }
    public ViewPagerIndicator(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }
    /**
     * 设置滑动到当前小圆点时其他圆点的位置
     */
    public void setCurrentPostion(int currentIndex) {
        mIndex = currentIndex; //当前小圆点
        this.removeAllViews(); //移除界面上存在的view
        int pex = context.getResources().getDimensionPixelSize(
                R.dimen.view_indicator_padding);
        for (int i = 0; i < this.mCount; i++) {
            //创建一个ImageView控件来放置小圆点
            ImageView imageView = new ImageView(context);
            if (mIndex == i) { //滑动到的当前界面
                //设置小圆点的图片为白色图片
                imageView.setImageResource(R.drawable.indicator_on);
            }else {
                //设置小圆点的图片为灰色图片
                imageView.setImageResource(R.drawable.indicator_off);
            }
            imageView.setPadding(pex, 0, pex, 0);//设置小圆点图片上下左右的padding
            this.addView(imageView);//把小圆点添加到自定义ViewPagerIndicator控件上
        }
    }
    /**
     * 设置小圆点的数目
     */
    public void setCount(int count) {
        this.mCount = count;
    }
}

设置界面上圆点间的距离 resvaluesdimens.xml


<resources>
    <dimen name="view_indicator_padding">5dp</dimen>
</resources>

白色和灰色的小圆点图片 resdrawableindicator_on.xml和indicator_off.xml


<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <size android:height="6dp" android:width="6dp" />
    <solid android:color="@android:color/white" />
</shape>

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <size android:height="6dp" android:width="6dp" />
    <solid android:color="#BCBCBC" />
</shape>

4.3 搭建店铺界面布局

店铺界面是由一个标题栏、一个广告栏以及一个店铺列表组成,标题栏主要用于展示该界面的标题,广告栏主要用于展示店铺中的菜品广告图片,店铺列表主要用于展示各店铺的信息。

image-20220308165621093

放置界面控件 reslayoutactivity_shop.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical">
    <include layout="@layout/title_bar" />
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#f5f5f6"
        android:scrollbars="none">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <include layout="@layout/adbanner" />
            <cn.itcast.order.views.ShopListView
                android:id="@+id/slv_list"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_marginLeft="8dp"
                android:layout_marginTop="8dp"
                android:layout_marginRight="8dp"
                android:dividerHeight="8dp"
                android:scrollbars="none" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

创建自定义控件ShopListView orderviewsShopListView.java

package cn.itcast.order.views;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;

public class ShopListView extends ListView {
    public ShopListView(Context context) {
        super(context);
    }
    public ShopListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public ShopListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}

4.4 搭建店铺列表条目界面布局

​ 由于店铺界面使用自定义控件ShopListView展示店铺列表,所以需要创建一个该列表的条目界面。在条目界面中需要展示店铺名称、月销售商品的数量、起送价格、配送费用、店铺特色以及配送时间。

image-20220308165706017

放置界面控件 reslayoutshop_item.xml


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="8dp"
    android:layout_marginTop="8dp"
    android:layout_marginRight="8dp"
    android:background="@drawable/item_bg_selector"
    android:padding="10dp">
    <ImageView
        android:id="@+id/iv_shop_pic"
        android:layout_width="100dp"
        android:layout_height="70dp"
        android:layout_alignParentLeft="true" />
    <LinearLayout
        android:id="@+id/ll_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@id/iv_shop_pic"
        android:orientation="vertical">
        <TextView
            android:id="@+id/tv_shop_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@android:color/black"
            android:textSize="14sp" />
        <TextView
            android:id="@+id/tv_sale_num"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:textColor="@color/color_gray"
            android:textSize="12sp" />
        <TextView
            android:id="@+id/tv_cost"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:textColor="@color/color_gray"
            android:textSize="12sp" />
    </LinearLayout>
    <TextView
        android:id="@+id/tv_feature"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/ll_info"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="10dp"
        android:layout_toRightOf="@id/iv_shop_pic"
        android:background=