我们如何才能在颤振中实现类似的功能?

时间:2019-08-26 11:30:03

标签: flutter flutter-layout flutter-animation

我想在扑朔迷离中建立这样的东西。

snap

我已经尝试过使用条子,但是由于动画到达顶部时,无法获得所需的输出。

主要的理想功能如下。

1。行为类似于列表视图,但卡片应堆叠在屏幕顶部。

2。应选择被窃听的列表并将其作为主卡显示,如所附图像所示。

import 'dart:math' as math;

class FlashCards extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("Flash Cards"),
            backgroundColor: Colors.black,
          ),
          body: StackedList()),
    );
  }
}

class StackedList extends StatefulWidget {
  @override
  _StackedListState createState() => _StackedListState();
}

class _StackedListState extends State<StackedList> {
  static const _minHeight = 16.0;
  //var _maxHeight = 120.0;
  bool _tapped = false;
  final List<Color> _colors = Colors.primaries;

  @override
  Widget build(BuildContext context) => CustomScrollView(
        slivers: _colors
            .map(
              (color) => StackedListChild(
                minHeight: _minHeight,
                maxHeight: _tapped
                    ? (_colors.indexOf(color) == _colors.length - 1
                        ? MediaQuery.of(context).size.height
                        : 500)
                    : (_colors.indexOf(color) == _colors.length - 1
                        ? MediaQuery.of(context).size.height
                        : 120.0),
                pinned: true,
                child: GestureDetector(
                  child: Container(
                    color: _colors.indexOf(color) == 0
                        ? Colors.black
                        : _colors[_colors.indexOf(color) - 1],
                    child: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.vertical(
                            top: Radius.circular(_minHeight)),
                        color: color,
                      ),
                    ),
                  ),
                  onTap: () => setState(() {
                    _tapped = !_tapped;
                  }),
                  //print(_colors.indexOf(color).toString() + "Tapped"),
                ),
              ),
            )
            .toList(),
      );
}

class StackedListChild extends StatelessWidget {
  final double minHeight;
  final double maxHeight;
  final bool pinned;
  final bool floating;
  final Widget child;

  SliverPersistentHeaderDelegate get _delegate => _StackedListDelegate(
      minHeight: minHeight, maxHeight: maxHeight, child: child);

  const StackedListChild({
    Key key,
    @required this.minHeight,
    @required this.maxHeight,
    @required this.child,
    this.pinned = false,
    this.floating = false,
  })  : assert(child != null),
        assert(minHeight != null),
        assert(maxHeight != null),
        assert(pinned != null),
        assert(floating != null),
        super(key: key);

  @override
  Widget build(BuildContext context) => SliverPersistentHeader(
      key: key, pinned: pinned, floating: floating, delegate: _delegate);
}

class _StackedListDelegate extends SliverPersistentHeaderDelegate {
  final double minHeight;
  final double maxHeight;
  final Widget child;

  _StackedListDelegate({
    @required this.minHeight,
    @required this.maxHeight,
    @required this.child,
  });

  @override
  double get minExtent => minHeight;

  @override
  double get maxExtent => math.max(maxHeight, minHeight);

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new SizedBox.expand(child: child);
  }

  @override
  bool shouldRebuild(_StackedListDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}

就像在动画中一样,点击的小部件会移到顶部,只有扩展的小部件。

1 个答案:

答案 0 :(得分:0)

要进行设计,您需要解决一些任务:

  1. 上卡的位置固定。
  2. 卡片有透明的角,我们可以在那里看到以前的卡片。

如何解决?

  1. 通常要执行第一个任务,您需要创建自己的条子并更改条子的几何形状。观看关于银条的无聊节目:https://www.youtube.com/watch?v=Mz3kHQxBjGg&t=1606s

问题在于SliverList非常复杂,尤其是在您刚开始学习颤振的情况下。

所以我的解决方案有点笨拙。

我们可以使用滚动位置来获取顶部可见卡的索引。 之后,将其隐藏在银条列表中,但将其显示在堆栈小部件中。 它将具有相同的可见影响。

  1. 在您的代码中,您正在用额外的容器包装卡,以将前一张卡的颜色用作背景色,但是当您需要在每个结点附近显示两个角落时,使用这种方法会遇到问题。解决方案是使用SizedOverflowBox。 SizedOverflowBox窗口小部件可帮助您在较小的窗口小部件的位置呈现较大的窗口小部件,并具有可见的溢出。

enter image description here

class Foo {
public:
    Foo() {

    }

    void first(function<void()> printFirst) {
        // cout<<1<<endl;
        // printFirst() outputs "first". Do not change or remove this line.
        // mtx.lock();
        printFirst();
        flag=1;
        // mtx.unlock();
        cond.notify_all();
        // cout<<11<<endl;
    }

    void second(function<void()> printSecond) {
        // cout<<2<<endl;
        {
            unique_lock<mutex> lk(mtx);
            cond.wait(lk,[this](){return flag==1;});
            // printSecond() outputs "second". Do not change or remove this line.
            printSecond();
            flag=2;
        }

        // cout<<22<<endl;
        cond.notify_all();
    }

    void third(function<void()> printThird) {
        // cout<<3<<endl;
        unique_lock<mutex> lk(mtx);
        cond.wait(lk,[this](){return flag==2;});
        // printThird() outputs "third". Do not change or remove this line.
        printThird();
        flag=3;
        // cout<<33<<endl;
    }

    mutex mtx;
    condition_variable cond;
    int flag=0;
};

希望这会引导您提出新的想法。

p.s。欢迎来到stackoverflow。 ?