这文我们一步一步开发一个商城。首先我们设定的目标是完成下面5个页面。å¾çå°å

为了完成这个炫酷的任务我们先看下你需要哪些知识。注意葵花宝典第一页:欲练神功,必先。。。学会下图知识:

ç¥è¯ç¹æ¢³ç

不要被这个图吓到。第二页告诉你:如不自攻,亦能成功。。

å¾çå°å

先列举两个会用到的插件:

  • Dio2.0:Dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消等操作。视频中将全面学习和使用Dio的操作。

  • Swiper:swiper滑动插件的使用,使用Swiper插件图片的切换效果

第一步:先打开VSCode,文件打开一个自己的目录。例如我的D:\flutter\App,开启终端,输入flutter create flutter_shop;

如果出错,你可能没配置好fultter环境。这个问题这里不说了。

然后进到这个目录中。运行看下。测试自己环境没问题。 

看看这破电脑,竟然用了1分多钟。

下面我们开始一个页面:在lib下建立pages/index_page.dart,这也是一个测试页面,页面只有一个标题和中间有个文字。

import 'package:flutter/material.dart';

class IndexPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('百姓生活+'),),
      body: Center(
        child:Text(' 百姓生活+')
      ),
    );
  }
}

然后修改flutter-shop下的main.dart,引入我们写的这个测试文件

import 'package:flutter/material.dart';
import './pages/index_page.dart';

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: MaterialApp(
        title:'百姓生活+',
        debugShowCheckedModeBanner: false, //Flutter去除右上角Debug标签
        theme: ThemeData(
          primaryColor:Colors.pink
        ),
        home:IndexPage()
      ),
    );
  }
}

然后运行 flutter run ,效果如下:

修改刚刚的index_page.dart,加入一个导航条。如下代码

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'home_page.dart';
import 'category_page.dart';
import 'cart_page.dart';
import 'member_page.dart';

class IndexPage extends StatefulWidget {
  @override
  _IndexPageState createState() => _IndexPageState();
}

class _IndexPageState extends State<IndexPage> {
  final List<BottomNavigationBarItem> bottomTabs = [
    BottomNavigationBarItem(icon: Icon(CupertinoIcons.home), title: Text('首页')),
    BottomNavigationBarItem(
        icon: Icon(CupertinoIcons.search), title: Text('分类')),
    BottomNavigationBarItem(
        icon: Icon(CupertinoIcons.shopping_cart), title: Text('购物车')),
    BottomNavigationBarItem(
        icon: Icon(CupertinoIcons.profile_circled), title: Text('会员中心'))
  ];
  final List tabBodies = [HomePage(), CategoryPage(), CartPage(), MemberPage()];
  int currentIndex = 0;
  var currentPage;
  @override
  void initState() {
    super.initState();
    currentPage = tabBodies[currentIndex];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color.fromRGBO(244, 245, 245, 1.0),
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        currentIndex: currentIndex,
        items: bottomTabs,
        onTap: (index) {
          setState(() {
            currentIndex = index;
            currentPage = tabBodies[currentIndex];
          });
        },
      ),
      body: currentPage,
    );
  }
}

另外新建4个文件:类似下面的代码,注意修改类名。和Text内容以示区别。

import 'package:flutter/material.dart';

class MemberPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:Center(
        child: Text('MemberPage'),
      )
    );
  }
}

这样导航条就做好了,点击分类会变化页面。

接下来添加 dio插件:

修改pages/home_page.dart

import 'package:flutter/material.dart';
import 'package:dio/dio.dart'; 

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    getHttp();
    return Scaffold(
      body:Center(
        child: Text('商城首页'),
      )
    );
  }
}

void getHttp()async{
  try{
    Response response;
    var data={'name':'Jack'};
    response = await Dio().get(
      'http://www.cctv.com/'
    );
    return print(response);
    
  }catch(e){
    return print(e);
  }
}

好了,dio开始工作了。下面我们做一个页面传递参数,然后进行一个Post请求。

main.dart:入口文件一般不用怎么修改。

import 'package:flutter/material.dart';
import './pages/index_page.dart';

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: MaterialApp(
        title:'百姓生活+',
        debugShowCheckedModeBanner: false, //Flutter去除右上角Debug标签
        theme: ThemeData(
          primaryColor:Colors.pink
        ),
        home:IndexPage()
      ),
    );
  }
}

pages/index_page.dart ,框架文件,定义了下方的导航Bar,并引入4个页面文件。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'home_page.dart';
import 'category_page.dart';
import 'cart_page.dart';
import 'member_page.dart';

