栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在Flutter中输入DragTarget时如何更新Draggable子级?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在Flutter中输入DragTarget时如何更新Draggable子级?

我能想到的唯一方法是使用streambuilder和将承载可拖动对象是否在拖动目标上的信息的流。此代码提供了基本的解决方案。

class _MyHomePageState extends State<MyHomePage> {  BehaviorSubject<bool> willAcceptStream;  @override  void initState() {    willAcceptStream = new BehaviorSubject<bool>();    willAcceptStream.add(false);    super.initState();  }  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text(widget.title),      ),      body: Column(        children: <Widget>[          Container( height: 400, width: double.infinity, child: Container(   width: 100,   height: 100,   child: Center(     child: Draggable(       feedback: StreamBuilder(         initialdata: false,         stream: willAcceptStream,         builder: (context, snapshot) {return Container(  height: 100,  width: 100,  color: snapshot.data ? Colors.green : Colors.red,);         },       ),       childWhenDragging: Container(),       child: Container(         height: 100,         width: 100,         color: this.willAcceptStream.value ?? false  ? Colors.green  : Colors.blue,       ),       onDraggableCanceled: (v, f) => setState(  () {    this.willAcceptStream.add(false);  },),     ),   ), ),          ),          DragTarget( builder: (context, list, list2) {   return Container(     height: 50,     width: double.infinity,     color: Colors.blueGrey,     child: Center(child: Text('TARGET ZONE'),),   ); }, onWillAccept: (item) {   debugPrint('will accept');   this.willAcceptStream.add(true);   return true; }, onLeave: (item) {   debugPrint('left the target');   this.willAcceptStream.add(false); },          ),        ],      ),    );  }}

编辑:第一个示例不会同时处理多个拖动,这更干净一些。

import 'package:rxdart/rxdart.dart';import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  // This widget is the root of your application.  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'Draggable Test',      theme: ThemeData(        primarySwatch: Colors.blue,      ),      home: MyHomePage(),    );  }}class MyHomePage extends StatefulWidget {  MyHomePage({Key key}) : super(key: key);  @override  _MyHomePageState createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> {  MyDraggableController<String> draggableController;  @override  void initState() {    this.draggableController = new MyDraggableController<String>();    super.initState();  }  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text('Draggable Test'),      ),      body: Column(        children: <Widget>[          Container( height: 400, width: double.infinity, child: Container(   width: 100,   height: 100,   child: Center(     child: Stack(       children: <Widget>[         Positioned(left: 30,top: 30,child: MyDraggable<String>(draggableController, 'Test1'),         ),         Positioned(left: 230,top: 230,child: MyDraggable<String>(draggableController, 'Test2'),         )       ],     ),   ), ),          ),          DragTarget<String>( builder: (context, list, list2) {   return Container(     height: 50,     width: double.infinity,     color: Colors.blueGrey,     child: Center(       child: Text('TARGET ZONE'),     ),   ); }, onWillAccept: (item) {   debugPrint('draggable is on the target');   this.draggableController.onTarget(true, item);   return true; }, onLeave: (item) {   debugPrint('draggable has left the target');   this.draggableController.onTarget(false, item); },          ),        ],      ),    );  }}class MyDraggable<T> extends StatefulWidget {  final MyDraggableController<T> controller;  final T data;  MyDraggable(this.controller, this.data);  @override  _MyDraggableState createState() =>      _MyDraggableState<T>(this.controller, this.data);}class _MyDraggableState<T> extends State<MyDraggable> {  BehaviorSubject<DraggableInfo<T>> willAcceptStream;  MyDraggableController<T> controller;  T data;  _MyDraggableState(this.controller, this.data);  @override  void initState() {    willAcceptStream = this.controller._isOnTarget;    willAcceptStream.add(new DraggableInfo<T>(false, this.data));    super.initState();  }  @override  Widget build(BuildContext context) {    return Draggable<T>(      data: this.data,      feedback: StreamBuilder<DraggableInfo<T>>(        initialdata: DraggableInfo<T>(false, this.data),        stream: willAcceptStream,        builder: (context, snapshot) {          return Container( height: 100, width: 100, color: snapshot.data.isonTarget && snapshot.data.data == this.data ? Colors.green : Colors.red,          );        },      ),      childWhenDragging: Container(),      child: Container(        height: 100,        width: 100,        color: (this.willAcceptStream.value.isonTarget ?? this.willAcceptStream.value.data == this.data) ? Colors.green : Colors.blue,      ),      onDraggableCanceled: (v, f) => setState( () {   this.willAcceptStream.add(DraggableInfo(false, null)); },          ),    );  }}class DraggableInfo<T> {  bool isOnTarget;  T data;  DraggableInfo(this.isOnTarget, this.data);}class MyDraggableController<T> {  BehaviorSubject<DraggableInfo<T>> _isOnTarget;  MyDraggableController() {    this._isonTarget = new BehaviorSubject<DraggableInfo<T>>();  }  void onTarget(bool onTarget, T data) {    _isOnTarget.add(new DraggableInfo(onTarget, data));  }}

