Flutter實現矩形取色器的封裝
前言
最近看插件庫上少有的取色器大都是圓形的或者奇奇怪的的亞子,所以今天做兩個矩形的顏色取色器
提示:以下是本篇文章正文內容,下面案例可供參考
一、BarTypeColorPicker
條形選色板的功能實現,顏色的獲取是通過位置來判斷,然後賦予相應的顏色。這個封裝好的組件可通過colorListener、onTapUpListener的回調方法,把顏色傳出去。
代碼如下(示例):
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; ///描述:條形選色板 class BarTypeColorPicker extends StatefulWidget { final Color initialColor; final ValueChanged<Color> colorListener; final ValueChanged<Color> onTapUpListener; final int colorWidth; final int colorHeight; final Color color; const BarTypeColorPicker( {Key key, this.initialColor, this.colorListener, this.onTapUpListener, this.colorWidth, this.colorHeight, this.color}) : super(key: key); @override _BarTypeColorPickerState createState() => _BarTypeColorPickerState( colorWidth.toDouble(), colorHeight.toDouble(), ); } class _BarTypeColorPickerState extends State<BarTypeColorPicker> { double _top = 0.0; double _left = 0.0; double _Thumbsize = 20; double lightness; double _colorwidth; double _colorHeight; Color _color; _BarTypeColorPickerState(double colorwidth, double colorHeight) { this._colorwidth = colorwidth; this._colorHeight = colorHeight; } @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return Center( child: GestureDetector( onPanStart: (DragStartDetails detail) { var localPosition = detail.localPosition; buildSetState(localPosition, context); if (widget.colorListener != null) { widget.colorListener(_color); } }, onPanDown: (DragDownDetails detail) { var localPosition = detail.localPosition; buildSetState(localPosition, context); if (widget.colorListener != null) { widget.colorListener(_color); } }, onPanUpdate: (DragUpdateDetails detail) { var localPosition = detail.localPosition; buildSetState(localPosition, context); if (widget.colorListener != null) { widget.colorListener(_color); } }, onPanEnd: (DragEndDetails detail) { if (widget.onTapUpListener != null) { widget.onTapUpListener(_color); } }, onTapUp: (TapUpDetails detail) { if (widget.onTapUpListener != null) { widget.onTapUpListener(_color); } }, child: ColorRect( colorHeight: _colorHeight, colorwidth: _colorwidth, top: _top, Thumbsize: _Thumbsize, left: _left, color: _color), ), ); } void buildSetState(Offset localPosition, BuildContext context) { return setState(() { _left = localPosition.dx; _top = localPosition.dy; if (_left < 0) { _left = 0; } else if (0 <= _left && _left <= _colorwidth) { _left = _left; } else if (_left > _colorwidth) { _left = (_colorwidth); } if ((_colorwidth / 7) * 0 < _left && _left < (_colorwidth / 7) * 1) { _color = Color(0xFFFF0000); } else if ((_colorwidth / 7) * 1 < _left && _left < (_colorwidth / 7) * 2) { _color = Color(0xFFFFFF00); } else if ((_colorwidth / 7) * 2 < _left && _left < (_colorwidth / 7) * 3) { _color = Color(0xFF00FF00); } else if ((_colorwidth / 7) * 3 < _left && _left < (_colorwidth / 7) * 4) { _color = Color(0xFF00FFFF); } else if ((_colorwidth / 7) * 4 < _left && _left < (_colorwidth / 7) * 5) { _color = Color(0xFF0000FF); } else if ((_colorwidth / 7) * 5 < _left && _left < (_colorwidth / 7) * 6) { _color = Color(0xFFFF00FF); } else if ((_colorwidth / 7) * 6 < _left && _left < (_colorwidth / 7) * 7) { _color = Color(0xFFFFFFFF); } if (_top <= 0) { _top = 0; } else if (0 <= _top && _top <= _colorHeight) { } else if (_top > _colorHeight) { _top = _colorHeight; } }); } } class ColorRect extends StatelessWidget { ColorRect({ Key key, @required double colorHeight, @required double colorwidth, @required double top, @required double Thumbsize, @required double left, @required Color color, }) : _colorHeight = colorHeight, _colorwidth = colorwidth, _top = top, _Thumbsize = Thumbsize, _left = left, _color = color, super(key: key); final double _colorHeight; final double _colorwidth; final double _top; final double _Thumbsize; final double _left; final Color _color; List<Color> colorList = [ Color(0xFFFF0000), Color(0xFFFFFF00), Color(0xFF00FF00), Color(0xFF00FFFF), Color(0xFF0000FF), Color(0xFFFF00FF), Color(0xFFFFFFFF), ]; @override Widget build(BuildContext context) { return Container( width: _colorwidth, height: _colorHeight, child: Stack( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: colorList .map( (e) => Container( padding: EdgeInsets.symmetric(horizontal: 2), height: _colorHeight, width: _colorwidth / 7, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), color: e, ), ), ), ) .toList(), ), Container( child: Thumb( top: _top, Thumbsize: _Thumbsize, left: _left, color: _color)), ], ), ); } } class Thumb extends StatelessWidget { const Thumb({ Key key, @required double top, @required double Thumbsize, @required double left, @required Color color, }) : _top = top, _Thumbsize = Thumbsize, _left = left, _color = color, super(key: key); final double _top; final double _Thumbsize; final double _left; final Color _color; @override Widget build(BuildContext context) { return Positioned( top: _top - _Thumbsize / 2, left: _left - _Thumbsize / 2, child: GestureDetector( child: Container( child: Icon( Icons.circle, color: _color, size: _Thumbsize, ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( blurRadius: 0.1, //陰影范圍 spreadRadius: 0.001, //陰影濃度 color: Colors.black, //陰影顏色 ), ], ), ))); } }
下面是使用方法。
BarTypeColorPicker( initialColor: Colors.white, colorWidth: 360, colorHeight: 150, ),
具體效果圖:
一、RectangleColorPicker
矩形選色板的功能實現,顏色的獲取是通過位置的坐標值轉換為相應的顏色。這個封裝好的組件可通過colorListener、onTapUpListener的回調方法,把顏色傳出去。
代碼如下(示例):
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class RectangleColorPicker extends StatefulWidget { final Color initialColor; final ValueChanged<Color> colorListener; final ValueChanged<Color> onTapUpListener; final int colorWidth; final int colorHeight; final Color color; const RectangleColorPicker( {Key key, this.initialColor, this.colorListener, this.onTapUpListener, this.colorWidth, this.colorHeight, this.color}) : super(key: key); @override _RectangleColorPickerState createState() => _RectangleColorPickerState( colorWidth.toDouble(), colorHeight.toDouble(), ); } class _RectangleColorPickerState extends State<RectangleColorPicker> { double _top = 0.0; double _left = 0.0; double _Thumbsize = 20; double _hue = 0.0; double _brightnum = 50.0; double lightness; double _colorwidth; double _colorHeight; _RectangleColorPickerState(double colorwidth, double colorHeight) { this._colorwidth = colorwidth; this._colorHeight = colorHeight; } Color get _color { return HSLColor.fromAHSL( 1, _hue, 1, lightness, ).toColor(); //返回HSL、AHSL格式的色調亮度字符串 } @override void initState() { super.initState(); HSLColor hslColor = HSLColor.fromColor(widget.initialColor); _left = (_colorwidth * hslColor.hue) / 360; _top = (_colorHeight * (hslColor.lightness - 0.5) * 200) / 100; this._hue = hslColor.hue; this.lightness = hslColor.lightness; } @override Widget build(BuildContext context) { return Center( child: GestureDetector( onPanStart: (DragStartDetails detail) { var localPosition = detail.localPosition; buildSetState(localPosition, context); if(widget.colorListener != null){ widget.colorListener(_color); } }, onPanDown: (DragDownDetails detail) { var localPosition = detail.localPosition; buildSetState(localPosition, context); if(widget.colorListener != null){ widget.colorListener(_color); } }, onPanUpdate: (DragUpdateDetails detail) { //獲取當前觸摸點的局部坐標 var localPosition = detail.localPosition; buildSetState(localPosition, context); if(widget.colorListener != null){ widget.colorListener(_color); } }, onPanEnd: (DragEndDetails detail) { if(widget.onTapUpListener != null){ widget.onTapUpListener(_color); } }, onTapUp: (TapUpDetails detail){ if(widget.onTapUpListener != null){ widget.onTapUpListener(_color); } }, child: ColorRect( colorHeight: _colorHeight, colorwidth: _colorwidth, top: _top, Thumbsize: _Thumbsize, left: _left, color: _color), ), ); } void buildSetState(Offset localPosition, BuildContext context) { return setState(() { _left = localPosition.dx; _top = localPosition.dy; if (_left < 0) { _left = 0; } else if (0 <= _left && _left <= _colorwidth) { _left = _left; _hue = (360 * _left) / (_colorwidth); } else if (_left > _colorwidth) { _left = (_colorwidth); _hue = 360; } if (((5 / 360 - 5 / 360) < _left && _left < (5 / 360 + 5 / 360) * _colorwidth) && (_top < 5)) { _left = 5 / 360 * _colorwidth; _top = 0; } else if ((((5 + 350 / 6) / 360 - 5 / 360) * _colorwidth < _left && _left < ((5 + 350 / 6) / 360 + 5 / 360) * _colorwidth) && (_top < 5)) { _left = (5 + (1 * 350) / 6) / 360 * _colorwidth; _top = 0; } else if ((((5 + (2 * 350) / 6) / 360 - 5 / 360) * _colorwidth < _left && _left < ((5 + (2 * 350) / 6) / 360 + 5 / 360) * _colorwidth) && (_top < 5)) { _left = (5 + (2 * 350) / 6) / 360 * _colorwidth; _top = 0; } else if ((((5 + (3 * 350) / 6) / 360 - 5 / 360) * _colorwidth < _left && _left < ((5 + (3 * 350) / 6) / 360 + 5 / 360) * _colorwidth) && (_top < 5)) { _left = (5 + (3 * 350) / 6) / 360 * _colorwidth; _top = 0; } else if ((((5 + (4 * 350) / 6) / 360 - 5 / 360) * _colorwidth < _left && _left < ((5 + (4 * 350) / 6) / 360 + 5 / 360) * _colorwidth) && (_top < 5)) { _left = (5 + (4 * 350) / 6) / 360 * _colorwidth; _top = 0; } else if ((((5 + (5 * 350) / 6) / 360 - 5 / 360) * _colorwidth < _left && _left < ((5 + (5 * 350) / 6) / 360 + 5 / 360) * _colorwidth) && (_top < 5)) { _left = (5 + (5 * 350) / 6) / 360 * _colorwidth; _top = 0; } else if ((((5 + (6 * 350) / 6) / 360 - 5 / 360) * _colorwidth < _left && _left < ((5 + (6 * 350) / 6) / 360 + 5 / 360)) && (_top < 5)) { _left = (5 + (6 * 350) / 6) / 360 * _colorwidth; _top = 0; } if (_top <= 0) { _top = 0; _brightnum = 50; lightness = _brightnum / 100; } else if (0 <= _top && _top <= _colorHeight) { _brightnum = (100 * _top) / _colorHeight / 2 + 50; lightness = _brightnum / 100; } else if (_top > _colorHeight) { _top = _colorHeight; _brightnum = 100; lightness = _brightnum / 100; } }); } } class ColorRect extends StatelessWidget { const ColorRect({ Key key, @required double colorHeight, @required double colorwidth, @required double top, @required double Thumbsize, @required double left, @required Color color, }) : _colorHeight = colorHeight, _colorwidth = colorwidth, _top = top, _Thumbsize = Thumbsize, _left = left, _color = color, super(key: key); final double _colorHeight; final double _colorwidth; final double _top; final double _Thumbsize; final double _left; final Color _color; @override Widget build(BuildContext context) { return Container( child: Stack( children: [ Container( child: ClipRRect( borderRadius: BorderRadius.circular(10), child: DecoratedBox( child: Container( height: _colorHeight, width: _colorwidth, ), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.centerLeft, end: Alignment.centerRight, stops: [ 0, 5 / 360, (5 + 350 / 6) / 360, (5 + (2 * 350) / 6) / 360, (5 + (3 * 350) / 6) / 360, (5 + (4 * 350) / 6) / 360, (5 + (5 * 350) / 6) / 360, (5 + (6 * 350) / 6) / 360, 1.0 ], colors: [ Color.fromARGB(255, 255, 0, 0), Color.fromARGB(255, 255, 0, 0), Color.fromARGB(255, 255, 255, 0), Color.fromARGB(255, 0, 255, 0), Color.fromARGB(255, 0, 255, 255), Color.fromARGB(255, 0, 0, 255), Color.fromARGB(255, 255, 0, 255), Color.fromARGB(255, 255, 0, 0), Color.fromARGB(255, 255, 0, 0), ], ), )), ), ), Container( child: ClipRRect( borderRadius: BorderRadius.circular(10), child: DecoratedBox( child: Container( height: _colorHeight, width: _colorwidth, ), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color.fromARGB(0, 255, 255, 255), Colors.white, ], ), )), ), ), Container( child: Thumb( top: _top, Thumbsize: _Thumbsize, left: _left, color: _color)), ], ), ); } } class Thumb extends StatelessWidget { const Thumb({ Key key, @required double top, @required double Thumbsize, @required double left, @required Color color, }) : _top = top, _Thumbsize = Thumbsize, _left = left, _color = color, super(key: key); final double _top; final double _Thumbsize; final double _left; final Color _color; @override Widget build(BuildContext context) { return Positioned( top: _top - _Thumbsize / 2, left: _left - _Thumbsize / 2, child: GestureDetector( child: Container( child: Icon( Icons.circle, color: _color, size: _Thumbsize, ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( blurRadius: 0.1, //陰影范圍 spreadRadius: 0.001, //陰影濃度 color: Colors.black, //陰影顏色 ), ], ), ))); } }
下面是使用方法。
RectangleColorPicker( [initialColor: Colors.white, colorWidth: 360, colorHeight: 150, onTapUpListener: (_color) { } colorListener: (_color) { } ] ),
具體效果圖:
總結
提示:這裡對文章進行總結:
例如:以上就是今天要講的內容,本文僅僅簡單介紹瞭兩種顏色選色板的使用,後面還會陸續發佈一些flutter的組件使用教程。
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Flutter LinearProgressIndicator使用指南分析
- Android Flutter制作一個修改組件屬性的動畫
- Flutter瀑佈流仿寫原生的復用機制詳解
- Flutter Component動畫的顯和隱最佳實踐
- flutter封裝單選點擊菜單工具欄組件