なんか、毎回ログイン画面作ってる気が...
新たなサービスを実装するとき、なんか、毎回作ってる気がする…
いや、多分気のせいではない!まぁ、サービス毎にデザインが違ったりするので全く同じモノを作るわけではないけど、機能的には同じじゃないの?
というわけで、
そういう意味での雛形を作っておけばええんでないかぇ?
という事に、さっき気がついたので、雛形を貼り付けておきますw
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: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const LoginPage(),
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: LoginForm(
elevation: 4,
onLogin: (email, password, rememberMe) {
print(email);
print(password);
print(rememberMe);
},
),
),
);
}
}
class LoginForm extends StatefulWidget {
final double elevation;
final Function(String email, String password, bool rememberMe)? onLogin;
final Color color;
const LoginForm({
super.key,
this.elevation = 0.0,
this.color = Colors.white,
this.onLogin,
});
@override
State<StatefulWidget> createState() => LoginFormState();
}
class LoginFormState extends State<LoginForm> {
bool isObscure = true;
bool rememberMe = false;
final userId = TextEditingController();
final password = TextEditingController();
final GlobalKey<FormState> loginFormKey = GlobalKey<FormState>();
@override
void initState() {
isObscure = true;
super.initState();
}
@override
Widget build(BuildContext context) {
final themeColor = Theme.of(context).primaryColor;
return Form(
key: loginFormKey,
child: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(30),
decoration: BoxDecoration(
color: widget.color,
borderRadius: BorderRadius.circular(8.0),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.6),
blurRadius: widget.elevation,
)
],
),
child: SizedBox(
width: 300,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Welcome back',
style: TextStyle(
fontSize: 17,
color: Colors.black,
),
),
const SizedBox(height: 8),
const Text(
'Login to your account',
style: TextStyle(
fontSize: 23,
color: Colors.black,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 35),
TextFormField(
controller: userId,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "e-mail",
prefixIcon: Icon(
Icons.email,
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
const SizedBox(height: 20),
TextFormField(
controller: password,
obscureText: isObscure,
decoration: InputDecoration(
border: const OutlineInputBorder(),
hintText: "password",
prefixIcon: const Icon(
Icons.lock,
),
suffixIcon: GestureDetector(
child: Icon(
isObscure ? Icons.visibility_off : Icons.visibility,
),
onTap: () {
setState(() {
isObscure = !isObscure;
});
},
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
const SizedBox(height: 25),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Checkbox(
value: rememberMe,
onChanged: (value) {
if (value != null) {
setState(() {
rememberMe = value;
});
}
},
),
const Text(
'Remember me',
),
],
),
const SizedBox(height: 30),
MaterialButton(
color: themeColor,
elevation: 4,
height: 50,
onPressed: () {
if (loginFormKey.currentState!.validate()) {
if (widget.onLogin != null) {
widget.onLogin!(
userId.text,
password.text,
rememberMe,
);
}
}
},
child: const Text(
'LOGIN',
),
),
],
),
),
),
),
);
}
}
この記事が気に入ったらサポートをしてみませんか?