Skip to content

Instantly share code, notes, and snippets.

@paurakhsharma
Last active September 3, 2021 07:12

Revisions

  1. paurakhsharma revised this gist Sep 2, 2021. 1 changed file with 13 additions and 13 deletions.
    26 changes: 13 additions & 13 deletions Flutter Dynamic Header.dart
    Original file line number Diff line number Diff line change
    @@ -1,15 +1,15 @@
    import 'package:flutter/material.dart';

    void main() async {
    runApp(DynamicHeader());
    runApp(const DynamicHeader());
    }

    class DynamicHeader extends StatelessWidget {
    const DynamicHeader({Key? key}) : super(key: key);

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    return const MaterialApp(
    home: HomePage(),
    );
    }
    @@ -28,12 +28,12 @@ class _HomePageState extends State<HomePage> {
    late final ScrollController _controller;
    bool _isScrollAreaCollapsed = false;

    static const HEADER_HEIGHT = 110.0;
    static const Expanded_Color = Color(0xff5379FF);
    static const Collapsed_Color = Color(0xff51C2FE);
    static const titleHeight = 110.0;
    static const expandedColor = Color(0xff5379FF);
    static const collapsedColor = Color(0xff51C2FE);

    final descText = 'This is another dynamic text text tt tt t end';
    final descTextStyle = TextStyle(
    static const descTextStyle = TextStyle(
    color: Colors.white,
    fontSize: 20,
    );
    @@ -45,7 +45,7 @@ class _HomePageState extends State<HomePage> {
    slivers: [
    SliverAppBar(
    backgroundColor:
    _isScrollAreaCollapsed ? Collapsed_Color : Expanded_Color,
    _isScrollAreaCollapsed ? collapsedColor : expandedColor,
    pinned: true,
    title: Column(
    children: [
    @@ -54,7 +54,7 @@ class _HomePageState extends State<HomePage> {
    children: [
    Text(
    _isScrollAreaCollapsed ? 'Wrapped' : 'Hello',
    style: TextStyle(
    style: const TextStyle(
    fontSize: 34,
    fontWeight: FontWeight.bold,
    ),
    @@ -77,14 +77,14 @@ class _HomePageState extends State<HomePage> {
    ),
    collapsedHeight: 60,
    expandedHeight: descTextHeight,
    bottom: HeaderBottom(),
    bottom: const HeaderBottom(),
    flexibleSpace: FlexibleSpaceBar(
    background: Padding(
    padding: const EdgeInsets.symmetric(horizontal: 16.0),
    child: Column(
    children: [
    Container(
    height: HEADER_HEIGHT,
    height: titleHeight,
    ),
    Text(
    descText,
    @@ -122,7 +122,7 @@ class _HomePageState extends State<HomePage> {
    final height = textPainter.size.height;
    final screenWidth = MediaQuery.of(context).size.width;
    final numberofLines = (width / (screenWidth - padding)).ceil();
    return numberofLines * height + HEADER_HEIGHT + 16;
    return numberofLines * height + titleHeight + 16;
    }

    void _scrollListner() {
    @@ -156,9 +156,9 @@ class _HomePageState extends State<HomePage> {
    }

    class HeaderBottom extends StatelessWidget implements PreferredSizeWidget {
    HeaderBottom({
    const HeaderBottom({
    Key? key,
    }) : preferredSize = Size.fromHeight(50.0),
    }) : preferredSize = const Size.fromHeight(50.0),
    super(key: key);

    @override
  2. paurakhsharma created this gist Sep 2, 2021.
    191 changes: 191 additions & 0 deletions Flutter Dynamic Header.dart
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,191 @@
    import 'package:flutter/material.dart';

    void main() async {
    runApp(DynamicHeader());
    }

    class DynamicHeader extends StatelessWidget {
    const DynamicHeader({Key? key}) : super(key: key);

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    home: HomePage(),
    );
    }
    }

    class HomePage extends StatefulWidget {
    const HomePage({
    Key? key,
    }) : super(key: key);

    @override
    _HomePageState createState() => _HomePageState();
    }

    class _HomePageState extends State<HomePage> {
    late final ScrollController _controller;
    bool _isScrollAreaCollapsed = false;

    static const HEADER_HEIGHT = 110.0;
    static const Expanded_Color = Color(0xff5379FF);
    static const Collapsed_Color = Color(0xff51C2FE);

    final descText = 'This is another dynamic text text tt tt t end';
    final descTextStyle = TextStyle(
    color: Colors.white,
    fontSize: 20,
    );
    @override
    Widget build(BuildContext context) {
    return Scaffold(
    body: CustomScrollView(
    controller: _controller,
    slivers: [
    SliverAppBar(
    backgroundColor:
    _isScrollAreaCollapsed ? Collapsed_Color : Expanded_Color,
    pinned: true,
    title: Column(
    children: [
    Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: [
    Text(
    _isScrollAreaCollapsed ? 'Wrapped' : 'Hello',
    style: TextStyle(
    fontSize: 34,
    fontWeight: FontWeight.bold,
    ),
    ),
    SizedBox(
    height: 100,
    child: IconButton(
    onPressed: () {},
    icon: Icon(
    _isScrollAreaCollapsed
    ? Icons.expand_less
    : Icons.expand_more,
    size: 40,
    ),
    ),
    )
    ],
    )
    ],
    ),
    collapsedHeight: 60,
    expandedHeight: descTextHeight,
    bottom: HeaderBottom(),
    flexibleSpace: FlexibleSpaceBar(
    background: Padding(
    padding: const EdgeInsets.symmetric(horizontal: 16.0),
    child: Column(
    children: [
    Container(
    height: HEADER_HEIGHT,
    ),
    Text(
    descText,
    style: descTextStyle,
    ),
    ],
    ),
    ),
    ),
    ),
    SliverList(
    delegate: SliverChildListDelegate(
    List.generate(
    20,
    (index) => ListTile(
    title: Text('Item $index'),
    ),
    ),
    ),
    )
    ],
    ),
    );
    }

    double get descTextHeight {
    const padding = 32;
    final textPainter = TextPainter(
    text: TextSpan(text: descText, style: descTextStyle),
    textScaleFactor: MediaQuery.of(context).textScaleFactor,
    maxLines: 1,
    textDirection: TextDirection.ltr,
    )..layout();
    final width = textPainter.size.width;
    final height = textPainter.size.height;
    final screenWidth = MediaQuery.of(context).size.width;
    final numberofLines = (width / (screenWidth - padding)).ceil();
    return numberofLines * height + HEADER_HEIGHT + 16;
    }

    void _scrollListner() {
    if (_controller.offset > (descTextHeight - 130)) {
    if (_isScrollAreaCollapsed) return;
    setState(() {
    _isScrollAreaCollapsed = true;
    });
    } else {
    if (!_isScrollAreaCollapsed) return;
    setState(() {
    _isScrollAreaCollapsed = false;
    });
    }
    }

    @override
    void initState() {
    super.initState();
    _controller = ScrollController();

    _controller.addListener(_scrollListner);
    }

    @override
    void dispose() {
    _controller.removeListener(_scrollListner);
    _controller.dispose();
    super.dispose();
    }
    }

    class HeaderBottom extends StatelessWidget implements PreferredSizeWidget {
    HeaderBottom({
    Key? key,
    }) : preferredSize = Size.fromHeight(50.0),
    super(key: key);

    @override
    final Size preferredSize;

    @override
    Widget build(BuildContext context) {
    return Container(
    padding: const EdgeInsets.symmetric(horizontal: 16),
    color: Colors.black.withOpacity(0.2),
    height: 50,
    child: ListView.separated(
    separatorBuilder: (context, index) => const SizedBox(width: 8),
    itemCount: 20,
    scrollDirection: Axis.horizontal,
    itemBuilder: (context, index) {
    return Tab(
    child: Text(
    'Tab ${index + 1}',
    style: TextStyle(
    color:
    index == 0 ? Colors.white : Colors.white.withOpacity(0.6),
    ),
    ),
    );
    },
    ),
    );
    }
    }