Flutter Stateful widget - Part3 - InheritedWidget Example - Sample Post List

Hello Guys in previous post we discussed Statefull widget and How to access state of widget.


In this post i am going to show you how to handle state with InheritedWidget

In this Example we are going to create posts and display list of posts

For this First create a Class with name Post

class Post{
  var title;
  var desc;
  Post(this.title,this.desc);
}

 

Now Create InheritedWidget

class _InheritedWidget extends InheritedWidget {
  _InheritedWidget({
    Key key,
    @required Widget child,
    this.data,
  }): super(key: key, child: child);

  final MyInheritedWidgetState data;

  @override
  bool updateShouldNotify(_InheritedWidget oldWidget) {
    return true;
  }
}

 

in the above class we have defined MyInheritedWidgetState which will have the data,
so lets create that widget

class MyInheritedWidgetState extends State
{

  List _items = [];

  /// Getter (number of items)
  int get itemsCount => _items.length;
  List get items => _items;

  /// Helper method to add an Item
  void addItem(title,description){
    setState((){
      _items.add(new Post(title,description));
    });
  }
  @override
  Widget build(BuildContext context){
    return  _InheritedWidget(
      data: this,
      child: widget.child,
    );
  }
}

 

This class contains list object(_items) wich stores created posts.
The method addItem() will be used to add the post into list while create post from child widgets

Now Design widgets to create Post and display list of Posts

Create Post Widget

 

class CreatePost extends StatelessWidget{
  TextEditingController _titleControler=TextEditingController();
  TextEditingController _descControler=TextEditingController();
  @override
  Widget build(BuildContext context) {
    final MyInheritedWidgetState state = MyInheritedWidget.of(context);
    FocusNode textSecondFocusNode = new FocusNode();
    return SingleChildScrollView(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(

          children: [
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: TextField(
              controller: _titleControler,

              onSubmitted: (value){
                FocusScope.of(context).requestFocus(textSecondFocusNode);
              },
              decoration: InputDecoration(

                hintText: "Enter Post Title",

                focusedBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(22),
                  borderSide: BorderSide(color: Colors.pink,width: 2)


                ),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12),


                )
              ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: TextField(
                maxLines: 10,
                minLines: 4,
                controller: _descControler,
                onSubmitted: (value){

                },
                focusNode: textSecondFocusNode,
                decoration: InputDecoration(
                    hintText: "Enter Post Description",
                    focusedBorder: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(22),
                        borderSide: BorderSide(color: Colors.pink,width: 2)


                    ),
                    border: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(12),


                    ),

                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                color: Colors.pink,
                child: Text("Create",style: TextStyle(color: Colors.white,fontSize: 20),),
                onPressed: (){
                  state.addItem(_titleControler.text, _descControler.text);

                  _titleControler.text="";
                  _descControler.text="";
                },

              ),
            )
          ],
        ),
      ),
    );
  }

}

 

This create post widget having two textfileds to write Post title and Description and one button to create post.
Here we are using  final MyInheritedWidgetState state = MyInheritedWidget.of(context) to add post into list.

 

Display List of Posts

class MyPosts extends StatefulWidget{


  @override
  State createState() {
    // TODO: implement createState
    return _MyPostsState();
  }

}
class _MyPostsState extends State{
  @override
  Widget build(BuildContext context) {
    final MyInheritedWidgetState state = MyInheritedWidget.of(context);
    return Container(
      color: Colors.grey,
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: ListView.builder(

          itemBuilder: (context,index){
          return Container(
            margin: EdgeInsets.all(5),
            child: Card(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  mainAxisSize: MainAxisSize.max,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(state.items[index].title,style: TextStyle(fontSize: 20,color: Colors.pink),),
                    SizedBox(height: 10,),
                    Text(state.items[index].desc,style: TextStyle(fontSize: 14,color: Colors.brown),)
                  ],
                ),
              ),
            ),
          );
        },
        itemCount: state.itemsCount,
        ),
      ),
    );
  }

 

Now here is time to use our InheritedWidget to load its child

class MyApp extends StatefulWidget{
  @override
  State createState() {
    // TODO: implement createState
    return _MyAppState();
  }

}

class _MyAppState extends State with TickerProviderStateMixin
{
  TabController _tabController=TabController(length: 2, vsync: AnimatedListState(),initialIndex: 0);
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MyInheritedWidget(

      child: SafeArea(
        child: Scaffold(
          appBar: AppBar(
            title: Text("Social App",),
            backgroundColor: Colors.pink,
            bottom: TabBar(tabs: [
              Tab(child: Text("CreatePost"),),
              Tab(child: Text("MyPosts"),),
            ],controller: _tabController,),
          ),
          body: TabBarView(


            children: [
              CreatePost(),
              MyPosts(),
            ],
          ),
        ),
      ),
    );

  }

}

 

Here we are taking the InheritedWidget as parent widget and passing SafeArea with TabBar as child

Now lets call this widget in the main method 
 

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

class MyApps extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(

        primarySwatch: Colors.blue,
      ),
      home: MyApp(),
    );
  }
}

 

Now lets run the code and you will check the magic of changing the state object in two widgets