颤动幻灯片过渡到特定位置

Posted

技术标签:

【中文标题】颤动幻灯片过渡到特定位置【英文标题】:Flutter Slide Transition To a Specific Location 【发布时间】:2021-01-06 04:36:47 【问题描述】:

我正在使用颤振制作语法测验应用程序,我有一个问题和几个选择,我想通过幻灯片动画使选择滑到问题的空白部分

例如:

_新学校怎么样?

(你)(你的)(它)

当我按下 (Your) 时,选择小部件会滑到 _ 留下一个空容器

(你的)新学校怎么样?

(你)()(它)

我用 Draggable 和 DragTarget 制作的,你可以在这些图片中看到它

image 1

image 2

但我希望它在按下时滑动而不拖放

这里是一些代码

class QuestionsScreen extends StatefulWidget 
  QuestionsScreen(Key key) : super(key: key);

  @override
  _QuestionsScreenState createState() => _QuestionsScreenState();


class _QuestionsScreenState extends State<QuestionsScreen> 
  String userAnswer = "_";
  int indexOfDragPlace = QuestionBrain.getQuesitonText().indexOf("_");
  @override
  Widget build(BuildContext context) 
    final screenSize = MediaQuery.of(context).size;
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            Container(
              padding: EdgeInsets.all(10),
              color: Colors.white,
              child: Center(
                child: Scrollbar(
                  child: ListView(
                    children: [
                      Center(
                        child: Wrap(
                          children: [

                            ...QuestionBrain.getQuesitonText()
                                .substring(0, indexOfDragPlace)
                                .split(" ")
                                .map((e) => QuestionHolder(
                                      question: e + " ",
                                    )),

                            _buildDragTarget(),

                            ...QuestionBrain.getQuesitonText()
                                .substring(indexOfDragPlace + 1)
                                .split(" ")
                                .map((e) => QuestionHolder(
                                      question: e + " ",
                                    )),
                          ],
                        ),
                      )
                    ],
                  ),
                ),
              ),
            ),
     
            Wrap(
              children: [
                ...QuestionBrain.choices.map((choice) 
                  if (choice == userAnswer) 
                    return ChoiceHolder(
                      choice: "",
                      backGroundColor: Colors.black12,
                    );
                  
                  return DraggableChoiceBox(
                    choice: choice,
                    userAnswer: userAnswer,
                    onDragStarted: () 
                      setState(() 
                        dragedAnswerResult = "";
                      );
                    ,
                    onDragCompleted: () 
                      setState(() 
                        userAnswer = choice;
                        setState(() 
                          answerColor = Colors.orange;
                        );
                        print("Called");
                      );
                    ,
                  );
                ).toList()
              ],
            ),
          ],
        ),
      ),
    );
  


  Widget _buildDragTarget() 
    return DragTarget<String>(
      builder: (context, icoming, rejected) 
        return Material(
          child: Container(
            padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
            width: MediaQuery.of(context).size.width * 0.20,
            height: MediaQuery.of(context).size.height * 0.05,
            color: answerColor,
            child: FittedBox(
              child: Text(
                userAnswer,
                style: TextStyle(
                    fontSize: 12,
                    color: Colors.white,
                    fontWeight: FontWeight.bold),
              ),
            ),
          ),
        );
      ,
   
      onAccept: (data) 
        userAnswer = data;
        answerColor = Colors.orange;
      ,
   
    );
  

 



class DraggableChoiceBox extends StatelessWidget 
  const DraggableChoiceBox(
    Key key,
    this.choice,
    this.userAnswer,
    this.onDragCompleted,
    this.onDragStarted,
  ) : super(key: key);
  final String choice;
  final String userAnswer;
  final Function onDragCompleted;
  final Function onDragStarted;
  @override
  Widget build(BuildContext context) 
    return Draggable(
      onDragCompleted: onDragCompleted,
      data: choice,
      child: ChoiceHolder(choice: choice),
      feedback: Material(
        elevation: 20,
        child: ChoiceHolder(
          choice: choice,
          margin: 0,
        ),
      ),
      childWhenDragging: ChoiceHolder(
        choice: "",
        backGroundColor: Colors.black12,
      ),
      onDragStarted: onDragStarted,
    );
  

【问题讨论】:

请分享一些您已经尝试过的代码。 @HasilT 我添加了一些代码,您需要更多说明吗? 【参考方案1】:

您可以使用类似于Hero 小部件的工作方式的overlays,这是一个“未经修饰”的示例:

import 'package:flutter/material.dart';

class SlideToPosition extends StatefulWidget 
  @override
  _SlideToPositionState createState() => _SlideToPositionState();


class _SlideToPositionState extends State<SlideToPosition> 
  GlobalKey target = GlobalKey();

  GlobalKey toMove = GlobalKey();
  double dx = 0.0, dy = 0.0, dxStart = 0.0, dyStart = 0.0;
  String choosedAnswer = '', answer = 'answer', finalAnswer = '';

  OverlayEntry overlayEntry;

  @override
  void initState() 
    overlayEntry = OverlayEntry(
      builder: (context) => TweenAnimationBuilder(
        duration: Duration(milliseconds: 500),
        tween:
            Tween<Offset>(begin: Offset(dxStart, dyStart), end: Offset(dx, dy)),
        builder: (context, offset, widget) 
          return Positioned(
            child: Material(
                child: Container(
                    color: Colors.transparent,
                    height: 29,
                    width: 100,
                    child: Center(child: Text(choosedAnswer)))),
            left: offset.dx,
            top: offset.dy,
          );
        ,
      ),
    );
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            SizedBox(
              height: 20,
            ),
            Row(
              children: [
                Text('text'),
                Container(
                  key: target,
                  height: 30,
                  width: 100,
                  child: Center(child: Text(finalAnswer)),
                  decoration:
                      BoxDecoration(border: Border(bottom: BorderSide())),
                ),
                Text('text')
              ],
            ),
            SizedBox(
              height: 20,
            ),
            GestureDetector(
              child: Container(
                  height: 30,
                  width: 100,
                  color: Colors.blue[200],
                  child: Center(child: Text(answer, key: toMove))),
              onTap: () async 
                setState(() 
                  answer = '';
                );
                RenderBox box1 = target.currentContext.findRenderObject();

                Offset targetPosition = box1.localToGlobal(Offset.zero);

                RenderBox box2 = toMove.currentContext.findRenderObject();
                Offset toMovePosition = box2.localToGlobal(Offset.zero);
                
                setState(() 
                  answer = '';
                  choosedAnswer = 'answer';
                );
                dxStart = toMovePosition.dx;
                dyStart = toMovePosition.dy;
                dx = targetPosition.dx;
                dy = targetPosition.dy;

                Overlay.of(context).insert(overlayEntry);
                setState(() );

                await Future.delayed(Duration(milliseconds: 500));

                overlayEntry.remove();
                setState(() 
                  finalAnswer = 'answer';
                );
              ,
            ),
          ],
        ),
      ),
    );
  


很抱歉变量命名不佳:)

【讨论】:

谢谢你的朋友,你帮了很多忙

以上是关于颤动幻灯片过渡到特定位置的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使当前视图颤动的情况下实现这种幻灯片效果

R 官员包:添加反映当前幻灯片位置的幻灯片编号

BX 滑块,从第一张幻灯片过渡到最后一张幻灯片闪烁(向右然后返回原始)

jQuery移动过渡幻灯片页面内容第二次未刷新到原始

如何在覆盖 UIView 之前停止幻灯片过渡到 Second VC?

iPhone横向UIView幻灯片过渡