Skip to content

Instantly share code, notes, and snippets.

@ianldgs
Last active September 8, 2020 03:41
Show Gist options
  • Save ianldgs/794884d8837b83fd9c64e06d9b90af4e to your computer and use it in GitHub Desktop.
Save ianldgs/794884d8837b83fd9c64e06d9b90af4e to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'My Flutter Pad'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
const kExpandedHeight = 300.0;
class _MyHomePageState extends State<MyHomePage> {
ScrollController _scrollController;
@override
void initState() {
super.initState();
_scrollController = ScrollController()
..addListener(() => setState(() {}));
}
bool get _showTitle {
return _scrollController.hasClients
&& _scrollController.offset > kExpandedHeight - kToolbarHeight;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverAppBar(
pinned: true,
leading: IconButton(icon: Icon(Icons.menu), onPressed: () {},),
expandedHeight: kExpandedHeight,
title: _showTitle ? Text('_SliverAppBar') : null,
flexibleSpace: _showTitle ? null : FlexibleSpaceBar(
title: new Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text('_SliverAppBar'),
Text('subtitle'),
],
),
background: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Info'),
],
),
),
),
SliverList(
delegate: SliverChildListDelegate(List<Text>.generate(100, (int i) {
return Text("List item $i");
})),
),
]
),
);
}
}
@fattiger00
Copy link

fattiger00 commented Oct 5, 2019

Excellent demo. but using ..addListener(() => setState(() {})); Does do like this will have bad effect on performance?
Making _showTitle as a property, adding a condition to call setState method, will it be better?
like this The way I thought

@ianldgs
Copy link
Author

ianldgs commented Oct 7, 2019

Not sure about performance (would have to be measured), but it's definitely not recommended by the community to call an empty setState.
I've extracted this piece of code from a widget of mine a long time ago, so I could have a reference whenever I needed. However, the widget in question was also doing a parallax and I was just getting started with flutter.
Your example is really better and I recommend anyone with a use case like this to use it.

@zgramming
Copy link

zgramming commented Oct 13, 2019

I already try this,Anyway nice demo.
But i have some question, Why everytime i scrolled my listview always refresh. I assume this script make my listview always refresh every scrolled. And make my app very slow.

_scrollController = ScrollController()
      ..addListener(() => setState(() {}));
  }
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_news/api/Api_news.dart';
import 'package:flutter_news/pages/display_json/FetchNewsByWartawan.dart';
import 'package:flutter_news/pages/reusableWidget/DataNotFound.dart';
import 'package:flutter_news/pages/reusableWidget/LoadingIndicator.dart';

import 'package:flutter_screenutil/flutter_screenutil.dart';

class WartawanDetail extends StatefulWidget {
  final int idWartawan;
  final String gambarWartawan;
  final String namaWartawan;
  final int jumlahBerita;
  WartawanDetail({
    this.idWartawan,
    this.gambarWartawan,
    this.namaWartawan,
    this.jumlahBerita,
  });
  @override
  _WartawanDetailState createState() => _WartawanDetailState();
}

class _WartawanDetailState extends State<WartawanDetail> {
  ScrollController _scrollController;
  ApiHelper api = ApiHelper();
  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController()
      ..addListener(() => setState(() {
            print("${_scrollController.offset}");
          }));
  }

  bool get _changeColor {
    return _scrollController.hasClients &&
        _scrollController.offset > (250 - kToolbarHeight);
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      top: true,
      child: Scaffold(
        body: CustomScrollView(
          controller: _scrollController,
          slivers: <Widget>[
            SliverAppBar(
              floating: false,
              pinned: true,
              expandedHeight: ScreenUtil.getInstance().setHeight(250),
              leading: Container(
                child: IconButton(
                  icon: Icon(
                    Icons.arrow_back,
                    color: _changeColor ? Colors.blue : Colors.black,
                  ),
                  onPressed: () => Navigator.pop(context),
                ),
              ),
              flexibleSpace: FlexibleSpaceBar(
                title: Container(
                  child: Text(widget.namaWartawan),
                ),
                background: Container(
                  child: CachedNetworkImage(
                    fit: BoxFit.cover,
                    imageUrl:
                        "${Urls.BASE_API_IMAGE}/wartawan/${widget.gambarWartawan}",
                  ),
                ),
              ),
              actions: <Widget>[
                IconButton(
                  icon: Icon(Icons.more_horiz),
                  onPressed: () => "",
                ),
              ],
            ),
            SliverFixedExtentList(
              itemExtent: MediaQuery.of(context).size.height,
              delegate: SliverChildListDelegate(
                [
                  Container(
                    padding: EdgeInsets.all(8),
                    child: FutureBuilder(
                      future: api.getBeritaByWartawan(widget.idWartawan),
                      builder: (BuildContext context, AsyncSnapshot snapshot) {
                        switch (snapshot.connectionState) {
                          case ConnectionState.waiting:
                          case ConnectionState.active:
                            return LoadingIndicator();
                            break;
                          default:
                            if (!snapshot.hasData) {
                              return DataNotFound();
                            } else {
                              return ListView.builder(
                                shrinkWrap: true,
                                physics: NeverScrollableScrollPhysics(),
                                itemCount: snapshot.data.length,
                                itemBuilder: (BuildContext context, int index) {
                                  return FetchNewsByWartawan(
                                    idBerita: snapshot.data[index].idBerita,
                                    judulBerita:
                                        snapshot.data[index].judulBerita,
                                    isiBerita: snapshot.data[index].isiBerita,
                                    namaKategori:
                                        snapshot.data[index].namaKategori,
                                    namaWartawan:
                                        snapshot.data[index].namaWartawan,
                                    tanggalBerita:
                                        snapshot.data[index].tanggalBerita,
                                    gambarBerita:
                                        snapshot.data[index].gambarBerita,
                                  );
                                },
                              );
                            }
                        }
                      },
                    ),
                  ),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

@ianldgs
Copy link
Author

ianldgs commented Oct 14, 2019

@zgramming you will maybe have better luck following @fattiger00's gist. Your widget just needs to rebuild when the colour will in fact change. Maybe putting the scroll logic and list logic in separate widgets would be wise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment