首页 > 解决方案 > 当孩子和反馈相同时如何防止在可拖动的内部重建

问题描述

问题

我希望用户能够拖动卡片内的文本字段。所以孩子和反馈应该始终处于相同的状态。但是,一旦我触摸卡,小部件就会重建并且状态会重置。

尝试的解决方案

我试过使用键,无状态小部件,我不知道。

代码

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());
          },
    ));
  }
}

标签: flutterdraggable

解决方案


推荐阅读