Search code examples
jsonapiflutterbuttonpageviews

How do I switch to another employee by clicking on the "NEXT" button? And how do I add a page after PageView.builder?


I have employees with their images, names, and emails displayed in pageView form "the number of employees depends on the Http query of the JSON API." I want to switch from one employee to another by clicking on the "NEXT" button. In addition, I would like to add a page after viewing all PageViews employees.

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Employees(),
    );
  }
}

class Employees extends StatefulWidget {
  @override
  _EmployeesState createState() => _EmployeesState();
}

class _EmployeesState extends State<Employees> {
  PageController _controller = PageController(initialPage: 0,);

  getEmployees()async{
    String theUrl = 'http://demo8161595.mockable.io/employee';
    var res = await http.get(Uri.encodeFull(theUrl),headers:{"Accept":"application/json"});
    var responsBody = json.decode(res.body);
    print(responsBody);
    return responsBody;
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title:Text("Employees") ,
      ),
      body:FutureBuilder(
        future: getEmployees(),
        builder: (BuildContext context , AsyncSnapshot snapshot){
          List snap = snapshot.data;
          if(snapshot.connectionState == ConnectionState.waiting){
            return Center(
              child: CircularProgressIndicator(),
            );
          }
          if(snapshot.hasError){
            return Center(
              child: Text("Error .... "),
            );
          }

          return PageView.builder(
            itemCount: snap.length,
            itemBuilder: (context,index){
              return PageView(
                controller:_controller,
                children: <Widget>[
                  Container(
                    padding: EdgeInsets.all(5.0),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[
                        Center(
                          child: CircleAvatar(
                            radius: 50.0,
                            backgroundImage:
                            NetworkImage("${snap[index]['avatar']}"),
                            backgroundColor: Colors.transparent,
                          ),
                        ),
                        SizedBox(height: 10.0),
                        Padding(
                          padding: EdgeInsets.all(5.0),
                          child:Column(
                            crossAxisAlignment: CrossAxisAlignment.stretch,
                            mainAxisAlignment: MainAxisAlignment.start,
                            children: <Widget>[

                              Text(
                                'Name',
                                style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold,),
                              ),
                              SizedBox(height: 5.0),
                              Text("${snap[index]['firstName']}" + "  " + "${snap[index]['lastName']}",style: TextStyle(fontSize: 20)),
                            ],
                          ),
                        ),
                        SizedBox(height: 10.0),
                        Padding(
                          padding: EdgeInsets.all(5.0),
                          child:Column(
                            crossAxisAlignment: CrossAxisAlignment.stretch,
                            mainAxisAlignment: MainAxisAlignment.start,
                            children: <Widget>[
                              Text(
                                'Email',
                                style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold,),
                              ),
                              SizedBox(height: 5.0),
                              Text("${snap[index]['email']}",style: TextStyle(fontSize: 20)),
                            ],
                          ),
                        ),
                        SizedBox(height:5.0),
                        Padding(
                          padding: EdgeInsets.all(5.0),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.stretch,
                            mainAxisAlignment: MainAxisAlignment.start,
                            children: <Widget>[
                              SizedBox(height: 20.0),
                              Center(
                                child: Container(
                                    padding: const EdgeInsets.all(8.0),
                                  child:  Center(
                                    child:Container(
                                      child: RaisedButton.icon(
                                        onPressed: () {
                                          int page = _controller.page.toInt();
                                          _controller.animateToPage(page + 1 ,  duration: Duration(milliseconds: 500),curve: Curves.ease,);
                                          _controller.jumpToPage(page+1);
                                          if(_controller.page.toInt() == snap.length)
                                          {
                                            Container(
                                              child: Center(
                                                child: Text("Last Page"),
                                              ),
                                            );
                                          }
                                        },
                                        color: Colors.teal,
                                        icon: Icon(Icons.navigate_next,color:Colors.white ,),
                                        label: Text("NEXT",style: TextStyle(color: Colors.white),),
                                      ),
                                    ),
                                  ),
                                ),
                              ),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              );
            },
          );
        },
      ),
    );
  }
}

Solution

  • EDIT 2: Changed the code.

