Flutter仿美团点餐的UI效果

Flutter仿美团点餐的UI效果

前两天公司项目紧,要我做一个左边列表选择后,展示右边的标签,然后右边的标签可以多选,捋了下逻辑,觉得很简单,于是手撸了代码,代码如下

import 'package:flutter/cupertino.dart';

import 'package:flutter/material.dart';

class TestMenuPage extends StatefulWidget {

  @override

  _TestMenuPageState createState() => _TestMenuPageState();

}

class _TestMenuPageState extends State {

  List leftList = [];

  int _leftIndex = 0;

  Map> totalItem = {};

  double height;

  @override

  initState() {

    super.initState();

    leftList = List.generate(20, (index) => LeftData('$index组', index + 1)).toList();

  }

  @override

  Widget build(BuildContext context) {

    int length = 0;

    totalItem.forEach((key, value) {

      length += value.length;

    });

    height = MediaQuery.of(context).size.height;

    return Scaffold(

      appBar: AppBar(

        title: Text('测试菜单'),

        actions: [

          Container(

            width: 80,

            height: 50,

            child: Center(

              child: GestureDetector(

                onTap: () {

                  print('所有选中的项目: ${totalItem.toString()}');

                },

                child: Text(

                  '完成',

                  style: TextStyle(

                    fontSize: 16,

                    color: Colors.white,

                  ),

                ),

              ),

            ),

          )

        ],

      ),

      body: Column(

        // mainAxisSize: MainAxisSize.min,

        children: [

          if (length != 0)

            Column(

              mainAxisSize: MainAxisSize.min,

              children: [

                Container(

                  height: 36,

                  width: double.infinity,

                  padding: EdgeInsets.symmetric(horizontal: 16),

                  alignment: Alignment.centerLeft,

                  child: Text.rich(

                    TextSpan(

                      children: [

                        TextSpan(

                          text: '已选择',

                          style: TextStyle(

                            fontSize: 16,

                            color: Color(

                              0xff282828,

                            ),

                          ),

                        ),

                        WidgetSpan(

                          child: Container(

                            width: 8,

                          ),

                        ),

                        TextSpan(

                          text: '擅长治疗疾病最多选择20个',

                          style: TextStyle(

                            fontSize: 14,

                            color: Color(

                              0xff989898,

                            ),

                          ),

                        )

                      ],

                    ),

                  ),

                ),

                Container(

                  width: double.infinity,

                  padding: EdgeInsets.only(

                    left: 16,

                    right: 16,

                    top: 16,

                    bottom: 16,

                  ),

                  // height: 173,

                  constraints: BoxConstraints(

                    // minHeight: 50,

                    maxHeight: 173,

                  ),

                  child: Scrollbar(

                    thickness: 2,

                    child: SingleChildScrollView(

                      physics: BouncingScrollPhysics(),

                      child: Wrap(

                        runSpacing: 13,

                        spacing: 13,

                        children: _grow(),

                      ),

                    ),

                  ),

                ),

              ],

            ),

          Expanded(

            flex: 2,

            child: Container(

              height: double.infinity,

              decoration: BoxDecoration(

                border: Border(

                  top: BorderSide(

                    color: Color(0xfff0f0f0),

                    width: 1,

                  ),

                ),

              ),

              child: Row(

                children: [

                  Container(

                    width: 100,

                    height: double.infinity,

                    child: Scrollbar(

                      thickness: 2,

                      child: ListView.builder(

                        physics: BouncingScrollPhysics(),

                        shrinkWrap: true,

                        itemBuilder: (c, index) {

                          LeftData l = leftList[index];

                          return GestureDetector(

                            behavior: HitTestBehavior.opaque,

                            onTap: () {

                              setState(() {

                                _leftIndex = index;

                              });

                              print('_leftIndex: $_leftIndex');

                            },

                            child: Container(

                              height: 44,

                              width: double.infinity,

                              color: _leftIndex == index ? Colors.white : Color(0xfff2f2f2),

                              child: _leftIndex == index

                                  ? Stack(

                                      // mainAxisAlignment: MainAxisAlignment.center,

                                      children: [

                                        Positioned(

                                          child: Center(

                                            child: Container(

                                              decoration: BoxDecoration(

                                                border: Border(

                                                  left: BorderSide(

                                                    color: Color(0xffc33b2a),

                                                    width: 2,

                                                  ),

                                                ),

                                              ),

                                              height: 15,

                                              width: 2,

                                              margin: EdgeInsets.only(right: 8),

                                            ),

                                          ),

                                          left: 20,

                                          top: 12,

                                          bottom: 12,

                                          // width: 2,

// height: 15,

                                        ),

                                        Positioned(

                                          child: Text(

                                            l.name,

                                            style: TextStyle(

                                              fontSize: 16,

                                              color: Color(0xff282828),

                                            ),

                                          ),

                                          left: 32,

                                          top: 12,

                                          bottom: 12,

                                        ),

                                      ],

                                    )

                                  : Stack(

                                      children: [

                                        Positioned(

                                          child: Text(

                                            l.name,

                                            style: TextStyle(

                                              fontSize: 16,

                                              color: Color(0xff282828),

                                            ),

                                          ),

                                          left: 32,

                                          top: 12,

                                          bottom: 12,

                                        )

                                      ],

                                    ),

                            ),

                          );

                        },

                        itemCount: leftList.length,

                        itemExtent: 44,

                      ),

                    ),

                  ),

                  Expanded(

                    child: Container(

                      color: Colors.white,

                      child: Scrollbar(

                        thickness: 2,

                        child: SingleChildScrollView(

                          physics: BouncingScrollPhysics(),

                          child: Container(

                            padding: EdgeInsets.all(10),

                            child: Wrap(

                              spacing: 10,

                              runSpacing: 10,

                              children: List.generate(

                                50,

                                (index) => Row(

                                  mainAxisSize: MainAxisSize.min,

                                  children: [

                                    GestureDetector(

                                      behavior: HitTestBehavior.opaque,

                                      onTap: () {

                                        setState(() {

                                          if (length < 20) {

                                            if (totalItem[_leftIndex] == null)

                                              totalItem[_leftIndex] = [];

                                            List list = totalItem[_leftIndex];

                                            if (!list.contains(index))

                                              list.add(index);

                                            else

                                              list.remove(index);

                                            print('totalItem: ${totalItem.toString()}');

                                          } else {

                                            print('最多只能选择20个');

                                          }

                                        });

                                        _grow();

                                      },

                                      child: totalItem[_leftIndex] != null &&

                                              totalItem[_leftIndex].contains(index)

                                          ? Container(

                                              height: 32,

                                              padding: EdgeInsets.symmetric(horizontal: 10),

                                              decoration: BoxDecoration(

                                                borderRadius: BorderRadius.all(

                                                  Radius.circular(2),

                                                ),

                                                border: Border.all(

                                                  color: Color(0xffc33b2a),

                                                  width: 1,

                                                ),

                                              ),

                                              child: Center(

                                                child: Text(

                                                  '$_leftIndex组$index项',

                                                  style: TextStyle(

                                                    color: Color(0xffc33b2a),

                                                    fontSize: 16,

                                                  ),

                                                ),

                                              ),

                                            )

                                          : Container(

                                              height: 32,

                                              padding: EdgeInsets.symmetric(horizontal: 10),

                                              decoration: BoxDecoration(

                                                borderRadius: BorderRadius.all(

                                                  Radius.circular(2),

                                                ),

                                                border: Border.all(

                                                  color: Color(0xffd0d0d0),

                                                  width: 1,

                                                ),

                                              ),

                                              child: Center(

                                                child: Text(

                                                  '$_leftIndex组$index项',

                                                  style: TextStyle(

                                                    color: Color(0xff282828),

                                                    fontSize: 16,

                                                  ),

                                                ),

                                              ),

                                            ),

                                    ),

                                  ],

                                ),

                              ),

                            ),

                          ),

                        ),

                      ),

                    ),

                  )

                ],

              ),

            ),

          ),

        ],

      ),

    );

  }

