欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

flutter引入公共组件在ListView中不显示问题(全局组件复用问题)

程序员文章站 2022-03-03 13:53:12
...

异常问题:
RenderCustomMultiChildLayoutBox object was given an infinite size during layout
子布局没有明确的大小不能使用Scaffold脚手架
公共组件的构建使用如下方式

class LoginWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _LoginState();
  }
}

class _LoginState extends State<LoginWidget> {
  final phoneController = TextEditingController();
  final pwdController = TextEditingController();

  @override
  Widget build(BuildContext context) {
  //此处用Container替代scaffold
    return Container(
        child: Container(
            alignment: AlignmentDirectional.center,
            child: Padding(
              padding: EdgeInsets.fromLTRB(30.0, 32.0, 30.0, 0),
              child: Column(
                children: <Widget>[
                  Image(
                    image: AssetImage("images/course_logo.png"),
                    width: 139,
                    height: 38,
                    fit: BoxFit.contain,
                  ),
                  inputPhone(context),

                  inputPassword(context),

                  loginWidget(context),

                  loginByWX(context),
                ],
              ),
            )),
    );
  }

引入的公共组件widget样例(登录模块)

import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:micro_course/bean/LoginMsg.dart';
import 'package:micro_course/utils/HexColor.dart';
import 'package:micro_course/http/DioManger.dart';
import 'package:micro_course/http/APIConfig.dart';
import 'package:micro_course/common/eventbus.dart';
import 'package:fluwx/fluwx.dart' as fluwx;

class LoginWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _LoginState();
  }
}

class _LoginState extends State<LoginWidget> {
  final phoneController = TextEditingController();
  final pwdController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Container(
            alignment: AlignmentDirectional.center,
            child: Padding(
              padding: EdgeInsets.fromLTRB(30.0, 32.0, 30.0, 0),
              child: Column(
                children: <Widget>[
                  Image(
                    image: AssetImage("images/course_logo.png"),
                    width: 139,
                    height: 38,
                    fit: BoxFit.contain,
                  ),
                  inputPhone(context),

                  inputPassword(context),

                  loginWidget(context),

                  loginByWX(context),
                ],
              ),
            )),
    );
  }

  ///手机号模块
  Widget inputPhone(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(top: 40),
      child: Container(
        height: 50,
        width: 307,
        padding: EdgeInsets.only(left: 10.0),
        alignment: AlignmentDirectional.center,
        decoration: BoxDecoration(
            color: Colors.grey[200], borderRadius: BorderRadius.circular(15)),
        child: TextField(
//          autofocus: true,
          controller: phoneController,
          decoration: InputDecoration(
            hintText: "请输入手机号",
            border: InputBorder.none,
            contentPadding: EdgeInsets.zero,
          ),
          onChanged: (v) {
//                      print("手机号:$v");
          },
        ),
      ),
    );
  }

  /// 密码模块
  Widget inputPassword(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(top: 20),
      child: Container(
        height: 50,
        width: 307,
        padding: EdgeInsets.only(left: 10.0),
        alignment: AlignmentDirectional.center,
        decoration: BoxDecoration(
            color: Colors.grey[200], borderRadius: BorderRadius.circular(15)),
        child: TextField(
//          autofocus: true,
          controller: pwdController,
          decoration: InputDecoration(
            hintText: "请输入密码",
            border: InputBorder.none,
            contentPadding: EdgeInsets.zero,
          ),
          onChanged: (v) {
//                      print("密码:$v");
          },
        ),
      ),
    );
  }

  /// 手机号登录模块
  Widget loginWidget(BuildContext context) {
    return GestureDetector(
      onTap: () {
        var params = {
          "phone": phoneController.text,
          "password": pwdController.text,
        };
        login(params, context);

//        Scaffold.of(context).showSnackBar(SnackBar(
//          content: Text('点击登录'+phoneController.text),
//        ));
      },
      child: Padding(
        padding: EdgeInsets.fromLTRB(7.5, 0, 7.5, 0),
        child: Container(
          height: 120,
          child: Stack(
            alignment: AlignmentDirectional.center,
            children: <Widget>[
              Container(
                height: 50,
                width: 307,
                decoration: BoxDecoration(
                  color: Colors.yellow[800],
                  borderRadius: BorderRadius.all(Radius.circular(45)),
                ),
              ),
              Text(
                '登录',
                style: TextStyle(fontSize: 18, color: HexColor('#824E00')),
              ),
            ],
          ),
        ),
      ),
    );
  }

  /// 微信登录模块
  Widget loginByWX(BuildContext context) {
    return GestureDetector(
      onTap: loginWX,
      child: Container(
//        height: 50,
        alignment: AlignmentDirectional.center,
        child: Padding(
          padding: EdgeInsets.all(2),
          child: Image(
            image: AssetImage("images/send.png"),
            width: 139,
            height: 40,
            fit: BoxFit.contain,
          ),
        ),
      ),
    );
  }

  void login(Map<String, String> params, BuildContext context) {
    DioManger.getInstance().post(APIConfig.LOGIN, params, null, (data) {
      setState(() {
        print("登录成功:" + data.toString());
        Map<String, dynamic> jsonMsg = json.decode(data.toString());
        LoginMsg loginMsg = LoginMsg.fromJson(jsonMsg);
        print("json转实体类:" + loginMsg.toString());

        ///更新UI
//            Navigator.pushReplacement(context, MaterialPageRoute(
//                builder: (context) => BottomNavigationWidget(),
//                settings: RouteSettings(
//                arguments:jsonMsg,
//               ),
//            ));
        getUserCourseList(loginMsg);
      });
    }, (error) {
      setState(() {});
      print("登录异常:" + error.toString());
    });
  }

  ///获取用户课程信息
  void getUserCourseList(LoginMsg loginMsg) {
    ///显示指定Map的限定类型
    Map<String, String> parms = {
      "student_id": loginMsg.data.studentId.toString()
    };
    Map<String, String> headers = {
      "token": loginMsg.data.loginToken.toString()
    };
    DioManger.getInstance().get(APIConfig.GET_COURSE_LIST, parms, headers,
            (data) {
          print("获取课程列表成功:" + data.toString());

          /// 登录成功发送全局事件
          bus.emit('login', loginMsg);
        }, (error) {
          print("获取课程列表失败:" + error.toString());
        });
  }

  ///微信登录
  void loginWX() {
    print("微信登录");
    fluwx
        .sendAuth(scope: "snsapi_userinfo", state: "wechat_sdk_demo_test")
        .then((data) {
      setState(() {
        print("拉取微信用户信息:" + data.toString());
      });
    }).catchError((e) {
      print('weChatLogin  e  $e');
    });
  }
}

公共组件的引入

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:micro_course/widgets/login.dart';

class CourseScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _LoginState();
  }
}

class _LoginState extends State<CourseScreen> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        resizeToAvoidBottomPadding: false,
        appBar: AppBar(
          title: Text(
            '选课',
            style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.normal,
                color: Colors.black87),
          ),
          centerTitle: true,
          actions: <Widget>[
            IconButton(
                icon: Icon(
                  Icons.more_horiz,
                  color: Colors.grey,
                ),
                onPressed: () {
                  Scaffold.of(context)
                      .showSnackBar(SnackBar(content: Text('点击分享')));
                })
          ],
        ),
        body: ListView(
          shrinkWrap: true,///根据子组件的总长度来设置 ListView 的长度
          children: <Widget>[
            Container(
                alignment: AlignmentDirectional.center,
                child: LoginWidget(),///引入公共登录组件
            ),
          ],
        ));
  }
}

  • 注意:此组件中因为有输入框的原因,在引入的时候公共组件要放在lisetview等滑动列表中,不然键盘弹起的时候会出现布局越界的异常,还有就是上文提到的公共组件中如果没有明确组件的大小,不能使用Scaffold脚手架,要用container等容器来替代。