繁体   English   中英

Flutter 在滚动 SingleChildScrollView 的同时更改堆栈中可拖动小部件的偏移量

[英]Flutter change offset of draggable widgets in a stack at the same time as scrolling a SingleChildScrollView

我在 Flutter 中有一堆小部件。 最低的堆栈是包含在 SingleChildScrollView 中的大图像。 我已经设置了一个 ScrollController,所以我知道图像何时在视图中水平滚动。

接下来在堆栈中,我有几个定位小部件(这些是可拖动的,因此它们可以相互独立地移动)。

我想做的是当 SingleChildScrollView 滚动时,我想更新堆栈中每个定位的小部件的 position 。

我考虑过 Stream、rebuildAllChildren 和 ValueNotifier,但从表面上看,这一切似乎都相当复杂,但实现起来应该很简单。 我可能在某处遗漏了一些非常明显的东西!

到目前为止,这是我的代码:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class LayoutScreen extends StatefulWidget {
  LayoutScreen();

  @override
  _LayoutScreenState createState() => _LayoutScreenState();
}

class _LayoutScreenState extends State<LayoutScreen> {
  ScrollController _controller;
  Offset boxoneposition;
  BuildContext context;

  _scrollListener() {
    print(_controller.offset);
    boxoneposition=Offset(100.0, 100);
    setState(() {
      print(boxoneposition);
      // this was a test - the value of boxoneposition is updated, however the view isn't
    });
 }

  @override
  void initState() {
    _controller = ScrollController();
    _controller.addListener(_scrollListener);

    boxoneposition = Offset(0.0, 30);

    super.initState();
  }

  DragBox boxOne() {
    // Trying to set up outside of widget build
    return DragBox(boxoneposition, 'Box One Yep', Colors.blueAccent, 1);
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[

        SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          controller: _controller,
          child: Container(
            width: 1000,
            height: 1000,
            decoration: BoxDecoration(
              image: DecorationImage(
                image: AssetImage('assets/images/logo.png'),
                fit: BoxFit.cover,
                repeat: ImageRepeat.noRepeat,
              ),
            ),
          ),
        ),
        //DragBox(boxoneposition, 'Box One', Colors.blueAccent, 1),
        boxOne(),
        DragBox(Offset(200.0, 50.0), 'Box Two', Colors.orange, 2),
        DragBox(Offset(300.0, 80.0), 'Box Three', Colors.lightGreen, 3),
      ],
    );
  }
}

class DragBox extends StatefulWidget {
  final Offset initPos;
  final String label;
  final Color itemColor;
  final int boxnumber;

  DragBox(this.initPos, this.label, this.itemColor, this.boxnumber);

  @override
  DragBoxState createState() => DragBoxState();
}

class DragBoxState extends State<DragBox> {
  Offset position = Offset(0.0, 0.0);
  String imagePath="";

  @override
  void initState() {
    super.initState();
    position = widget.initPos;
  }

  getBoxPic() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      String key='picture'+widget.boxnumber.toString();
      imagePath=prefs.getString(key);
    });
    print(imagePath);
    return File(imagePath);
  }

  @override
  Widget build(BuildContext context) {
    return Positioned(
      left: position.dx,
      top: position.dy,
      child: Draggable(
        data: widget.itemColor,
        child: Container(
          width: 100.0,
          height: 100.0,
          color: widget.itemColor,
          child: Center(
            child: 
            Image.asset('assets/images/logo.png')
          ),
        ),
        onDragStarted: () {
          setState(() {
            print("Foobar");
          });
        },
        onDraggableCanceled: (velocity, offset) {
          setState(() {
            position = offset;
            if (widget.boxnumber==1) {
              print("Wibble");
            }
          });
        },
        feedback: Container(
          width: 120.0,
          height: 120.0,
          color: widget.itemColor.withOpacity(0.5),
          child: Center(
            child: Text(
              widget.label,
              style: TextStyle(
                color: Colors.white,
                decoration: TextDecoration.none,
                fontSize: 18.0,
              ),
            ),
          ),
        ),
      )
    );
  }
}

非常感谢任何帮助!

我是个傻瓜。 有趣的是如何在一夜之间离开某事并回到它清除迷雾!

我通过简单地将整个堆栈放入 SingleChildScrollView 来解决这个问题。 滚动视图更宽且可水平滚动,并且堆栈中元素的 rest 正确地保持其位置,即使滚动视图被移动并且它们从屏幕上消失。

解决方案非常简单。 为了完整起见,这里是更新的代码:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class LayoutScreen extends StatefulWidget {
  LayoutScreen();

  @override
  _LayoutScreenState createState() => _LayoutScreenState();
}

class _LayoutScreenState extends State<LayoutScreen> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Arrange your images'),
        backgroundColor: Colors.orange,
      ),
      body: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: Stack(
          children: <Widget>[
            Container(
              width: 1000,
              height: 1000,
              decoration: BoxDecoration(
                image: DecorationImage(
                  image: AssetImage('assets/images/background.jpg'),
                  fit: BoxFit.cover,
                  repeat: ImageRepeat.noRepeat,
                ),
              ),
            ),
            DragBox(Offset(100.0, 10.0), 'Box One', Colors.blueAccent, 1),
            DragBox(Offset(200.0, 50.0), 'Box Two', Colors.orange, 2),
            DragBox(Offset(300.0, 80.0), 'Box Three', Colors.lightGreen, 3),
          ]
        ),
      )
    );
  }
}

class DragBox extends StatefulWidget {
  final Offset initPos;
  final String label;
  final Color itemColor;
  final int boxnumber;

  DragBox(this.initPos, this.label, this.itemColor, this.boxnumber);

  @override
  DragBoxState createState() => DragBoxState();
}

class DragBoxState extends State<DragBox> {
  Offset position = Offset(0.0, 0.0);
  String imagePath="";

  @override
  void initState() {
    super.initState();
    position = widget.initPos;
  }

  getBoxPic() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      String key='picture'+widget.boxnumber.toString();
      imagePath=prefs.getString(key);
    });
    print(imagePath);
    return File(imagePath);
  }
@override
  Widget build(BuildContext context) {
    return Positioned(
      left: position.dx,
      top: position.dy,
      child: Draggable(
        data: widget.itemColor,
        child: Container(
          width: 100.0,
          height: 100.0,
          color: widget.itemColor,
          child: Center(
            child: 
            Image.asset('assets/images/logo.png')
          ),
        ),
        onDragStarted: () {
          setState(() {
            print("Foobar");
          });
        },
        onDraggableCanceled: (velocity, offset) {
          setState(() {
            position = offset;
            if (widget.boxnumber==1) {
              print("Wibble");
            }
          });
        },
        feedback: Container(
          width: 120.0,
          height: 120.0,
          color: widget.itemColor.withOpacity(0.5),
          child: Center(
            child: Text(
              widget.label,
              style: TextStyle(
                color: Colors.white,
                decoration: TextDecoration.none,
                fontSize: 18.0,
              ),
            ),
          ),
        ),
      )
    );
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM