Flutter – 神经拟态按钮
Flutter包含各种内置按钮类型,如 RaisedButton、FlatButton 等。但是在 GestureDetector 的帮助下,我们可以使任何小部件对某些手势执行一组操作。在本文中,我们将使用 AnimatedContainer 在Flutter中制作 Neumorphic Button。创建按钮的传统方法包括使用阴影,但它让人感觉按钮悬停在背景上。但是在Neumorphism中,我们使用了两种类型的阴影——一侧是亮的,另一侧是暗的,这使得按钮感觉就像是附着在背景上而不是悬停在它上面。我们将使用 VS 代码来开发我们的Flutter应用程序。
分步实施
第 1 步:创建一个新的Flutter应用程序。
- 打开 VS 代码,使用“Ctrl+Shift+P”选择“Flutter: New Project”。
- 选择要在其中创建应用程序的文件夹。
- 然后为您的应用程序命名。
- 按“Enter”后, Flutter SDK 将为您创建一个新项目。
第 2 步:创建项目后打开“main. dart”文件并将下面的代码粘贴到其中。
Dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is root
// of your application
@override
Widget build(BuildContext context) {
return MaterialApp(
// By using this line,
// you can hide Debug banner
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const NeumorphismPage(),
);
}
}
Dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const NeumorphismPage(),
);
}
}
// Widget that will be shown
// at the start of application.
class NeumorphismPage extends StatefulWidget {
const NeumorphismPage({Key? key}) : super(key: key);
@override
State createState() => _NeumorphismPageState();
}
class _NeumorphismPageState extends State {
bool _isElevated = false;
@override
Widget build(BuildContext context) {
// Create your widget here.
return Scaffold();
}
}
Dart
class NeumorphismPage extends StatefulWidget {
const NeumorphismPage({Key? key}) : super(key: key);
@override
State createState() => _NeumorphismPageState();
}
class _NeumorphismPageState extends State {
// Boolean to check whether the
// button is elevated or not.
bool _isElevated = false;
@override
Widget build(BuildContext context) {
return Scaffold(
// Providing background
// color to our Scaffold
backgroundColor: Colors.grey[300],
body: Center(
// Gesture Detector to detect taps
child: GestureDetector(
onTap: () {
setState(() {
_isElevated = !_isElevated;
});
},
child: AnimatedContainer(
child: Image.asset(
"assets/gfg.png",
scale: 3,
),
// Providing duration parameter
// to create animation
duration: const Duration(
milliseconds: 200,
),
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.grey[300],
shape: BoxShape.circular,
// If widget is not elevated, elevate it.
boxShadow: _isElevated
?
// Elevation Effect
[
const BoxShadow(
color: Color(0xFFBEBEBE),
// Shadow for bottom right corner
offset: Offset(10, 10),
blurRadius: 30,
spreadRadius: 1,
),
const BoxShadow(
color: Colors.white,
// Shadow for top left corner
offset: Offset(-10, -10),
blurRadius: 30,
spreadRadius: 1,
),
]
: null,
),
),
),
),
);
}
}
Dart
class NeumorphismPage extends StatefulWidget {
const NeumorphismPage({Key? key}) : super(key: key);
@override
State createState() => _NeumorphismPageState();
}
class _NeumorphismPageState extends State {
bool _isElevated = false;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[300],
body: Center(
child: GestureDetector(
onTap: () {
setState(() {
_isElevated = !_isElevated;
});
},
child: AnimatedContainer(
child: Icon(
Icons.power_settings_new,
size: 80,
// Changing icon color on
// the basis of it's elevation
color:
_isElevated ? Colors.grey : Color.fromARGB(255, 83, 220, 230),
),
// Providing duration parameter
// to create animation
duration: const Duration(
milliseconds: 200,
),
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.grey[300],
shape: BoxShape.circle,
// when _isElevated is false, value
// of inset parameter will be true
// that will create depth effect.
boxShadow: _isElevated
?
// Elevated Effect
[
const BoxShadow(
color: Color(0xFFBEBEBE),
// Shadow for bottom right corner
offset: Offset(10, 10),
blurRadius: 30,
spreadRadius: 1,
inset: false,
),
const BoxShadow(
color: Colors.white,
// Shadow for top left corner
offset: Offset(-10, -10),
blurRadius: 30,
spreadRadius: 1,
inset: false,
),
]
:
// Depth Effect
[
const BoxShadow(
color: Color(0xFFBEBEBE),
// Shadow for bottom right corner
offset: Offset(10, 10),
blurRadius: 30,
spreadRadius: 1,
inset: true,
),
const BoxShadow(
color: Colors.white,
// Shadow for top left corner
offset: Offset(-10, -10),
blurRadius: 30,
spreadRadius: 1,
inset: true,
),
],
),
),
),
),
);
}
}
第 3 步:在 MyApp 小部件下方创建一个有状态小部件,并将其命名为 NeumorphismPage。在 VS Code 中,您可以尝试输入“stl”并在自动完成中选择有状态小部件或粘贴以下代码。这是“主要”的代码。dart”文件。
Dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const NeumorphismPage(),
);
}
}
// Widget that will be shown
// at the start of application.
class NeumorphismPage extends StatefulWidget {
const NeumorphismPage({Key? key}) : super(key: key);
@override
State createState() => _NeumorphismPageState();
}
class _NeumorphismPageState extends State {
bool _isElevated = false;
@override
Widget build(BuildContext context) {
// Create your widget here.
return Scaffold();
}
}
Note: You can create a separate dart file for each widget and then import it but as it is only a single widget we will only create one file.
第 4 步:以下是创建 Neumorphic 按钮的代码。
示例 1
在这个例子中,按下按钮后它会变平。
Dart
class NeumorphismPage extends StatefulWidget {
const NeumorphismPage({Key? key}) : super(key: key);
@override
State createState() => _NeumorphismPageState();
}
class _NeumorphismPageState extends State {
// Boolean to check whether the
// button is elevated or not.
bool _isElevated = false;
@override
Widget build(BuildContext context) {
return Scaffold(
// Providing background
// color to our Scaffold
backgroundColor: Colors.grey[300],
body: Center(
// Gesture Detector to detect taps
child: GestureDetector(
onTap: () {
setState(() {
_isElevated = !_isElevated;
});
},
child: AnimatedContainer(
child: Image.asset(
"assets/gfg.png",
scale: 3,
),
// Providing duration parameter
// to create animation
duration: const Duration(
milliseconds: 200,
),
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.grey[300],
shape: BoxShape.circular,
// If widget is not elevated, elevate it.
boxShadow: _isElevated
?
// Elevation Effect
[
const BoxShadow(
color: Color(0xFFBEBEBE),
// Shadow for bottom right corner
offset: Offset(10, 10),
blurRadius: 30,
spreadRadius: 1,
),
const BoxShadow(
color: Colors.white,
// Shadow for top left corner
offset: Offset(-10, -10),
blurRadius: 30,
spreadRadius: 1,
),
]
: null,
),
),
),
),
);
}
}
输出:
示例 2
在这个小部件中,按下按钮后,它将创建嵌入阴影。在此之前,我们需要添加一个包。
flutter pub add flutter_inset_box_shadow
然后文件开头的导入应更改如下:
import 'package:flutter/material.dart' hide BoxDecoration, BoxShadow;
import 'package:flutter_inset_box_shadow/flutter_inset_box_shadow.dart';
// As both packages contains BoxDecoration and BoxShadow, so hiding them in from one of the package to avoid Diamond Problem
导入后,我们将使用下面的代码创建嵌入阴影。
Dart
class NeumorphismPage extends StatefulWidget {
const NeumorphismPage({Key? key}) : super(key: key);
@override
State createState() => _NeumorphismPageState();
}
class _NeumorphismPageState extends State {
bool _isElevated = false;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[300],
body: Center(
child: GestureDetector(
onTap: () {
setState(() {
_isElevated = !_isElevated;
});
},
child: AnimatedContainer(
child: Icon(
Icons.power_settings_new,
size: 80,
// Changing icon color on
// the basis of it's elevation
color:
_isElevated ? Colors.grey : Color.fromARGB(255, 83, 220, 230),
),
// Providing duration parameter
// to create animation
duration: const Duration(
milliseconds: 200,
),
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.grey[300],
shape: BoxShape.circle,
// when _isElevated is false, value
// of inset parameter will be true
// that will create depth effect.
boxShadow: _isElevated
?
// Elevated Effect
[
const BoxShadow(
color: Color(0xFFBEBEBE),
// Shadow for bottom right corner
offset: Offset(10, 10),
blurRadius: 30,
spreadRadius: 1,
inset: false,
),
const BoxShadow(
color: Colors.white,
// Shadow for top left corner
offset: Offset(-10, -10),
blurRadius: 30,
spreadRadius: 1,
inset: false,
),
]
:
// Depth Effect
[
const BoxShadow(
color: Color(0xFFBEBEBE),
// Shadow for bottom right corner
offset: Offset(10, 10),
blurRadius: 30,
spreadRadius: 1,
inset: true,
),
const BoxShadow(
color: Colors.white,
// Shadow for top left corner
offset: Offset(-10, -10),
blurRadius: 30,
spreadRadius: 1,
inset: true,
),
],
),
),
),
),
);
}
}
输出: