Tarun Kurella
Tarun Kurella

Reputation: 807

Another exception was thrown: No Material widget found

So basically there is this product edit page which behaves differently uppon called.

If the product is being created for first time, then it is shown in a tab view controller.

if the product is being updated, its body is returned in scaffold.

here are some screenshots Create item screnshootupdate item screnshoot

when I submit through create product, i encounter no error.

But when I submit through update product, though the logic works, i get a short red screen with

like this

enter image description here

error Another exception was thrown: No Material widget found.

Here is the code for the screen

`

import 'package:flutter/material.dart';
import 'package:academy_app/models/products.dart';
import 'package:scoped_model/scoped_model.dart';
import 'package:academy_app/scoped-model/Products.dart';

class ProductEdit extends StatefulWidget {
  ProductEdit();

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return ProductEditState();
  }
}

class ProductEditState extends State<ProductEdit> {
  String title;
  String description;
  double price;
  Product product;

  final focusnode2 = FocusNode();
  final focusnode3 = FocusNode();
  Map<String, dynamic> formData = {
    "name": null,
    "desc": null,
    "price": null,
    "image": "asset/foood.jpg"
  };

  GlobalKey<FormState> formkey = GlobalKey<FormState>();

  Widget buildTitle(productItem) {
    return TextFormField(
      initialValue: productItem != null ? productItem.title : "",
      validator: (String value) {
        if (value.isEmpty || value.length < 3) {
          return 'title cannot be empty';
        }
      },
      textInputAction: TextInputAction.next,
      decoration: InputDecoration(labelText: "Title"),
      onFieldSubmitted: (String value) {
        FocusScope.of(context).requestFocus(focusnode2);
      },
      onSaved: (String valuee) {
        setState(() {
          formData["name"] = valuee;
        });
      },
    );
  }

  Widget buildDesc(productItem) {
    return TextFormField(
      initialValue: productItem != null ? productItem.description : "",
      validator: (String value) {
        if (value.isEmpty || value.length < 3) {
          return 'Cant have that short description';
        }
      },
      textInputAction: TextInputAction.next,
      onFieldSubmitted: (value) {
        FocusScope.of(context).requestFocus(focusnode3);
      },
      focusNode: focusnode2,
      maxLines: 3,
      decoration: InputDecoration(labelText: "Description"),
      onSaved: (String valuee) {
        setState(() {
          formData["desc"] = valuee;
        });
      },
    );
  }

  Widget buildPrice(productItem) {
    return TextFormField(
      initialValue: productItem != null ? productItem.price.toString() : "",
      textInputAction: TextInputAction.done,
      focusNode: focusnode3,
      decoration: InputDecoration(labelText: " How much"),
      keyboardType: TextInputType.number,
      onFieldSubmitted: (value) {
        focusnode3.unfocus();
      },
      validator: (value) {
        if (!RegExp(r'^(?:[1-9]\d*|0)?(?:\.\d+)?$').hasMatch(value)) {
          return ' Enter numbers only';
        }
      },
      onSaved: (String valuee) {
        setState(() {
          formData["price"] = double.parse(valuee);
        });
      },
    );
  }

  void submitForm(Function addProduct, Function updateProduct, int index) {
    if (!formkey.currentState.validate()) {
      return;
    }
    formkey.currentState.save();
    setState(() {
      if (index == null) {
        addProduct(Product(
            price: formData["price"],
            title: formData["name"],
            description: formData["desc"],
            image: "asset/foood.jpg"));
      } else {
        updateProduct(
          Product(
              price: formData["price"],
              title: formData["name"],
              description: formData["desc"],
              image: "asset/foood.jpg"),
        );
      }
      Navigator.pushReplacementNamed(context, '/');
    });
  }

  Widget buildSubmitButton() {
    return ScopedModelDescendant<ProductsModel>(
      builder: (BuildContext context, Widget, ProductsModel) {
        return RaisedButton(
            child: Text("Save"),
            onPressed: () => submitForm(ProductsModel.addProduct,
                ProductsModel.updateProduct, ProductsModel.selected_index));
      },
    );
  }

  Widget _buildPageContent(BuildContext context, Product product) {
    final double deviceWidth = MediaQuery.of(context).size.width;
    final double targetWidth = deviceWidth > 550.0 ? 500.0 : deviceWidth * 0.95;
    final double targetPadding = deviceWidth - targetWidth;
    return GestureDetector(
      onTap: () {
        FocusScope.of(context).requestFocus(FocusNode());
      },
      child: Container(
        margin: EdgeInsets.all(10.0),
        child: Form(
          key: formkey,
          child: ListView(
            padding: EdgeInsets.symmetric(horizontal: targetPadding / 2),
            children: <Widget>[
              buildTitle(product),
              buildDesc(product),
              buildPrice(product),
              SizedBox(
                height: 10.0,
              ),
              buildSubmitButton()

            ],
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {


    return ScopedModelDescendant<ProductsModel>(
      builder: (context, Widget child, ProductsModel) {
        product = ProductsModel.getproduct();



        return ProductsModel.selected_index == null
            ? _buildPageContent(context, product)
            : Scaffold(
                appBar: AppBar(
                  title: Text("Update Item"),
                ),
                body:_buildPageContent(context, product) ,
              );
      },
    );
  }
}

`

