首页 > 解决方案 > 为什么提供程序包不更改背景图像?

问题描述

我已将提供程序包添加到我有两个屏幕的应用程序中。当用户单击应用程序上的小图像时,它会更改另一个屏幕上的主背景图像。我在两个屏幕上都调用了 Provider 和类,但它只是没有返回 Positioned.fill 中的“myValue”。

带有需要更改的背景图像的主页屏幕:

import 'package:flutter/material.dart';
import 'package:flutter_app_background/small_images.dart';
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';


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


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<MyModel>(
      create: (context) => MyModel(),
      child: MaterialApp(
        title: 'Title',
        home: HomePage(),
      ),
    );
  }
}

class HomePage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
      return Scaffold(
        extendBodyBehindAppBar: true,
        appBar: AppBar(
          title: Text('Background Image', style: TextStyle(
              color: Colors.black,
              fontSize: 16,
              fontWeight: FontWeight.bold),
          ),
          iconTheme: IconThemeData(color: Colors.white),
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.settings, color: Colors.black,),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SmallImages()),
                );
              },
            ),
          ],
          backgroundColor: Colors.transparent,
          elevation: 0.0,
        ),
        body: Stack(
          children: <Widget>
          [
            Positioned.fill(
              child: GestureDetector(
                child: Consumer<MyModel>(
                  builder: (context, myModel, child) {
                    return myModel.bgImage;
                    // return myValue;
                  },
                ),
              ),
            ),
          ],
        ),
      );
    }
}

class MyModel extends ChangeNotifier {
  Image bgImage = Image.asset('images/background_image.jpeg', fit: BoxFit.fill);

}

小图像屏幕,用户点击小图像以更改主页中的背景。

import 'package:flutter/material.dart';
import 'package:flutter_app_background/main.dart';
import 'package:provider/provider.dart';


class SmallImages extends StatefulWidget {
  static int tappedGestureDetector = 1;

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

class _SmallImagesState extends State<SmallImages> {

  List<bool> isSelected;

  void initState() {
    isSelected = [true, false, false, false, false, false, false, false, false];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final myModel = Provider.of<MyModel>(context,listen:true); //default for listen is `true`
    return Scaffold(
          appBar: AppBar(
            title: Text('Small Image', style: TextStyle(
                color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold),
            ),
            iconTheme: IconThemeData(color: Colors.white),
            actions: <Widget>[
              IconButton(
                icon: Icon(Icons.arrow_left, color: Colors.black,),
                onPressed: () {
                  Navigator.pop(
                    context,
                    MaterialPageRoute(builder: (context) => HomePage()),
                  );
                },
              ),
            ],
            backgroundColor: Colors.transparent,
            elevation: 0.0,
          ),
          body: Material(
            child: GestureDetector(
              child: MaterialApp(
                  builder: (context, snapshot) {
                    return GridView.count(
                      crossAxisCount: 1,
                      childAspectRatio: 1.0,
                      padding: const EdgeInsets.all(4.0),
                      mainAxisSpacing: 0.0,
                      crossAxisSpacing: 0.0,
                      children: [
                        GridView(
                          gridDelegate:
                          SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3,
                            childAspectRatio: MediaQuery
                                .of(context)
                                .size
                                .width /
                                (MediaQuery
                                    .of(context)
                                    .size
                                    .height / 2),
                          ),
                          children: [
                              GestureDetector(
                                onTap: () {
                                  setState(() {
                                    SmallImages.tappedGestureDetector = 1;
                                  });
                                  myModel.bgImage = Image.asset('images/iceland_background.jpg');
                                },
                                child: Container(
                                  height: 100,
                                  width: 107,
                                  decoration: BoxDecoration(border: SmallImages
                                      .tappedGestureDetector == 1
                                      ? Border.all(
                                      color: Color(0xff2244C7), width: 1.0)
                                      : Border
                                      .all(color: Colors.transparent,),),
                                  child: Image.asset(
                                    'images/nightsky_image.png',
                                  ),
                                ),
                            ),
                            Consumer<MyModel>(
                              builder: (context, myModel, child) {
                                return GestureDetector(
                                  onTap: () {
                                    setState(() {
                                      SmallImages.tappedGestureDetector = 2;
                                    }); // <-- replaced 'tapped' and 'other'
                                  },
                                  child: Container(
                                    height: 100,
                                    width: 107,
                                    decoration: BoxDecoration(border: SmallImages
                                        .tappedGestureDetector == 2
                                        ? Border.all(
                                        color: Color(0xff2244C7), width: 1.0)
                                        : Border
                                        .all(color: Colors.transparent,),),
                                    child: Image.asset(
                                      'images/own_image.png',
                                    ),
                                  ),
                                );
                              },
                            ),
                            Consumer<MyModel>(
                              builder: (context, myModel, child) {
                                return GestureDetector(
                                  onTap: () {
                                    setState(() {
                                      SmallImages.tappedGestureDetector = 3;
                                    }); // <-- replaced 'tapped' and 'other'
                                  },
                                  child: Container(
                                    height: 100,
                                    width: 107,
                                    decoration: BoxDecoration(border: SmallImages
                                        .tappedGestureDetector == 3
                                        ? Border.all(
                                        color: Color(0xff2244C7), width: 1.0)
                                        : Border
                                        .all(color: Colors.transparent,),),
                                    child: Image.asset(
                                      'images/iceland_image.png',
                                    ),
                                  ),
                                );
                              },
                            ),
                          ].toList(),
                        ),
                      ],
                    );
                  }),
            ),
          ),
        );
  }
}

标签: flutterbackgroundstatestatefulflutter-onpressed

解决方案


您应该用提供者包装材料应用程序:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Provider<MyModel>(
      create: (context) => MyModel(),
      child: MaterialApp(
        title: 'Title',
        home: HomePage(),
      );
    )

  }
}

如果您希望它在 MyModel 更改时重建一些小部件,您应该使用 ChangeNotifer 扩展 MyModel,如下所示:

class MyModel extends ChangeNotifier{
final bgImage = //someimage

而不是周围的 ProviderMaterialApp你应该ChangeNotifierProvider像这样使用:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<MyModel>(
      create: (context) => MyModel(),
      child: MaterialApp(
        title: 'Title',
        home: HomePage(),
      );
    )

  }
}

之后,您应该在小部件中包含提供程序,如下所示:

  @override
  Widget build(BuildContext context) {
    final mymodel = Provider.of<MyModel>(context); // injecting the provider
    return Container ( .....

你可以像这样在容器内使用背景图片,

color:mymodel.bgImage

只要您更改mymodel.bgImage小部件,就会自动重建。

如果您打算widget在. widget tree_final mymodel = Provider.of<MyModel>(context);widgetConsumer<MyModel>

Container(
  child:Consumer<MyModel>(
    builder: (context, myModel, child) {
    return Text("${myModel.text}"); // supposing that `text` is inside the `MyModel`
  },
)

如果您不需要在容器下使用子项和上下文,您可以这样做:

child:Consumer<MyModel>(
    builder: (_, myModel, _) {

改变的例子是myModel.bgImage这样的:

FlatButton(
onPressed: (val){
  myModel.image = otherImage  // changeing the value of my model while pressing on the button

  }
)

在按下按钮的同时更改我的模型的值将重建任何注入的小部件,MyModel Provider并且 Providerlisten属性设置为,(默认情况下true,listen 属性设置为)true

属性示例listen

final mymodel = Provider.of<MyModel>(context,listen:false) //default for listen is `true`

推荐阅读