Flutter 颜色渐变及模仿淘宝渐变关注按钮
Posted 一叶飘舟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter 颜色渐变及模仿淘宝渐变关注按钮相关的知识,希望对你有一定的参考价值。
一、线性颜色渐变
实现一个容器,大多使用 Container Widget,边框 border 通过 decoration
属性控制,而 BoxDecoration
除了支持 border 的控制外,还支持 gradient
的控制。
const BoxDecoration(
this.color,
this.image,
this.border,
this.borderRadius,
this.boxShadow,
this.gradient,
this.backgroundBlendMode,
this.shape = BoxShape.rectangle,
)
一般情况下都是使用线性渐变,Fultter 中通过 LinearGradient
来支持实现线性渐变
// 线性渐变
Container(
width: 200,
height: 100,
decoration: BoxDecoration(
gradient: LinearGradient(
// Alignment(x,y) (0,0) 是由 rectangle 中心点计算的
begin: Alignment(0.0, -1.0),
end: Alignment(0.0, 1.0),
colors: <Color>[
Color(0xFFFF5000),
Color(0xFFFF9000),
Colors.black,
],
),
),
),
LinearGradient
定义如下:
const LinearGradient(
this.begin = Alignment.centerLeft,
this.end = Alignment.centerRight,
@required List<Color> colors,
List<double> stops,
this.tileMode = TileMode.clamp,
)
colors
可以传入多个颜色,用来实现渐变
默认值是 Aligment.centerLeft
和 Aligment.centerRight
关于 Aligment 默认属性和 (x,y) 坐标的关系简单如下:
/// The top left corner.
static const Alignment topLeft = Alignment(-1.0, -1.0);
/// The center point along the top edge.
static const Alignment topCenter = Alignment(0.0, -1.0);
/// The top right corner.
static const Alignment topRight = Alignment(1.0, -1.0);
/// The center point along the left edge.
static const Alignment centerLeft = Alignment(-1.0, 0.0);
/// The center point, both horizontally and vertically.
static const Alignment center = Alignment(0.0, 0.0);
/// The center point along the right edge.
static const Alignment centerRight = Alignment(1.0, 0.0);
/// The bottom left corner.
static const Alignment bottomLeft = Alignment(-1.0, 1.0);
/// The center point along the bottom edge.
static const Alignment bottomCenter = Alignment(0.0, 1.0);
/// The bottom right corner.
static const Alignment bottomRight = Alignment(1.0, 1.0);
Flutter 中 View(典型表现是 Container Widget)中心点(0,0)实际上是真正的中心位置,而不是平常理解的 topLeft
这个点
所以上面渐变的效果如下:
二、横向线性渐变
上面实现的是纵向线性渐变,如果要使用横向的线性渐变,其实就是将 start 和 begin 的点改变一下:
Container(
width: 200,
height: 50,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment(-1, 0),
end: Alignment(1.0, 0),
colors: <Color>[
const Color(0xFFFF5000),
const Color(0xFFFF9000),
],
),
),
),
Alignment(-1, 0)
表示左边中间,Alignment(1.0, 0)
表示右边中间
效果:
三、模拟手机淘宝的关注按钮
这个关注按钮核心是一个 radius 的形状以及横向的线性颜色渐变
从 iconfont 找到一个微淘的关注图标(白色的,这里看不见):
尴尬的是这个图标是白色的,贴在这里看不出来。搞个背景色如下所示:
颜色渐变分析下来是:const Color(0xFFFF5000), const Color(0xFFFF9000)
除此之外,点击关注后,变成已关注的文案,并且可以多次改变状态
实现:
class FollowWidget extends StatefulWidget
FollowWidget(Key key) : super(key: key);
_FollowWidgetState createState() => _FollowWidgetState();
class _FollowWidgetState extends State<FollowWidget>
bool _followStatus = false;
void _followClickHandle()
setState(()
this._followStatus = !this._followStatus;
);
List<Color> _getGradient()
if (this._followStatus)
return <Color>[Colors.grey, Colors.grey];
else
return <Color>[const Color(0xFFFF5000), const Color(0xFFFF9000)];
List<Widget> _getContent()
List<Widget> defaultContent = <Widget>[
Text(
this._followStatus ? '已关注' : '关注',
style: TextStyle(
fontSize: 16,
color: Colors.white,
letterSpacing: 1.2,
),
)
];
List<Widget> prefixContent = <Widget>[
Image.network(
'https://gw.alicdn.com/tfs/TB1OC0TXMMPMeJjy1XcXXXpppXa-108-84.png',
height: 16,
),
SizedBox(width: 3)
];
if (!this._followStatus)
defaultContent.insertAll(0, prefixContent);
return defaultContent;
@override
Widget build(BuildContext context)
return InkWell(
child: Container(
width: 90,
height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
gradient: LinearGradient(
begin: Alignment(-1, 0),
end: Alignment(1.0, 0),
colors: this._getGradient(),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: this._getContent(),
),
),
onTap: this._followClickHandle,
);
效果:
四、完整代码
FlutterHelloWorld/main.45-颜色渐变-follow组件.dart at dev1 · postbird/FlutterHelloWorld · GitHub
FlutterHelloWorld/main.45-2-渐变关注按钮.dart at dev1 · postbird/FlutterHelloWorld · GitHub
如果打不开github,看这里的源码即可。
import 'package:flutter/material.dart';
void main()
runApp(MyApp());
class MyApp extends StatelessWidget
const MyApp(Key key) : super(key: key);
@override
Widget build(BuildContext context)
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('渐变'),
),
body: HomeContent(),
),
);
class HomeContent extends StatelessWidget
const HomeContent(Key key) : super(key: key);
@override
Widget build(BuildContext context)
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 径向渐变
Container(
width: 200,
height: 100,
decoration: BoxDecoration(
gradient: LinearGradient(
// Alignment(x,y) (0,0) 是由 rectangle 中心点计算的
begin: Alignment(0.0, -1.0),
end: Alignment(0.0, 1.0),
colors: <Color>[
Color(0xFFFF5000),
Color(0xFFFF9000),
Colors.black,
],
),
),
),
SizedBox(height: 10),
// 横向渐变
Container(
width: 200,
height: 50,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment(-1, 0),
end: Alignment(1.0, 0),
colors: <Color>[
const Color(0xFFFF5000),
const Color(0xFFFF9000),
],
),
),
),
SizedBox(height: 10),
FollowWidget(),
],
),
);
class FollowWidget extends StatefulWidget
FollowWidget(Key key) : super(key: key);
_FollowWidgetState createState() => _FollowWidgetState();
class _FollowWidgetState extends State<FollowWidget>
bool _followStatus = false;
void _followClickHandle()
setState(()
this._followStatus = !this._followStatus;
);
List<Color> _getGradient()
if (this._followStatus)
return <Color>[Colors.grey, Colors.grey];
else
return <Color>[const Color(0xFFFF5000), const Color(0xFFFF9000)];
List<Widget> _getContent()
List<Widget> defaultContent = <Widget>[
Text(
this._followStatus ? '已关注' : '关注',
style: TextStyle(
fontSize: 16,
color: Colors.white,
letterSpacing: 1.2,
),
)
];
List<Widget> prefixContent = <Widget>[
Image.network(
'https://gw.alicdn.com/tfs/TB1OC0TXMMPMeJjy1XcXXXpppXa-108-84.png',
height: 16,
),
SizedBox(width: 3)
];
if (!this._followStatus)
defaultContent.insertAll(0, prefixContent);
return defaultContent;
@override
Widget build(BuildContext context)
return InkWell(
child: Container(
width: 90,
height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
gradient: LinearGradient(
begin: Alignment(-1, 0),
end: Alignment(1.0, 0),
colors: this._getGradient(),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: this._getContent(),
),
),
onTap: this._followClickHandle,
);
import 'package:flutter/material.dart';
void main()
runApp(MyApp());
class MyApp extends StatelessWidget
const MyApp(Key key) : super(key: key);
@override
Widget build(BuildContext context)
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('AnimatedContainer Follow'),
),
body: FollowWidget(),
),
);
class FollowWidget extends StatefulWidget
FollowWidget(Key key) : super(key: key);
_FollowWidgetState createState() => _FollowWidgetState();
class _FollowWidgetState extends State<FollowWidget>
bool _followStatus = false;
void _followClickHandle()
setState(()
this._followStatus = !this._followStatus;
);
List<Color> _getGradient()
if (this._followStatus)
return <Color>[Colors.grey, Colors.grey];
else
return <Color>[const Color(0xFFFF5000), const Color(0xFFFF9000)];
List<Widget> _getContent()
List<Widget> defaultContent = <Widget>[
Text(
this._followStatus ? '已关注' : '关注',
style: TextStyle(
fontSize: 16,
color: Colors.white,
letterSpacing: 1.2,
),
)
];
List<Widget> prefixContent = <Widget>[
Image.network(
'https://gw.alicdn.com/tfs/TB1OC0TXMMPMeJjy1XcXXXpppXa-108-84.png',
height: 16,
),
SizedBox(width: 3)
];
if (!this._followStatus)
defaultContent.insertAll(0, prefixContent);
return defaultContent;
@override
Widget build(BuildContext context)
return InkWell(
child: AnimatedContainer(
width: 90,
height: 40,
duration: Duration(milliseconds: 500),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
gradient: LinearGradient(
begin: Alignment(-1, 0),
end: Alignment(1.0, 0),
colors: this._getGradient(),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: this._getContent(),
),
),
onTap: this._followClickHandle,
);
以上是关于Flutter 颜色渐变及模仿淘宝渐变关注按钮的主要内容,如果未能解决你的问题,请参考以下文章