    import 'dart:convert';
    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Employees(),
        );
      }
    }
    
    class Employees extends StatefulWidget {
      @override
      _EmployeesState createState() => _EmployeesState();
    }
    
    class _EmployeesState extends State<Employees> {
      PageController _controller = PageController(initialPage: 0,);
    
      getEmployees()async{
        String theUrl = 'http://demo8161595.mockable.io/employee';
        var res = await http.get(Uri.encodeFull(theUrl),headers:{"Accept":"application/json"});
        var responsBody = json.decode(res.body);
        print(responsBody);
        return responsBody;
      }
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: new AppBar(
            title:Text("Employees") ,
          ),
          body:FutureBuilder(
            future: getEmployees(),
            builder: (BuildContext context , AsyncSnapshot snapshot){
              List snap = snapshot.data;
              if(snapshot.connectionState == ConnectionState.waiting){
                return Center(
                  child: CircularProgressIndicator(),
                );
              }
              if(snapshot.hasError){
                return Center(
                  child: Text("Error .... "),
                );
              }
    
              return PageView.builder(
                itemCount: snap.length,
                itemBuilder: (context,index){
                  return PageView(
                    controller:_controller,
                    children: snap.map((e) => employeePage(e,snap.length)).toList(),
                  );
                },
              );
            },
          ),
        );
      }
    
      Widget employeePage(node , length)
      {
        return Container(
                        padding: EdgeInsets.all(5.0),
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          children: <Widget>[
                            Center(
                              child: CircleAvatar(
                                radius: 50.0,
                                backgroundImage:
                                NetworkImage("${node['avatar']}"),
                                backgroundColor: Colors.transparent,
                              ),
                            ),
                            SizedBox(height: 10.0),
                            Padding(
                              padding: EdgeInsets.all(5.0),
                              child:Column(
                                crossAxisAlignment: CrossAxisAlignment.stretch,
                                mainAxisAlignment: MainAxisAlignment.start,
                                children: <Widget>[
    
                                  Text(
                                    'Name',
                                    style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold,),
                                  ),
                                  SizedBox(height: 5.0),
                                  Text("${node['firstName']}" + "  " + "${node['lastName']}",style: TextStyle(fontSize: 20)),
                                ],
                              ),
                            ),
                            SizedBox(height: 10.0),
                            Padding(
                              padding: EdgeInsets.all(5.0),
                              child:Column(
                                crossAxisAlignment: CrossAxisAlignment.stretch,
                                mainAxisAlignment: MainAxisAlignment.start,
                                children: <Widget>[
                                  Text(
                                    'Email',
                                    style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold,),
                                  ),
                                  SizedBox(height: 5.0),
                                  Text("${node['email']}",style: TextStyle(fontSize: 20)),
                                ],
                              ),
                            ),
                            SizedBox(height:5.0),
                            Padding(
                              padding: EdgeInsets.all(5.0),
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.stretch,
                                mainAxisAlignment: MainAxisAlignment.start,
                                children: <Widget>[
                                  SizedBox(height: 20.0),
                                  Center(
                                    child: Container(
                                        padding: const EdgeInsets.all(8.0),
                                      child:  Center(
                                        child:Container(
                                          child: RaisedButton.icon(
                                            onPressed: () {
                                              int page = _controller.page.toInt();
                                              _controller.animateToPage(page + 1 ,  duration: Duration(milliseconds: 500),curve: Curves.ease,);
                                              _controller.jumpToPage(page+1);
                                              if(_controller.page.toInt() == length)
                                              {
                                                Container(
                                                  child: Center(
                                                    child: Text("Last Page"),
                                                  ),
                                                );
                                              }
                                            },
                                            color: Colors.teal,
                                            icon: Icon(Icons.navigate_next,color:Colors.white ,),
                                            label: Text("NEXT",style: TextStyle(color: Colors.white),),
                                          ),
                                        ),
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ],
                        ),
                      );
      }
    }
    

    EDIT 1: After you have changed the code i have realized your mistake.

    This is how the PageView widget works

    PageView(
      controller: _controller,
      children: [
        MyPage1Widget(),
        MyPage2Widget(),
        MyPage3Widget(),
      ],
    )
    

    Here you are providing 3 screens in the children of the PageView and asking page view to go to the next one when _controller.jumpToPage() or _controller.next() is called.

    But in your code, in the PageView widget children you have provided a single container, so there is only one screen to show. Which is why you are not able to see any changes.

    Previous Answer :

    What you need is the PageViewController through which you can jump/animate to any page.

    STEP 1 : instantiate the Page View Controller

    class _EmployeesState extends State<Employees> {
    PageController _controller = PageController(
        initialPage: 0,
    );
    

    STEP 2 : Add the Page View Controller in the PageView

           return PageView(
                    controller:_controller
                    children: <Widget>[
                      Container(
                        padding: EdgeInsets.all(5.0),
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          children: <Widget>[
                            Center(
                              child: CircleAvatar(
                                radius: 50.0,
                                backgroundImage:
                                NetworkImage("${snap[index]['avatar']}"),
                                backgroundColor: Colors.transparent,
                              ),
                            ),
                            .....
    

    STEP 3 : Change the page view when button tapped

    onTap: () {
    //Current page
    int page = _controller.page.toInt();
    
    //Animate to page
    _controller.animateToPage(page + 1);
    
    //Jump to page
    controller.animateToPage(page + 1);
    
    //if page view reaches last page
    if(controller.page.toInt() == snap.length)
    {
      //Navigate to some page
    }
    
    }
    

    Given above is the OnTapped function, you can wrap the Text widget in a Button and insert the code in the ontapped parameter.

    Let me know if you face errors.