CustomscrollView scrolled to position top automatically, when i tap a textfield in sliver app bar

4,480

First add a ScrollController to your customScrollView. Then animate to the offset position you would like eg.

class _HomeScreenState extends State<HomeScreen> {
 ScrollController scrollController;
 
  @override
void initState() {
super.initState();
scrollController = new ScrollController();
}
 @override
Widget build(BuildContext context) {
return CustomScrollView(
 controller = scrollController,
  slivers: <Widget>[
  .... your wiidgets...
 ],
);
/* this method should be called on search bar textField tapped or when on whatever 
 event 
*/
void toTop(){
 scrollController.animateTo(0,
      duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
}

Hope this helps anyone else......

Share:
4,480
SaravanaRaja
Author by

SaravanaRaja

(3208969)

Updated on December 03, 2022

Comments

  • SaravanaRaja
    SaravanaRaja over 1 year

    Developed a flutter page with search bar on top and bottom we have horizontal list view & followed by vertical list view... when i tapped on the search bar text field my below view scrolled to top position automatically.

    when I debug it the build method is calling again, how to solve the issue?

    this is the same issue happening in this example https://github.com/lohanidamodar/flutter_ui_challenges which is the reference I took from.

    src\pages\hotel\hhome.dart is the page

    enter image description here

    Here is my code is you feel this code is too big, please take a look the github example code (src\pages\hotel\hhome.dart) which has the same issue

    class _HomeScreenState extends State<HomeScreen> {
    @override
    Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: <Widget>[
        _buildSliverAppBar(),
        _buildTitle('Category'),
        _buildSliverCategoryList(),
        _buildSliverPopularProducts(),
        _buildTitle('Top Distributors'),
        _buildSliverTopDistributorsList(),
        _buildSliverClothing(),
        _buildSliverElectronics(),
        _buildSliverHealthAndBeauty(),
      ],
    );
    }
    
     //Appbar: with "search" & "filter"
    Widget _buildSliverAppBar() {
    return SliverAppBar(
      leading: Icon(null),
      backgroundColor: colorPrimary,
      elevation: 10.0,
      forceElevated: true,
      pinned: true,
      flexibleSpace: ListView(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.only(left: 16.0, right: 16.0),
            child: Row(
              children: <Widget>[
                Expanded(
                  child: Container(
                    margin: EdgeInsets.only(right: 8.0),
                    alignment: Alignment.center,
                    height: 38.0,
                    padding: EdgeInsets.only(left: 16.0),
                    decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(40.0)),
                    child: TextField(
                      style: TextStyle(fontSize: 15.0),
                      decoration: InputDecoration(
                        hintText: "Search products",
                        border: InputBorder.none,
                        suffixIcon: IconButton(
                          onPressed: () {},
                          color: colorBlack,
                          icon: Icon(Icons.search),
                          iconSize: 20,
                        ),
                      ),
                    ),
                  ),
                  flex: 1,
                ),
                RawMaterialButton(
                  splashColor: colorPrimary,
                  constraints: BoxConstraints(maxWidth: 38.0),
                  onPressed: () {},
                  child: Icon(
                    Icons.clear_all,
                    color: colorBlack,
                    size: 24.0,
                  ),
                  shape: CircleBorder(),
                  fillColor: colorWhite,
                  padding: EdgeInsets.all(7.0),
                )
              ],
            ),
          )
        ],
      ),
    );
    }
    
    //get title for the list
    Widget _buildTitle(String title) {
    return SliverToBoxAdapter(
      child: Container(
        color: colorGrey,
        child: Padding(
          padding: EdgeInsets.only(top: 8.0, left: 16.0),
          child: Align(alignment: Alignment.centerLeft, child: Text(title)),
        ),
      ),
    );
    }
    
    //get "category" list
    Widget _buildSliverCategoryList() {
    return SliverToBoxAdapter(
      child: Container(
        color: colorGrey,
        height: 100,
        child: ListView(
          padding: EdgeInsets.only(right: 16.0),
          scrollDirection: Axis.horizontal,
          children: _listCategoryModel.map((itemCategory) {
            return _buildListTileCategory(itemCategory);
          }).toList(),
        ),
      ),
    );
    }
    
     //get "category" listTile
    Widget _buildListTileCategory(CategoryModel itemCategory) {
    return Padding(
      padding: const EdgeInsets.only(left: 16.0, top: 8.0, bottom: 8.0),
      child: Container(
          alignment: Alignment.center,
          width: 55,
          child: Material(
            color: Colors.transparent,
            child: InkWell(
              splashColor: colorPrimary,
              onTap: () {
                print('clicked: category ${itemCategory.name}');
              },
              child: Column(
                children: <Widget>[
                  Card(
                    elevation: 8.0,
                    color: colorPrimary,
                    child: Container(
                      width: 55,
                      height: 55,
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 8.0),
                    child: Text(
                      itemCategory.name,
                      overflow: TextOverflow.ellipsis,
                      style: TextStyle(fontSize: 10.0),
                    ),
                  )
                ],
              ),
            ),
          )),
    );
    }
    
    //get "popular products" two item
    Widget _buildSliverPopularProducts() {
    return SliverToBoxAdapter(
      child: Container(
        padding: EdgeInsets.all(16.0),
        color: colorWhite,
        child: Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(bottom: 8.0),
              child: Row(
                children: <Widget>[
                  Expanded(child: Text('Popular Products')),
                  Text(
                    'View all',
                    style: TextStyle(color: colorPrimary),
                  ),
                ],
              ),
            ), //text: "Popular Products" title
            Row(
              children: <Widget>[getItem(), getItem()],
            )
          ],
        ),
      ),
    );
    }
    
    Widget getItem() {
    return Expanded(
      child: Card(
        elevation: 4.0,
        color: colorGrey,
        child: Container(
          child: Column(
            children: <Widget>[
              Card(
                elevation: 0.0,
                color: colorWhite,
                child: Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Container(
                    width: (getScreenWidth(context) / 2) - 24,
                    height: (getScreenWidth(context) / 2) - 24,
                    child: Stack(
                      children: <Widget>[
                        Align(
                          child: Icon(
                            Icons.favorite,
                            color: colorPrimary,
                          ),
                          alignment: Alignment.topRight,
                        )
                      ],
                    ),
                  ),
                ),
              ),
              Padding(
                padding:
                    const EdgeInsets.only(left: 4.0, right: 4.0, bottom: 8.0),
                child: Align(
                  child: Text(
                    'Default watch',
                    style: TextStyle(
                      fontSize: 12.0,
                    ),
                  ),
                  alignment: Alignment.centerLeft,
                ),
              ), //text: product name
              Padding(
                padding:
                    const EdgeInsets.only(left: 4.0, right: 4.0, bottom: 8.0),
                child: Align(
                  child: Text(
                    "\$25.75",
                    style: TextStyle(
                      color: colorPrimary,
                    ),
                  ),
                  alignment: Alignment.centerLeft,
                ),
              ), //text: product price in dollar
              Padding(
                padding:
                    const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
                child: Row(
                  children: <Widget>[
                    Expanded(
                      child: RawMaterialButton(
                        onPressed: () {},
                        child: Icon(
                          Icons.remove,
                          color: colorPrimary,
                          size: 16.0,
                        ),
                        shape: CircleBorder(),
                        elevation: 2.0,
                        fillColor: colorWhite,
                        padding: EdgeInsets.all(6.0),
                        splashColor: colorPrimary,
                      ),
                    ), //button: decrease product count
                    Expanded(
                      flex: 2,
                      child: Container(
                        margin: EdgeInsets.only(left: 8.0, right: 8.0),
                        child: AbsorbPointer(
                          //to avoid touch on the button with not like disable 
    effect
                          absorbing: true,
                          child: RaisedButton(
                            color: colorWhite,
                            textColor: colorPrimary,
                            elevation: 1.0,
                            padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
                            child: Text(
                              '0',
                              style: TextStyle(fontSize: 16.0),
                            ),
                            onPressed: () {},
                            shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(25.0)),
                          ),
                        ),
                      ),
                    ), //text: product count
                    Expanded(
                      child: RawMaterialButton(
                          onPressed: () {},
                          child: Icon(
                            Icons.add,
                            color: colorPrimary,
                            size: 16.0,
                          ),
                          shape: CircleBorder(),
                          elevation: 2.0,
                          fillColor: colorWhite,
                          padding: EdgeInsets.all(6.0),
                          splashColor: colorPrimary),
                    ) //button: increase product count
                  ],
                ),
              )
            ],
          ),
        ),
      ),
    );
    }
    
    //get "top distributors" list
    Widget _buildSliverTopDistributorsList() {
    return SliverToBoxAdapter(
      child: Container(
        color: colorGrey,
        height: 100,
        child: ListView(
          padding: EdgeInsets.only(left: 16.0, right: 16.0),
          scrollDirection: Axis.horizontal,
          children: _listCategoryModel.map((itemCategory) {
            return _buildListTileTopDistributors();
          }).toList(),
        ),
      ),
    );
    }
    
    Widget _buildListTileTopDistributors() {
    var width = (getScreenWidth(context) / 4);
    var height = (getScreenWidth(context) / 6);
    return Padding(
      padding: const EdgeInsets.only(top: 8.0, bottom: 8.0),
      child: Container(
          alignment: Alignment.center,
          width: width,
          child: Material(
            color: Colors.transparent,
            child: InkWell(
              splashColor: colorPrimary,
              onTap: () {},
              child: Card(
                elevation: 8.0,
                color: colorPrimary,
                child: Container(
                  width: width,
                  height: height,
                ),
              ),
            ),
          )),
    );
    }
    
    //get "clothing" two item
    Widget _buildSliverClothing() {
    return SliverToBoxAdapter(
      child: Container(
        padding: EdgeInsets.all(16.0),
        color: colorWhite,
        child: Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(bottom: 8.0),
              child: Row(
                children: <Widget>[
                  Expanded(child: Text('Clothing')),
                  Text(
                    'View all',
                    style: TextStyle(color: colorPrimary),
                  ),
                ],
              ),
            ), //text: "Popular Products" title
            Row(
              children: <Widget>[getItem(), getItem()],
            )
          ],
        ),
      ),
    );
    }
    
    //get "clothing" two item
    Widget _buildSliverElectronics() {
    return SliverToBoxAdapter(
      child: Container(
        padding: EdgeInsets.all(16.0),
        color: colorWhite,
        child: Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(bottom: 8.0),
              child: Row(
                children: <Widget>[
                  Expanded(child: Text('Electronics')),
                  Text(
                    'View all',
                    style: TextStyle(color: colorPrimary),
                  ),
                ],
              ),
            ), //text: "Popular Products" title
            Row(
              children: <Widget>[getItem(), getItem()],
            )
          ],
        ),
      ),
    );
    }
    
    //get "clothing" two item
    Widget _buildSliverHealthAndBeauty() {
    return SliverToBoxAdapter(
      child: Container(
        padding: EdgeInsets.all(16.0),
        color: colorWhite,
        child: Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(bottom: 8.0),
              child: Row(
                children: <Widget>[
                  Expanded(child: Text('HealthAndBeauty')),
                  Text(
                    'View all',
                    style: TextStyle(color: colorPrimary),
                  ),
                ],
              ),
            ), //text: "Popular Products" title
            Row(
              children: <Widget>[getItem(), getItem()],
            )
          ],
        ),
      ),
    );
    }
    
    
    final List<CategoryModel> _listCategoryModel = [
    CategoryModel(
        id: 0,
        name: 'Clothing',
        imageUrl: '',
        description: 'sampledescription'),
    CategoryModel(
        id: 1,
        name: 'Electronics',
        imageUrl: '',
        description: 'sampledescription'),
    CategoryModel(
        id: 2, name: 'Watches', imageUrl: '', description: 'sampledescription'),
    CategoryModel(
        id: 3, name: 'Beauty', imageUrl: '', description: 'sampledescription'),
    CategoryModel(
        id: 4, name: 'Shoes', imageUrl: '', description: 'sampledescription'),
    CategoryModel(
        id: 5,
        name: 'Furnitures',
        imageUrl: '',
        description: 'sampledescription'),
    CategoryModel(
        id: 6, name: 'Grocery', imageUrl: '', description: 'sampledescription'),
    ];
    }
    

    Thank you, for your time.