Смещение изменения Flutter перетаскиваемых виджетов в стеке одновременно с прокруткой SingleChildScrollView - PullRequest
0 голосов
/ 03 августа 2020

У меня есть стопка виджетов во Flutter. Самый нижний стек - это большое изображение, которое содержится внутри SingleChildScrollView. Я установил ScrollController, поэтому я знаю, когда изображение было горизонтально прокручено в представлении.

Далее в стеке у меня есть несколько позиционированных виджетов (их можно перетаскивать, чтобы их можно было перемещать независимо друг от друга ).

То, что я хотел бы сделать, - это когда SingleChildScrollView прокручивается, я хотел бы обновить положение каждого из расположенных выше виджетов в стеке.

Я рассматривает 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,
              ),
            ),
          ),
        ),
      )
    );
  }
}

Любая помощь очень ценится!

1 Ответ

0 голосов
/ 04 августа 2020

Я был дураком. Забавно, как уходить от чего-то в одночасье и возвращаться к нему очищает туман!

Я разобрался с этим, просто поместив весь стек в SingleChildScrollView. Прокрутка шире и прокручивается по горизонтали, а остальные элементы в стеке правильно сохраняют свои позиции, даже если прокрутка перемещается и исчезает с экрана.

Решение было очень простым. Для полноты, вот обновленный код:

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