You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Dart实现登录动作并在Flutter中创建登录UI?

Flutter 登录UI搭建与Dart登录逻辑实现

一、构建登录UI

按照以下步骤完成基础登录界面的搭建:

1. 创建Stateful Widget

登录界面需要响应输入框状态变化,因此使用StatefulWidget:

class LoginPage extends StatefulWidget {
  const LoginPage({super.key});

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  bool _isLoading = false;

  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 后续实现build内容
  }
}

2. 配置Scaffold与AppBar

在build方法中返回Scaffold,设置顶部标题栏:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('用户登录'),
      centerTitle: true,
    ),
    body: // 核心内容区域
  );
}

3. 用Column组织核心组件

将所有UI元素放入Column,设置布局属性让内容垂直居中,并添加内边距避免内容贴边:

body: Padding(
  padding: const EdgeInsets.symmetric(horizontal: 24.0),
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      // 后续添加FlutterLogo、输入框、按钮
    ],
  ),
),

在Column的children中加入官方Logo组件:

const FlutterLogo(
  size: 100.0,
),
const SizedBox(height: 48.0), // 间距

5. 实现用户名/密码输入框

添加两个TextField分别处理账号和密码输入:

// 账号输入框
TextField(
  controller: _emailController,
  keyboardType: TextInputType.emailAddress,
  decoration: const InputDecoration(
    hintText: '输入邮箱或用户名',
    labelText: '账号',
    border: OutlineInputBorder(),
  ),
),
const SizedBox(height: 16.0),
// 密码输入框
TextField(
  controller: _passwordController,
  obscureText: true, // 隐藏密码内容
  decoration: const InputDecoration(
    hintText: '输入密码',
    labelText: '密码',
    border: OutlineInputBorder(),
  ),
),
const SizedBox(height: 24.0),

二、Dart实现登录动作

1. 编写登录逻辑方法

在_LoginPageState类中添加登录方法,包含输入校验和模拟接口请求:

Future<void> _login() async {
  final email = _emailController.text.trim();
  final password = _passwordController.text.trim();

  // 简单输入校验
  if (email.isEmpty || password.isEmpty) {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('账号或密码不能为空')),
    );
    return;
  }

  // 标记加载状态
  setState(() {
    _isLoading = true;
  });

  try {
    // 模拟API请求(实际项目替换为真实接口调用)
    await Future.delayed(const Duration(seconds: 2));
    
    // 登录成功逻辑:比如跳转到主页、保存用户信息
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('登录成功')),
    );
    // 示例:跳转到主页
    // Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => HomePage()));
  } catch (e) {
    // 登录失败处理
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('登录失败:${e.toString()}')),
    );
  } finally {
    // 结束加载状态
    setState(() {
      _isLoading = false;
    });
  }
}

2. 添加登录按钮

在Column的children末尾添加登录按钮,绑定登录方法:

ElevatedButton(
  onPressed: _isLoading ? null : _login,
  child: _isLoading
      ? const CircularProgressIndicator(color: Colors.white)
      : const Text('登录'),
),

完整代码示例

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '登录示例',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const LoginPage(),
    );
  }
}

class LoginPage extends StatefulWidget {
  const LoginPage({super.key});

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  bool _isLoading = false;

  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  Future<void> _login() async {
    final email = _emailController.text.trim();
    final password = _passwordController.text.trim();

    if (email.isEmpty || password.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('账号或密码不能为空')),
      );
      return;
    }

    setState(() {
      _isLoading = true;
    });

    try {
      await Future.delayed(const Duration(seconds: 2));
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('登录成功')),
      );
      // Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const HomePage()));
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('登录失败:${e.toString()}')),
      );
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('用户登录'),
        centerTitle: true,
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 24.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            const FlutterLogo(size: 100.0),
            const SizedBox(height: 48.0),
            TextField(
              controller: _emailController,
              keyboardType: TextInputType.emailAddress,
              decoration: const InputDecoration(
                hintText: '输入邮箱或用户名',
                labelText: '账号',
                border: OutlineInputBorder(),
              ),
            ),
            const SizedBox(height: 16.0),
            TextField(
              controller: _passwordController,
              obscureText: true,
              decoration: const InputDecoration(
                hintText: '输入密码',
                labelText: '密码',
                border: OutlineInputBorder(),
              ),
            ),
            const SizedBox(height: 24.0),
            ElevatedButton(
              onPressed: _isLoading ? null : _login,
              child: _isLoading
                  ? const CircularProgressIndicator(color: Colors.white)
                  : const Text('登录'),
            ),
          ],
        ),
      ),
    );
  }
}

// 示例主页(可根据需求实现)
// class HomePage extends StatelessWidget {
//   const HomePage({super.key});

//   @override
//   Widget build(BuildContext context) {
//     return Scaffold(
//       appBar: AppBar(title: const Text('主页')),
//       body: const Center(child: Text('登录成功!')),
//     );
//   }
// }

内容的提问来源于stack exchange,提问作者Amirah. H.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 09:26:01