9
This commit is contained in:
3
lib/cases/cases.dart
Normal file
3
lib/cases/cases.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
export 'counter/counter_page.dart';
|
||||
export 'guess/guess_page.dart';
|
||||
export 'paper/paper.dart';
|
||||
45
lib/cases/counter/counter_page.dart
Normal file
45
lib/cases/counter/counter_page.dart
Normal file
@@ -0,0 +1,45 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CounterPage extends StatefulWidget {
|
||||
const CounterPage({super.key});
|
||||
|
||||
|
||||
|
||||
@override
|
||||
State<CounterPage> createState() => _CounterPageState();
|
||||
}
|
||||
|
||||
class _CounterPageState extends State<CounterPage> {
|
||||
int _counter = 0;
|
||||
|
||||
void _incrementCounter() {
|
||||
setState(() {
|
||||
_counter++;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Text(
|
||||
'You have pushed the button this many times:',
|
||||
),
|
||||
Text(
|
||||
'$_counter',
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _incrementCounter,
|
||||
tooltip: 'Increment',
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
47
lib/cases/guess/guess_app_bar.dart
Normal file
47
lib/cases/guess/guess_app_bar.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class GuessAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
final VoidCallback onCheck;
|
||||
final TextEditingController controller;
|
||||
|
||||
const GuessAppBar({
|
||||
Key? key,
|
||||
required this.onCheck,
|
||||
required this.controller,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppBar(
|
||||
leading: Icon(Icons.menu, color: Colors.black),
|
||||
actions: [
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: onCheck,
|
||||
icon: Icon(
|
||||
Icons.run_circle_outlined,
|
||||
color: Colors.blue,
|
||||
))
|
||||
],
|
||||
title: TextField(
|
||||
controller: controller,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: Color(0xffF3F6F9),
|
||||
constraints: BoxConstraints(maxHeight: 34), //约束信息
|
||||
contentPadding: EdgeInsets.only(top: -14,left: 10),
|
||||
border: UnderlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||
),
|
||||
hintText: "输入 0~99 数字",
|
||||
hintStyle: TextStyle(fontSize: 14)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
||||
}
|
||||
125
lib/cases/guess/guess_page.dart
Normal file
125
lib/cases/guess/guess_page.dart
Normal file
@@ -0,0 +1,125 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'guess_app_bar.dart';
|
||||
import 'result_notice.dart';
|
||||
|
||||
class GuessPage extends StatefulWidget {
|
||||
const GuessPage({super.key});
|
||||
|
||||
@override
|
||||
State<GuessPage> createState() => _GuessPageState();
|
||||
}
|
||||
|
||||
class _GuessPageState extends State<GuessPage> with SingleTickerProviderStateMixin,AutomaticKeepAliveClientMixin{
|
||||
|
||||
late AnimationController controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
int _value = 0;
|
||||
|
||||
final Random _random = Random();
|
||||
bool _guessing = false;
|
||||
bool? _isBig;
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_guessCtrl.dispose();
|
||||
controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _generateRandomValue() {
|
||||
setState(() {
|
||||
_guessing = true;
|
||||
_value = _random.nextInt(100);
|
||||
print(_value);
|
||||
});
|
||||
}
|
||||
|
||||
TextEditingController _guessCtrl = TextEditingController();
|
||||
|
||||
void _onCheck() {
|
||||
print("=====Check:目标数值:$_value=====${_guessCtrl.text}============");
|
||||
int? guessValue = int.tryParse(_guessCtrl.text);
|
||||
// 游戏未开始,或者输入非整数,无视
|
||||
if (!_guessing || guessValue == null) return;
|
||||
controller.forward(from: 0);
|
||||
//猜对了
|
||||
if (guessValue == _value) {
|
||||
setState(() {
|
||||
_isBig = null;
|
||||
_guessing = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 猜错了
|
||||
setState(() {
|
||||
_isBig = guessValue > _value;
|
||||
});
|
||||
_guessCtrl.clear();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: GuessAppBar(
|
||||
controller: _guessCtrl,
|
||||
onCheck: _onCheck,
|
||||
),
|
||||
body: Stack(
|
||||
children: [
|
||||
if(_isBig!=null)
|
||||
Column(
|
||||
children: [
|
||||
if(_isBig!)
|
||||
ResultNotice(color:Colors.redAccent,info:'大了',controller: controller,),
|
||||
Spacer(),
|
||||
if(!_isBig!)
|
||||
ResultNotice(color:Colors.blueAccent,info:'小了',controller: controller,),
|
||||
],
|
||||
),
|
||||
Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
if (!_guessing)
|
||||
const Text(
|
||||
'点击生成随机数值',
|
||||
),
|
||||
Text(
|
||||
_guessing ? '**' : '$_value',
|
||||
style: const TextStyle(
|
||||
fontSize: 68, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _guessing ? null : _generateRandomValue,
|
||||
backgroundColor: _guessing ? Colors.grey : Colors.blue,
|
||||
tooltip: 'Increment',
|
||||
child: const Icon(Icons.generating_tokens_outlined),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
// TODO: implement wantKeepAlive
|
||||
bool get wantKeepAlive => true;
|
||||
|
||||
|
||||
}
|
||||
35
lib/cases/guess/result_notice.dart
Normal file
35
lib/cases/guess/result_notice.dart
Normal file
@@ -0,0 +1,35 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ResultNotice extends StatelessWidget {
|
||||
final Color color;
|
||||
final String info;
|
||||
final AnimationController controller;
|
||||
|
||||
const ResultNotice({
|
||||
Key? key,
|
||||
required this.color,
|
||||
required this.info,
|
||||
required this.controller,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Expanded(
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
color: color,
|
||||
child: AnimatedBuilder(
|
||||
animation: controller,
|
||||
builder: (_, child) => Text(
|
||||
info,
|
||||
style: TextStyle(
|
||||
fontSize: 54 * (controller.value),
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
52
lib/cases/paper/color_selector.dart
Normal file
52
lib/cases/paper/color_selector.dart
Normal file
@@ -0,0 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ColorSelector extends StatelessWidget {
|
||||
final List<Color> supportColors;
|
||||
final ValueChanged<int> onSelect;
|
||||
final int activeIndex;
|
||||
|
||||
const ColorSelector({
|
||||
Key? key,
|
||||
required this.supportColors,
|
||||
required this.activeIndex,
|
||||
required this.onSelect,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 8),
|
||||
child: Wrap(
|
||||
// crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: List.generate(
|
||||
supportColors.length,
|
||||
_buildByIndex,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildByIndex(int index) {
|
||||
bool select = index == activeIndex;
|
||||
return GestureDetector(
|
||||
onTap: () => onSelect(index),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
width: 24,
|
||||
height: 24,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
border: select ? Border.all(color: Colors.blue) : null
|
||||
),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: supportColors[index],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
102
lib/cases/paper/conform_dialog.dart
Normal file
102
lib/cases/paper/conform_dialog.dart
Normal file
@@ -0,0 +1,102 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020-04-23
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明:
|
||||
|
||||
class ConformDialog extends StatelessWidget {
|
||||
final String title;
|
||||
final String msg;
|
||||
final String conformText;
|
||||
final VoidCallback onConform;
|
||||
|
||||
ConformDialog({
|
||||
Key? key,
|
||||
required this.title,
|
||||
required this.msg,
|
||||
required this.onConform,
|
||||
this.conformText = '删除',
|
||||
}) : super(key: key);
|
||||
|
||||
final ButtonStyle conformStyle = ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.redAccent,
|
||||
foregroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
minimumSize: const Size(70, 35),
|
||||
padding: EdgeInsets.zero,
|
||||
shape: const StadiumBorder(),
|
||||
);
|
||||
|
||||
final ButtonStyle cancelStyle = OutlinedButton.styleFrom(
|
||||
minimumSize: const Size(70, 35),
|
||||
elevation: 0,
|
||||
padding: EdgeInsets.zero,
|
||||
shape: const StadiumBorder(),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Dialog(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
_buildTitle(),
|
||||
_buildMessage(),
|
||||
_buildButtons(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTitle()=>Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.warning_amber_rounded, color: Colors.orange),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Widget _buildMessage()=>Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 15,
|
||||
bottom: 15,
|
||||
),
|
||||
child: Text(
|
||||
msg,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
);
|
||||
|
||||
Widget _buildButtons(BuildContext context) => Row(
|
||||
children: [
|
||||
const Spacer(),
|
||||
OutlinedButton(
|
||||
onPressed: Navigator.of(context).pop,
|
||||
style: cancelStyle,
|
||||
child: const Text(
|
||||
'取消',
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
)),
|
||||
const SizedBox(width: 10),
|
||||
ElevatedButton(
|
||||
onPressed: onConform,
|
||||
style: conformStyle,
|
||||
child: Text(conformText),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
14
lib/cases/paper/model.dart
Normal file
14
lib/cases/paper/model.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Line {
|
||||
List<Offset> points;
|
||||
Color color;
|
||||
double strokeWidth;
|
||||
|
||||
Line({
|
||||
required this.points,
|
||||
this.color = Colors.black,
|
||||
this.strokeWidth = 1,
|
||||
});
|
||||
|
||||
}
|
||||
194
lib/cases/paper/paper.dart
Normal file
194
lib/cases/paper/paper.dart
Normal file
@@ -0,0 +1,194 @@
|
||||
import 'dart:math';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'color_selector.dart';
|
||||
import 'conform_dialog.dart';
|
||||
|
||||
import 'model.dart';
|
||||
import 'paper_app_bar.dart';
|
||||
import 'stork_width_selector.dart';
|
||||
|
||||
class Paper extends StatefulWidget {
|
||||
const Paper({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Paper> createState() => _PaperState();
|
||||
}
|
||||
|
||||
class _PaperState extends State<Paper> with AutomaticKeepAliveClientMixin {
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
|
||||
|
||||
List<Line> _lines = []; // 线列表
|
||||
|
||||
int _activeColorIndex = 0; // 颜色激活索引
|
||||
int _activeStorkWidthIndex = 0; // 线宽激活索引
|
||||
|
||||
// 支持的颜色
|
||||
final List<Color> supportColors = [
|
||||
Colors.black,
|
||||
Colors.red,
|
||||
Colors.orange,
|
||||
Colors.yellow,
|
||||
Colors.green,
|
||||
Colors.blue,
|
||||
Colors.indigo,
|
||||
Colors.purple,
|
||||
Colors.pink,
|
||||
Colors.grey,
|
||||
Colors.redAccent,
|
||||
Colors.orangeAccent,
|
||||
Colors.yellowAccent,
|
||||
Colors.greenAccent,
|
||||
Colors.blueAccent,
|
||||
Colors.indigoAccent,
|
||||
Colors.purpleAccent,
|
||||
Colors.pinkAccent,
|
||||
];
|
||||
|
||||
// 支持的线粗
|
||||
final List<double> supportStorkWidths = [1, 2, 4, 6, 8, 10];
|
||||
|
||||
List<Line> _historyLines = [];
|
||||
|
||||
void _back() {
|
||||
Line line = _lines.removeLast();
|
||||
_historyLines.add(line);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _revocation() {
|
||||
Line line = _historyLines.removeLast();
|
||||
_lines.add(line);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: PaperAppBar(
|
||||
onClear: _showClearDialog,
|
||||
onBack: _lines.isEmpty ? null : _back,
|
||||
onRevocation: _historyLines.isEmpty ? null : _revocation,
|
||||
),
|
||||
body: Stack(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onPanStart: _onPanStart,
|
||||
onPanUpdate: _onPanUpdate,
|
||||
child: CustomPaint(
|
||||
painter: PaperPainter(lines: _lines),
|
||||
child: ConstrainedBox(constraints: const BoxConstraints.expand()),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ColorSelector(
|
||||
supportColors: supportColors,
|
||||
activeIndex: _activeColorIndex,
|
||||
onSelect: _onSelectColor,
|
||||
),
|
||||
),
|
||||
StorkWidthSelector(
|
||||
supportStorkWidths: supportStorkWidths,
|
||||
color: supportColors[_activeColorIndex],
|
||||
activeIndex: _activeStorkWidthIndex,
|
||||
onSelect: _onSelectStorkWidth,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showClearDialog() {
|
||||
String msg = "您的当前操作会清空绘制内容,是否确定删除!";
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => ConformDialog(
|
||||
title: '清空提示',
|
||||
conformText: '确定',
|
||||
msg: msg,
|
||||
onConform: _clear,
|
||||
));
|
||||
}
|
||||
|
||||
void _clear() {
|
||||
_lines.clear();
|
||||
Navigator.of(context).pop();
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _onPanStart(DragStartDetails details) {
|
||||
_lines.add(Line(
|
||||
points: [details.localPosition],
|
||||
strokeWidth: supportStorkWidths[_activeStorkWidthIndex],
|
||||
color: supportColors[_activeColorIndex],
|
||||
));
|
||||
}
|
||||
|
||||
void _onPanUpdate(DragUpdateDetails details) {
|
||||
Offset point = details.localPosition;
|
||||
double distance = (_lines.last.points.last - point).distance;
|
||||
if (distance > 5) {
|
||||
_lines.last.points.add(details.localPosition);
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
void _onSelectStorkWidth(int index) {
|
||||
if (index != _activeStorkWidthIndex) {
|
||||
setState(() {
|
||||
_activeStorkWidthIndex = index;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _onSelectColor(int index) {
|
||||
if (index != _activeColorIndex) {
|
||||
setState(() {
|
||||
_activeColorIndex = index;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PaperPainter extends CustomPainter {
|
||||
PaperPainter({
|
||||
required this.lines,
|
||||
}) {
|
||||
_paint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeCap = StrokeCap.round;
|
||||
}
|
||||
|
||||
late Paint _paint;
|
||||
final List<Line> lines;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
drawLine(canvas, lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
///根据点位绘制线
|
||||
void drawLine(Canvas canvas, Line line) {
|
||||
_paint.color = line.color;
|
||||
_paint.strokeWidth = line.strokeWidth;
|
||||
canvas.drawPoints(PointMode.polygon, line.points, _paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) => true;
|
||||
}
|
||||
76
lib/cases/paper/paper_app_bar.dart
Normal file
76
lib/cases/paper/paper_app_bar.dart
Normal file
@@ -0,0 +1,76 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class PaperAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
final VoidCallback onClear;
|
||||
final VoidCallback? onBack;
|
||||
final VoidCallback? onRevocation;
|
||||
|
||||
const PaperAppBar({
|
||||
Key? key,
|
||||
required this.onClear,
|
||||
this.onBack,
|
||||
this.onRevocation,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppBar(
|
||||
leading: BackUpButtons(
|
||||
onBack: onBack,
|
||||
onRevocation: onRevocation,
|
||||
),
|
||||
leadingWidth: 100,
|
||||
title: Text('画板绘制'),
|
||||
actions: [
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: onClear,
|
||||
icon: Icon(CupertinoIcons.delete, size: 20))
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
||||
}
|
||||
|
||||
class BackUpButtons extends StatelessWidget {
|
||||
final VoidCallback? onBack;
|
||||
final VoidCallback? onRevocation;
|
||||
|
||||
const BackUpButtons({
|
||||
Key? key,
|
||||
required this.onBack,
|
||||
required this.onRevocation,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const BoxConstraints cts = BoxConstraints(minHeight: 32, minWidth: 32);
|
||||
Color backColor = onBack ==null?Colors.grey:Colors.black;
|
||||
Color revocationColor = onRevocation ==null?Colors.grey:Colors.black;
|
||||
return Center(
|
||||
child: Wrap(
|
||||
children: [
|
||||
Transform.scale(
|
||||
scaleX: -1,
|
||||
child: IconButton(
|
||||
splashRadius: 20,
|
||||
constraints: cts,
|
||||
onPressed: onBack,
|
||||
icon: Icon(Icons.next_plan_outlined,color: backColor),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: onRevocation,
|
||||
constraints: cts,
|
||||
icon: Icon(Icons.next_plan_outlined, color: revocationColor),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
50
lib/cases/paper/stork_width_selector.dart
Normal file
50
lib/cases/paper/stork_width_selector.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StorkWidthSelector extends StatelessWidget {
|
||||
final List<double> supportStorkWidths;
|
||||
final ValueChanged<int> onSelect;
|
||||
final int activeIndex;
|
||||
final Color color;
|
||||
|
||||
const StorkWidthSelector({
|
||||
Key? key,
|
||||
required this.supportStorkWidths,
|
||||
required this.activeIndex,
|
||||
required this.onSelect,
|
||||
required this.color,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: List.generate(
|
||||
supportStorkWidths.length,
|
||||
_buildByIndex,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildByIndex(int index) {
|
||||
bool select = index == activeIndex;
|
||||
return GestureDetector(
|
||||
onTap: () => onSelect(index),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 2),
|
||||
width: 70,
|
||||
height: 18,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: select ? Border.all(color: Colors.blue) : null),
|
||||
child: Container(
|
||||
width: 50,
|
||||
color: color,
|
||||
height: supportStorkWidths[index],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user