why am i getting that red screen error? i confused about passing the contexts. why arent the textfiled accessing the material parent through in scaffold?

Upvotes: 1

Views: 5414

Answers (5)

Hamza Al Sheikh
Hamza Al Sheikh

Reputation: 16

Just wrap the Gesture Detector inside Material:

return Material(
      child: GestureDetector(
          ...
      ),
);

Upvotes: 0

Sadhvik Chirunomula
Sadhvik Chirunomula

Reputation: 1619

I had same issue. I got the error when I had code like this.

Widget _getLCSBar(int index) {
    return Container(
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black, width: 0.1),
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                _getLikeButton(index),
                _getCommentButton(index),
                _getShareButton(index),
              ],
            ));
}  

What I have done is wrapped it with Material

  Widget _getLCSBar(int index) {
    return Material(
        child: Container(
            decoration: BoxDecoration(
              border: Border.all(color: Colors.black, width: 0.1),
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                _getLikeButton(index),
                _getCommentButton(index),
                _getShareButton(index),
              ],
            )));
  }

Problem Solved!

Upvotes: 0

NearHuscarl
NearHuscarl

Reputation: 81330

In my case I forgot to wrap my widget with Scaffold widget. A lot of widgets need to be wrapped with it to work properly. So change this

Widget build(BuildContext context) {
  return YourScreenContent();
}

to this

Widget build(BuildContext context) {
  return Scaffold(
    body: YourScreenContent(),
  );
}

Upvotes: 1

Rudrik Patel
Rudrik Patel

Reputation: 696

As the error suggests that no material widget found, you need to wrap the Container of the _buildPateContent function into Material Widget. Here is the change that you can do:

  Widget _buildPageContent(BuildContext context, Product product) {
    final double deviceWidth = MediaQuery.of(context).size.width;
    final double targetWidth = deviceWidth > 550.0 ? 500.0 : deviceWidth * 0.95;
    final double targetPadding = deviceWidth - targetWidth;
    return GestureDetector(
      onTap: () {
        FocusScope.of(context).requestFocus(FocusNode());
      },
      child: Material(
          child: Container(
        margin: EdgeInsets.all(10.0),
        child: Form(
          key: formkey,
          child: ListView(
            padding: EdgeInsets.symmetric(horizontal: targetPadding / 2),
            children: <Widget>[
              buildTitle(product),
              buildDesc(product),
              buildPrice(product),
              SizedBox(
                height: 10.0,
              ),
              buildSubmitButton()
            ],
          ),
        ),
      ),
    ));
  }

Upvotes: 3

parth jansari
parth jansari

Reputation: 178

try wrapping you app in materialApp or wrap TextField in material Widget.

Upvotes: 1

Related Questions