【问题标题】:Flutter - Applying Background Gradient to Scrollable ViewFlutter - 将背景渐变应用于可滚动视图
【发布时间】:2020-04-21 10:47:23
【问题描述】:

有没有办法在 Flutter 中将完整的背景渐变应用到可滚动视图(例如 ListView 或 SingleChildScrollView)?我尝试了各种方法,例如将渐变应用到 Scaffold 或将 Scaffold 包裹在 Container 中,但渐变似乎只是随着内容滚动而不是应用到完整的可滚动高度。

示例:DartPad example

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Container(
        decoration: BoxDecoration(
          gradient:LinearGradient(
            begin: Alignment.topCenter,
            end: FractionalOffset.bottomCenter,
            colors: [Colors.green, Colors.orange],
            stops: [0, 1],
          ),
        ),
        child: Scaffold(
          backgroundColor: Colors.transparent,
          body: Center(
            child: ListView.builder(
              itemCount: 500,
              itemBuilder: (_, index) => Text('$index'),
            ),
          ),
        ),
      ),
    );
  }
}

【问题讨论】:

    标签: flutter dart flutter-layout


    【解决方案1】:

    我无法让渐变滚动。但是,如果您不介意将 ListView 的子项设置为固定高度,则有一种解决方法!

    1. 将渐变另存为图片
    2. 创建一个有状态的小部件,我们的带有渐变背景的ListView会放在这里。
    3. 把我们刚刚创建的图片放在固定高度Container,图片作为背景图片;固定高度是ListView的总高度。
    4. 用 SingleChildScrollView 包装 Container。为此创建一个新的ScrollController
    5. ListViewContainer 包装在Stack 中。同时为ListView 创建一个新控制器。
    6. 在自定义 Widget 的 initState 方法中,我们将为 bg 设置控制器以跟踪 ListView 的移动。

    我们的代码将如下所示:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          home: Scaffold(
            backgroundColor: Colors.transparent,
            body: MyListView(),
          ),
        );
      }
    }
    
    class MyListView extends StatefulWidget {
      @override
      _MyListViewState createState() => _MyListViewState();
    }
    
    class _MyListViewState extends State<MyListView> {
      final ScrollController listViewController = ScrollController();
      final ScrollController backgroundController = ScrollController();
      final int itemCount = 500;
      final double itemHeight = 20.0;
    
      @override
      void initState() {
        listViewController.addListener(() {
          backgroundController.jumpTo(listViewController.offset);
        });
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: <Widget>[
    
            // Our gradient background
            SingleChildScrollView(
              physics: NeverScrollableScrollPhysics(),
              controller: backgroundController,
              child: Container(
                height: itemCount * itemHeight,
                decoration: BoxDecoration(
                  image: DecorationImage(
                    image: AssetImage('assets/images/gradient.png'),
                    fit: BoxFit.cover,
                    repeat: ImageRepeat.noRepeat,
                  ),
                ),
              ),
            ),
    
            ListView.builder(
              controller: listViewController,
              shrinkWrap: true,
              itemCount: itemCount,
              itemBuilder: (_, index) => SizedBox(
                height: itemHeight,
                child: Text(index.toString()),
              ),
            ),
          ],
        );
      }
    
      @override
      void dispose() {
        listViewController.dispose();
        backgroundController.dispose();
        super.dispose();
      }
    }
    

    【讨论】:

    • 嗨,斯文,您的解决方案运行良好 (+1)。您实际上并不需要背景图片:只需使用 @NotoriousV2 提供的原始 BoxDecoration 即可,一切正常。
    【解决方案2】:

    它工作正常!用 dartpad 测试!

    如果可行,请接受答案!

    import 'package:flutter/material.dart';
    
        void main() {
          runApp(MyApp());
        }
    
        class MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            return MaterialApp(
              debugShowCheckedModeBanner: false,
              home: Scaffold(
                body: SingleChildScrollView(
                  child: Container(
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        begin: Alignment.topCenter,
                        end: FractionalOffset.bottomCenter,
                        colors: [Colors.green, Colors.orange],
                        stops: [0, 1],
                      ),
                    ),
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: List.generate(500, (ind) {
                        return ListTile(
                          title: Text('$ind'),
                        );
                      }).toList(),
                    ),
                  ),
                ),
              ),
            );
          }
        }
    

    【讨论】:

      猜你喜欢
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-29
      相关资源
      最近更新 更多