flutter - 当孩子和反馈相同时如何防止在可拖动的内部重建
问题描述
问题
我希望用户能够拖动卡片内的文本字段。所以孩子和反馈应该始终处于相同的状态。但是,一旦我触摸卡,小部件就会重建并且状态会重置。
尝试的解决方案
我试过使用键,无状态小部件,我不知道。
代码
import 'dart:math';
import 'package:flutter/material.dart';
import 'bloc/home.dart';
const _chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
Random _rnd = Random();
String getRandomString(int length) => String.fromCharCodes(Iterable.generate(
length, (_) => _chars.codeUnitAt(_rnd.nextInt(_chars.length))));
class QuestionCardDraggable extends StatefulWidget{
final String question;
final HomeBloc homeBloc;
QuestionCardDraggable(this.question, this.homeBloc);
@override
_QuestionCardDraggableState createState() => _QuestionCardDraggableState();
}
class _QuestionCardDraggableState extends State<QuestionCardDraggable> {
TextEditingController _myController;
@override
void initState(){
super.initState();
this._myController = TextEditingController(text: getRandomString(10));
_myController.addListener(() => {widget.homeBloc.add(AnswerChanged(answer: _myController.text))});
}
@override
Widget build(BuildContext context) {
return Card(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(vertical: 32.0, horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(widget.question,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.w700)),
Padding(padding: EdgeInsets.only(bottom: 8.0)),
TextFormField(
controller: _myController,
maxLines: 8,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'your answer...'
),
),
],
))
],
),
);
}
@override
void dispose() {
// Clean up the controller when the widget is removed from the
// widget tree.
_myController.dispose();
super.dispose();
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:projectQ/bloc/bloc.dart';
import 'QuestionCardDraggable.dart';
import 'package:projectQ/models/QuestionAnswer.dart';
class CardsSectionDraggable extends StatefulWidget {
@override
_CardsSectionState createState() => _CardsSectionState();
}
class _CardsSectionState extends State<CardsSectionDraggable> {
HomeBloc _homeBloc;
@override
void initState() {
super.initState();
this._homeBloc = BlocProvider.of<HomeBloc>(context);
}
@override
Widget build(BuildContext context) {
return BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
var length = state.questionsAnswers.length;
var cards = List();
if (length >= 3){
cards.add(notDraggable(
offset: 1,
width: 0.8,
height: 0.5,
child: QuestionCardDraggableStateless(state.questionsAnswers[2].question, state.questionsAnswers[2].answer, _homeBloc),
));
}
if (length >= 2){
cards.add(notDraggable(
offset: 0.8,
width: 0.85,
height: 0.55,
child: QuestionCardDraggableStateless(state.questionsAnswers[1].question, state.questionsAnswers[1].answer, _homeBloc),
));
}
if (length >= 1){
print( 'state: ${state.questionsAnswers.first.answer}');
cards.add(draggable(
offset: 0,
width: 0.9,
height: 0.6,
child: QuestionCardDraggable(state.questionsAnswers.first.question, _homeBloc), //QuestionCardDraggableStateless(state.questionsAnswers.first.question, state.questionsAnswers.first.answer, _homeBloc),
key: UniqueKey() //ValueKey(state.questionsAnswers.first.question)
));
}
return Expanded(
child: Stack(
children: <Widget>[
// Drag target row
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
dragTarget(),
Flexible(flex: 2, child: Container()),
dragTarget()
],
),
//End text
Align(
alignment: Alignment(0.0, 0.0),
child: Container(
child: Text(
"You are done for today!",
style: Theme.of(context).textTheme.headline3,
),
margin: EdgeInsets.all(40),
)
),
...cards,
]
));
}
);
}
Widget notDraggable({double offset, double height, double width, Widget child}) {
return Align(
alignment: Alignment(0.0, offset),
child: IgnorePointer(
child: SizedBox.fromSize(
size: Size(MediaQuery.of(context).size.width * width,
MediaQuery.of(context).size.height * height),
child: child,
)),
);
}
Widget draggable({double offset, double height, double width, Widget child, Key key}){
Widget keyChild = SizedBox.fromSize(
key: key,
size: Size(MediaQuery.of(context).size.width * width,
MediaQuery.of(context).size.height * height),
child: child,
);
return Align(
alignment: Alignment(0.0, offset),
child: Draggable(
feedback: keyChild,
child: keyChild,
childWhenDragging: Container(),
),
);
}
Widget dragTarget() {
return Flexible(
flex: 1,
child: DragTarget(
builder: (_, __, ___) {
return Container();
},
onWillAccept: (_) {
return true;
},
onAccept: (_) {
_homeBloc.add(PopCard());
},
));
}
}
解决方案
推荐阅读
- typescript - TypeScript 索引签名继承的普通类型
- dart - 带宽速度测试比预期慢
- python - AttributeError:模块“torchvision.models”没有属性“mobilenet_v3_small”
- google-chrome-extension - 两个后台脚本之间的 sendMessage/onMessage.addListener 不起作用
- python - 绘制一个以数据单位(而不是点或像素)指定宽度的空心环(甜甜圈)?
- java - RecyclerView 未显示来自 Firebase Firestore 的数据并导致应用程序崩溃
- javascript - 如何使用 map 方法返回带有 typescript 字符串的对象?
- mysql - MySQL通配符有问题
- cmake - 无法将 TensorFlow C 语言绑定下载为 ExternalProject
- reactjs - 从 WordPress 获取 HTML、CSS、JS 并从 React 应用程序提供它