class IndexPage extends StatefulWidget {
  @override
  _IndexPageState createState() => _IndexPageState();
}

class _IndexPageState extends State<IndexPage> {
  final List<BottomNavigationBarItem> bottomTabs = [
    BottomNavigationBarItem(icon: Icon(CupertinoIcons.home), title: Text('首页')),
    BottomNavigationBarItem(
        icon: Icon(CupertinoIcons.search), title: Text('分类')),
    BottomNavigationBarItem(
        icon: Icon(CupertinoIcons.shopping_cart), title: Text('购物车')),
    BottomNavigationBarItem(
        icon: Icon(CupertinoIcons.profile_circled), title: Text('会员中心'))
  ];
  final List tabBodies = [HomePage(), CategoryPage(), CartPage(), MemberPage()];
  int currentIndex = 0;
  var currentPage;
  @override
  void initState() {
    super.initState();
    currentPage = tabBodies[currentIndex];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color.fromRGBO(244, 245, 245, 1.0),
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        currentIndex: currentIndex,
        items: bottomTabs,
        onTap: (index) {
          setState(() {
            currentIndex = index;
            currentPage = tabBodies[currentIndex];
          });
        },
      ),
      body: currentPage,
    );
  }
}

4个页面文件:/pages/home_page.dart:

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';


class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  TextEditingController typeController = TextEditingController();
  String showText = '天气会显示在这里';
  @override
  Widget build(BuildContext context) {
    return Container(
       
        child: Scaffold(
          appBar: AppBar(title: Text('天气API测试'),),
          body:Container(
            height: 1000,
            child: Column(
              children: <Widget>[
                TextField(
                  controller:typeController,
                  decoration:InputDecoration (
                    contentPadding: EdgeInsets.all(10.0),
                    labelText: '输入城市',
                    helperText: '请输入你的城市'
                  ),
                  autofocus: false,
                ),
                RaisedButton(
                  onPressed:_choiceAction,
                  child: Text('查询'),
                ),
              
                Text(
                  showText,
                    overflow:TextOverflow.ellipsis,
                    maxLines: 2,
                ),
                ],
            ),
          ) 
        ),
    );
  }
  
Future getHttp(String TypeText)async{
  try{ 
      Response response;
      var data={'name':TypeText};
      response = await Dio().get(
         'https://api.heweather.net/s6/weather/now?location=beijing&key=55799160534d495a81c373e69fcf9366',
          queryParameters:data
      );
      return response.data;

  }catch(e){
    return print(e);
  }
}

void _choiceAction(){
     
    if(typeController.text.toString()==''){
      showDialog(
        context: context,
        builder: (context)=>AlertDialog(title:Text('城市地址不能为空'))
      );
    }else{
        getHttp(typeController.text.toString()).then((val){
         setState(() {
          //  showText=val['data']['name'].toString();
           showText=val.toString();
         });
        });
    }

  }
}


 

其他3个文件暂不做修改:类似这样,类名不同而已。

import 'package:flutter/material.dart';

class CartPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:Center(
        child: Text('Cart首页'),
      )
    );
  }
}

测试结果:如下,你成功了吗?

4

接下来,我们这里稍作修改:把接口地址写在一个单独的文件里,如

/config/service_url.dart:

const serviceUrl= 'http://www.xxxxx.com';//此端口后台写的。
const servicePath={
  'homePageContext': serviceUrl+'/house/indexapi', // 商家首页信息
};
 

/service/service_method.dart:

import 'package:dio/dio.dart';
import 'dart:async';
// import 'dart:io';
import '../config/service_url.dart';
 
Future getHomePageContent() async {
  try {
    print('start get HomePage data.....');
    Response response;
    Dio dio = new Dio();
    // dio.options.contentType("application/x-www-form-urlencoded") ;
    var fromData = {'Sokey': ''};
    response = await dio.post(servicePath['homePageContext'], data: fromData);
    if (response.statusCode == 200) {
      return response.data;
    } else {
      throw Exception('后端接口异常!');
    }
  } catch (e) {
    return print('ERROR:======>' + e);
  }
}

index

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'home_page.dart';
import 'category_page.dart';
import 'cart_page.dart';
import 'member_page.dart';

class IndexPage extends StatefulWidget {
  @override
  _IndexPageState createState() => _IndexPageState();
}

