Флаттер шоу градиента делителя верхней части ListView - PullRequest
0 голосов
/ 18 апреля 2020

в этом примере кода, который имеет ListView и Container, я хотел бы сделать простой верх градиента ListView, когда пользователь прокручивает элементы ListView вправо или влево,

прокручивает элементы вправо должен показывать делитель градиента, а прокрутка влево должна скрывать делитель, вся эта видимость должна иметь эффект затухания. Не могли бы вы помочь мне, как я могу показать и скрыть этот делитель градиента?

enter image description here

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() => runApp(SampleShadow());

class SampleShadow extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'sample',
      home: ShadowContainer(),
    );
  }
}

class ShadowContainer extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _ShadowContainer();
}

class _ShadowContainer extends State<ShadowContainer> with TickerProviderStateMixin {
  final ValueNotifier<bool> showShadow = ValueNotifier<bool>(false);

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.rtl,
      child: Scaffold(
        backgroundColor: Colors.indigo.withOpacity(0.7),
        appBar: AppBar(),
        body: Container(
          margin: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Container(
                height: 100.0,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(10.0),
                ),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Container(
                      width: 50.0,
                      height: 50.0,
                      decoration: BoxDecoration(
                        color: Colors.indigo[400],
                        borderRadius: BorderRadius.circular(100.0),
                      ),
                    ),
                    Expanded(
                      child: Stack(children: <Widget>[
                        NotificationListener<ScrollNotification>(
                          onNotification: (scrollState) {
                            if (scrollState is ScrollEndNotification && scrollState.metrics.pixels >= 100) {
                              showShadow.value = true;
                              print('show');
                            } else {
                              showShadow.value = false;
                              print('hide');
                            }
                            return false;
                          },
                          child: ListView.separated(
                              scrollDirection: Axis.horizontal,
                              itemBuilder: (context, index) {
                                return Container(
                                  margin: const EdgeInsets.all(10.0),
                                  width: 50.0,
                                  height: 50.0,
                                  decoration: BoxDecoration(
                                    color: Colors.purple[400],
                                    borderRadius: BorderRadius.circular(100.0),
                                  ),
                                );
                              },
                              separatorBuilder: (context, index) {
                                return const Divider();
                              },
                              itemCount: 50),
                        ),
                        ValueListenableBuilder<bool>(
                            valueListenable: showShadow,
                            builder: (context, value, child) => value? Container(
                                  width: 10.0,
                                  color: Colors.green,
                                ): Container()),
                      ]),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

1 Ответ

0 голосов
/ 18 апреля 2020

это решение отлично работает, благодаря @ CopsOnRoad

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() => runApp(SampleShadow());

class SampleShadow extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'sample',
      home: ShadowContainer(),
    );
  }
}

class ShadowContainer extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _ShadowContainer();
}

class _ShadowContainer extends State<ShadowContainer> with TickerProviderStateMixin {
  final ValueNotifier<bool> showShadow = ValueNotifier<bool>(false);
  AnimationController _animationController;
  Animation<double> _fadeInFadeOut;
  ScrollController _scrollController;

  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController();
    _animationController = AnimationController(vsync: this, duration: kThemeAnimationDuration);
    _fadeInFadeOut = Tween<double>(begin: 0.0, end: 1.0).animate(_animationController);
    _animationController.forward();
    _scrollController.addListener(() {
      if (_scrollController.offset >= 10) {
        showShadow.value = true;
      } else {
        showShadow.value = false;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.rtl,
      child: Scaffold(
        backgroundColor: Colors.indigo.withOpacity(0.7),
        appBar: AppBar(),
        body: Container(
          margin: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Container(
                height: 100.0,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(10.0),
                ),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Container(
                      width: 50.0,
                      height: 50.0,
                      decoration: BoxDecoration(
                        color: Colors.indigo[400],
                        borderRadius: BorderRadius.circular(100.0),
                      ),
                    ),
                    Expanded(
                      child: Stack(children: <Widget>[
                        ListView.separated(
                            controller: _scrollController,
                            scrollDirection: Axis.horizontal,
                            itemBuilder: (context, index) {
                              return Container(
                                margin: const EdgeInsets.all(10.0),
                                width: 50.0,
                                height: 50.0,
                                decoration: BoxDecoration(
                                  color: Colors.purple[400],
                                  borderRadius: BorderRadius.circular(100.0),
                                ),
                              );
                            },
                            separatorBuilder: (context, index) {
                              return const Divider();
                            },
                            itemCount: 50),
                        ValueListenableBuilder<bool>(
                            valueListenable: showShadow,
                            builder: (context, value, child) {
                              if (value) {
                                _animationController.forward();
                              } else {
                                _animationController.reverse();
                              }
                              return FadeTransition(
                                opacity: _fadeInFadeOut,
                                child: Container(
                                  width: 10.0,
                                  decoration: BoxDecoration(
                                      gradient: LinearGradient(
                                          begin: Alignment.centerRight,
                                          end: Alignment.centerLeft,
                                          colors: [Colors.black.withOpacity(0.5), Colors.transparent])),
                                ),
                              );
                            }),
                      ]),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
...