  List _grow() {

    List list = [];

    totalItem.forEach((key, value) {

      list.addAll(value

          .map(

            (e) => GestureDetector(

              behavior: HitTestBehavior.opaque,

              onTap: () {

                print('delete: $e');

                setState(() {

                  totalItem[key].remove(e);

                });

              },

              child: Row(

                mainAxisSize: MainAxisSize.min,

                children: [

                  Container(

                    height: 32,

                    padding: EdgeInsets.symmetric(horizontal: 10),

                    decoration: BoxDecoration(

                      borderRadius: BorderRadius.all(

                        Radius.circular(2),

                      ),

                      border: Border.all(

                        color: Color(0xffc33b2a),

                        width: 1,

                      ),

                    ),

                    child: Center(

                      child: Row(

                        children: [

                          Text(

                            '$key组$e项',

                            style: TextStyle(

                              color: Color(0xffc33b2a),

                              fontSize: 16,

                            ),

                          ),

                          Text(

                            'x',

                            style: TextStyle(

                              color: Color(0xffc33b2a),

                              fontSize: 16,

                            ),

                          ),

                        ],

                      ),

                    ),

                  ),

                ],

              ),

            ),

          )

          .toList());

    });

    return list;

  }

}

class LeftData {

  String name;

  int id;

  LeftData(this.name, this.id);

}

效果见下图:


初始时默认选择到第一组


从左边列表里筛选出标签后勾选上

不知道怎么弄gif图,就看截图吧,哈哈

逻辑是:第一次进入默认选到第一组,展示第一组的所有标签,然后根据选择的哪一组,从右边标签里筛选出想要的,然后上面的区域展示勾选上的,点击里面的x可以去掉该标签,点击下面的标签列表项也可以取消,上面的区域自适应高度。

写的比较简单,写完这个之后,就把它拿到公司项目里,对接接口了,如果大家用得着,可以拿过去,把接口对上就ok了,

你可能感兴趣的:(Flutter仿美团点餐的UI效果)