class _IndexPageState extends State<IndexPage> {
  final List<BottomNavigationBarItem> bottomTabs = [
    BottomNavigationBarItem(icon: Icon(CupertinoIcons.home), title: Text('首页')),
    BottomNavigationBarItem(
        icon: Icon(CupertinoIcons.search), title: Text('分类')),
    BottomNavigationBarItem(
        icon: Icon(CupertinoIcons.shopping_cart), title: Text('购物车')),
    BottomNavigationBarItem(
        icon: Icon(CupertinoIcons.profile_circled), title: Text('会员中心'))
  ];
  final List tabBodies = [HomePage(), CategoryPage(), CartPage(), MemberPage()];
  int currentIndex = 0;
  var currentPage;
  @override
  void initState() {
    super.initState();
    currentPage = tabBodies[currentIndex];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color.fromRGBO(244, 245, 245, 1.0),
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        currentIndex: currentIndex,
        items: bottomTabs,
        onTap: (index) {
          setState(() {
            currentIndex = index;
            currentPage = tabBodies[currentIndex];
          });
        },
      ),
      body: currentPage,
    );
  }
}

home:

import 'package:flutter/material.dart';
import '../service/service_method.dart';
 


class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}
 
class _HomePageState extends State<HomePage> {
   String homePageContent = '正在获取数据';

   @override
   void initState() { 
     getHomePageContent().then((val){ 
         setState((){
           homePageContent=val.toString();
         }); 
     });
     super.initState();
     
   }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
       appBar: AppBar(title: Text("百姓生活+"),),
       body: SingleChildScrollView(child: Text(homePageContent),),
    );
  }
 
} 

其他文件几乎没变化。结果首页会获取到数据

接下来我们获取轮播图数据,然后显示一个轮播图。首先是放个插件。

然后修改Home.dart:

import 'package:flutter/material.dart';
import '../service/service_method.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
import 'dart:convert'; 

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}
 
class _HomePageState extends State<HomePage> {
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
       appBar: AppBar(title: Text("百姓生活+"),),
       body:FutureBuilder(
         future: getHomePageContent(),
         builder: (context,snapshot){
           if (snapshot.hasData) {  
           // var d = {"list":[ {"id":3409,"KP_Wjt":"http:\/\/ .com\/uploads\/20191101\/3878bfd44de3de2cd9549fcf53d063b2Cen.jpg","KP_LpName":"港珠澳ISC首座","KP_KfID":"9","Kp_gflm":1,"KP_City":292,"KP_Tel":"400-6885-919","KP_Fjh":"","KP_Xszt":0,"KP_Wylx":"写字楼","KP_TsType":"养生社区,宜居生态地产","KP_Lpdz":"珠海市横琴大桥旁·宝湾路与富林东路交汇处","KP_YouHui":"全款99折","KP_TaoJia":"","KP_Tj":0,"KP_Yhz":0,"KP_Zlhx":"","KP_AllViewUrl":"","KP_Isallview":0,"KP_Qiprice":24000,"KP_Juprice":25000,"KP_ValidityStart":"2019年11月01日","KP_ValidityEnd":"2019年11月30日","KP_Kefu_Pic":"http:\/\/yuefangwangimg.oss-cn-hangzhou.aliyuncs.com\/uploads\/20190730\/505ff8f37977274e223423c0804514421Max.jpg","KP_Kefu_Name":"吴谊兰","CNAME":"珠海市","isvideo":0,"dtone":{"id":41803,"KP_Title":"珠海港珠澳ISC首座项目均价25000元\/㎡,非毛坯交付"}}],"total":3732};
             
            var e = json.encode(snapshot.data );
            var data=json.decode(e.toString());
           
             List<Map> swiperDataList = (data['list'] as List).cast(); // 顶部轮播组件数
             //print(swiperDataList);
             return Column(children: <Widget>[
               SwiperDiy(swiperDataList:swiperDataList)
             ],);
           } else {
             return Center(child: Text('Loading....'),);
           }
         },
       )
    );
  }

  
}



// 首页轮播组件编写
class SwiperDiy extends StatelessWidget {
  final List swiperDataList;
  SwiperDiy({Key key,this.swiperDataList}):super(key:key);

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 333.0,
      child: Swiper(
        itemBuilder: (BuildContext context,int index){
          return Image.network("${swiperDataList[index]['KP_Wjt']}",fit:BoxFit.fill);
        },
        itemCount: swiperDataList.length,
        pagination: new SwiperPagination(),
        autoplay: true,
      ),
    );
  }
}


 

结果如下:

谁家发生这个事,都会崩溃了。。这个社会要整顿了。。。。

下节我会公布我的接口数据。你不会头疼了。

 

 

 

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