实现效果
初始化代码
CodeReview(
//设置初始字符串,此处有个坑,很是郁闷,暂缓解决方案
// initState 中设置回调后不可以调用 setState 方法否则报错,否则运行出错
// widget.onTap(randString);
text: randomAlphaNumeric(4),
onTap: (text) {
// 点击后变化的字符串
},
),
插件呢只用了一个
random_string: ^1.1.0
现学现卖,果然还是有部分问题
实现思路,字母展示很简单,随机字母大小,随机pandding的高度,在row中展示即可。背景实现我用的事线条绘制,但遇到一些问题,暂时没有解决,只能单色线条了。 实际使用中,一般是后台生成图片进行校正,我这只是自娱自乐,还没有乐起来,着实伤心。。。
flutter 好一点的事计算文字,完全可以按照文字大小设置承载组建的size。因为很简单然后我就直接上代码了。
import 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:no_alone/code_paint.dart';
import 'package:no_alone/tools/dzy_theme.dart';
import 'package:random_string/random_string.dart';
// 当前存在的问题是,必须在外部调用的时候给一个初始值
class CodeReview extends StatefulWidget {
CodeReview({Key key, this.text, this.onTap}) : super(key: key);
final String text;
final onTap;
_CodeReviewState createState() => _CodeReviewState();
}
class _CodeReviewState extends State {
String _ranStr;
int _textLength;
double _width;
double _height;
List _lineOffsets = [];
Color _ranColor = DzyTheme.randomColor();
void _randLines() {
_lineOffsets.clear();
for (var i = 0; i < _textLength; i++) {
double fromX = randomBetween(10, 20).toDouble();
double fromY = randomBetween(3, 33).toDouble();
Offset from = Offset(fromX, fromY);
_lineOffsets.add(from);
double endX = randomBetween(60, _width.toInt() - 10).toDouble();
double endY = randomBetween(3, 33).toDouble();
Offset end = Offset(endX, endY);
_lineOffsets.add(end);
}
_ranColor = DzyTheme.randomColor();
}
@override
void initState() {
super.initState();
_textLength = widget.text.length ?? 4;
_width = _textLength.toDouble() * 22;
_height = 36;
_ranStr = widget.text;
_randLines();
// initState 中设置回调后不可以调用 setState 方法否则报错,否则运行出错
// widget.onTap(_ranDtr);
// _changeCode();
}
void _changeCode() {
_ranStr = randomAlphaNumeric(_textLength);
widget.onTap(_ranStr);
setState(() {
_randLines();
});
}
Container _subString(index) {
// 首次返回对应字母
// widget.currentStr(_ranDtr);
return Container(
padding: EdgeInsets.only(
left: 2, right: 2, top: randomBetween(0, 14).toDouble()),
child: Transform.rotate(
angle: pi / randomBetween(3, 30) * randomBetween(-1, 1),
child: Text(_ranStr[index],
style: TextStyle(
fontSize: randomBetween(16, 18).toDouble(),
color: DzyTheme.randomColor())),
),
);
}
Container _backLines() {
// 父类模块和子类模块最少有一个设置大小
return Container(
width: _width,
height: _height,
child: CustomPaint(
// size: Size(_width, _height),
painter: CodePaint(_lineOffsets, _ranColor),
foregroundPainter: CodePaint(_lineOffsets, _ranColor),
),
);
}
@override
Widget build(BuildContext context) {
return Container(
width: _width,
height: _height,
color: Colors.grey[200],
child: Stack(
alignment: Alignment.center,
children: [
_backLines(),
_backLines(),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: _changeCode,
child: Container(
width: _width,
height: _height,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(_textLength, (int index) {
return _subString(index);
}),
),
),
),
],
),
);
}
}
背景实现的线条方案,此处的坑未解决,暂时留作记录就是会调用任何重绘组建的方法,判断监听的类别没有找到对应方法,所以实现的不是很好,只做一个好的问题记录
import 'dart:ui';
import 'package:flutter/material.dart';
class CodePaint extends CustomPainter {
// 暂时没有找获取焦点后页面重绘的监听方法,所以外部传递
final List lineOffsets;
final Color ranColor;
CodePaint(this.lineOffsets, this.ranColor);
@override
void paint(Canvas canvas, Size size) {
debugPrint(canvas.runtimeType.toString());
canvas.save();
Paint _paint = Paint()
..color = ranColor //画笔颜色
..strokeCap = StrokeCap.round //画笔笔触类型
..isAntiAlias = true //是否启动抗锯齿
..blendMode = BlendMode.exclusion //颜色混合模式
..style = PaintingStyle.fill //绘画风格,默认为填充
..colorFilter = ColorFilter.mode(ranColor,
BlendMode.exclusion) //颜色渲染模式,一般是矩阵效果来改变的,但是flutter中只能使用颜色混合模式
..maskFilter = MaskFilter.blur(BlurStyle.inner, 1.0) //模糊遮罩效果,flutter中只有这个
..filterQuality = FilterQuality.high //颜色渲染模式的质量
// ..strokeWidth = randomBetween(1, 3).toDouble(); // 暂时固定
..strokeWidth = 1;
final pointMode = PointMode.lines;
canvas.drawPoints(pointMode, lineOffsets, _paint);
canvas.restore();
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
// oldDelegate.points != points;
}
}
最后还是放上一个懒人包
中间的两个问题,希望得到大牛的回复