编辑2:不使用流和streambuilder的解决方案。重要的是反馈小部件是有状态的。

import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  // This widget is the root of your application.  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'Draggable Test',      theme: ThemeData(        primarySwatch: Colors.blue,      ),      home: MyHomePage(),    );  }}class MyHomePage extends StatefulWidget {  MyHomePage({Key key}) : super(key: key);  @override  _MyHomePageState createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> {  MyDraggableController<String> draggableController;  @override  void initState() {    this.draggableController = new MyDraggableController<String>();    super.initState();  }  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text('Draggable Test'),      ),      body: Column(        children: <Widget>[          Container( height: 400, width: double.infinity, child: Container(   width: 100,   height: 100,   child: Center(     child: Stack(       children: <Widget>[         Positioned(left: 30,top: 30,child: MyDraggable<String>(  draggableController,  'Test1',),         ),         Positioned(left: 230,top: 230,child: MyDraggable<String>(  draggableController,  'Test2',),         ),       ],     ),   ), ),          ),          DragTarget<String>( builder: (context, list, list2) {   return Container(     height: 100,     width: double.infinity,     color: Colors.blueGrey,     child: Center(       child: Text('TARGET ZONE'),     ),   ); }, onWillAccept: (item) {   debugPrint('draggable is on the target $item');   this.draggableController.onTarget(true, item);   return true; }, onLeave: (item) {   debugPrint('draggable has left the target $item');   this.draggableController.onTarget(false, item); },          ),        ],      ),    );  }}class MyDraggable<T> extends StatefulWidget {  final MyDraggableController<T> controller;  final T data;  MyDraggable(this.controller, this.data, {Key key}) : super(key: key);  @override  _MyDraggableState createState() =>      _MyDraggableState<T>(this.controller, this.data);}class _MyDraggableState<T> extends State<MyDraggable> {  MyDraggableController<T> controller;  T data;  bool isOnTarget;  _MyDraggableState(this.controller, this.data);  FeedbackController feedbackController;  @override  void initState() {    feedbackController = new FeedbackController();    this.controller.subscribeToonTargetCallback(onTargetCallbackHandler);    super.initState();  }  void onTargetCallbackHandler(bool t, T data) {    this.isonTarget = t && data == this.data;    this.feedbackController.updateFeedback(this.isOnTarget);  }  @override  void dispose() {    this.controller.unSubscribeFromonTargetCallback(onTargetCallbackHandler);    super.dispose();  }  @override  Widget build(BuildContext context) {    return Draggable<T>(      data: this.data,      feedback: FeedbackWidget(feedbackController),      childWhenDragging: Container(        height: 100,        width: 100,        color: Colors.blue[50],      ),      child: Container(        height: 100,        width: 100,        color: (this.isonTarget ?? false) ? Colors.green : Colors.blue,      ),      onDraggableCanceled: (v, f) => setState( () {   this.isonTarget = false;   this.feedbackController.updateFeedback(this.isOnTarget); },          ),    );  }}class FeedbackController {  Function(bool) feedbackNeedsUpdateCallback;  void updateFeedback(bool isOnTarget) {    if (feedbackNeedsUpdateCallback != null) {      feedbackNeedsUpdateCallback(isOnTarget);    }  }}class FeedbackWidget extends StatefulWidget {  final FeedbackController controller;  FeedbackWidget(this.controller);  @override  _FeedbackWidgetState createState() => _FeedbackWidgetState();}class _FeedbackWidgetState extends State<FeedbackWidget> {  bool isOnTarget;  @override  void initState() {    this.isonTarget = false;    this.widget.controller.feedbackNeedsUpdateCallback = feedbackNeedsUpdateCallbackHandler;    super.initState();  }  void feedbackNeedsUpdateCallbackHandler(bool t) {    setState(() {      this.isonTarget = t;    });  }  @override  Widget build(BuildContext context) {    return Container(      height: 100,      width: 100,      color: this.isonTarget ?? false ? Colors.green : Colors.red,    );  }  @override  void dispose() {    this.widget.controller.feedbackNeedsUpdateCallback = null;    super.dispose();  }}class DraggableInfo<T> {  bool isOnTarget;  T data;  DraggableInfo(this.isOnTarget, this.data);}class MyDraggableController<T> {  List<Function(bool, T)> _targetUpdateCallbacks = new List<Function(bool, T)>();  MyDraggableController();  void onTarget(bool onTarget, T data) {    if (_targetUpdateCallbacks != null) {      _targetUpdateCallbacks.forEach((f) => f(onTarget, data));    }  }  void subscribeToonTargetCallback(Function(bool, T) f) {    _targetUpdateCallbacks.add(f);  }  void unSubscribeFromonTargetCallback(Function(bool, T) f) {    _targetUpdateCallbacks.remove(f);  }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/410202.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号