fluttercommunity / flutter_sticky_headers

Flutter Sticky Headers - Lets you place "sticky headers" into any scrollable content in your Flutter app. No special wrappers or magic required. Maintainer: @slightfoot
https://pub.dev/packages/sticky_headers
MIT License
1.07k stars 130 forks source link

[BUG] Jumpy header inside CustomScrollView with center key #67

Open Areopagitics opened 1 year ago

Areopagitics commented 1 year ago

When using StickyHeader inside a CustomScrollView with center key, the header immediately before the center header month jumps around; all the other header months have no problems. A plug and play ready example is found below. If there is an easy way to fix the problem, it would be much appreciated. I have tried countless other options...I am really surprised the sticky header is not included with the flutter CustomScrollView widgets.

Peek 2022-10-22 13-18

import 'package:flutter/material.dart';
import 'package:sticky_headers/sticky_headers.dart';

Map _months = {
  1:'January',
  2:'February',
  3:'March',
  4:'April',
  5:'May',
  6:'June',
  7:'July',
  8:'August',
  9:'September',
  10:'October',
  11:'November',
  12:'December',
};

abstract class BasePage extends StatefulWidget {
  BasePage({Key? key}) : super(key: key);
}

abstract class BaseState<Page extends BasePage> extends State<Page> {
  String screenName();
}
class CalendarPage extends BasePage {
  CalendarPage({Key? key}) : super(key: key);
  @override
  _CalendarPageState createState() => _CalendarPageState();
}

class _CalendarPageState extends BaseState<CalendarPage>{
  _CalendarPageState();

  Key centerKey = ValueKey<String>('center');
  var date = DateTime.now();

 Widget monthBuilder (BuildContext context, int plusMinus){
    int count = (date.month - 13) * -1;
    if(plusMinus==-1){count=date.month-1;}
    return SliverList(
      key: plusMinus==1 ? centerKey:null,
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          int month=date.month+index;
          if(plusMinus==-1){month=date.month-1+(-1*index);}
          return StickyHeader(
            header: Container(
              color: Colors.brown,
              padding: EdgeInsets.symmetric(vertical: 12.0),
              alignment: Alignment.center,
              child: Text('${_months[month]}',
                style: Theme.of(context).textTheme.headline2,
              ),
            ),
            content: ListView.builder(
              shrinkWrap: true,
              itemCount: DateTime(date.year,month+1,0).day,//check last day of month for days,
              itemBuilder: (context, int index) {
                return Column(children: [
                  Divider(),
                  TextButton( onPressed: () {  },
                  child: Text('Data'),),
                ]);
              },
            ),
          );
        },
        childCount: count,
      )
    );
  }

  @override
  String screenName() => "Calendar ${date.year}";

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
        center: centerKey,
        slivers: [
          monthBuilder(context, -1),
          monthBuilder(context, 1),
        ],
      );
  }
}
JAicewizard commented 1 year ago

Yes this also happens for me, but only for a the first bit of the child, and gets fixed after one whole screen has been scrolled.

JAicewizard commented 1 year ago

The way this library works is very hacky, the only work around is to calculate the header position during paint as done in the PR above. A better solution would be using flutter_sticky_header, except that the sticky headers above the center key are at the bottom instead of top.

justincbeck commented 1 year ago

I'm seeing a related issue where if I add an item to the list or scroll view that the header can jump down the list (by the amount the list size has increased) until a scroll is initiated, upon which it resets correctly. It's an edge case to be sure but can look bad to end users.

JAicewizard commented 1 year ago

Can you checkout if my fork (#72) fixes that issue?

Areopagitics commented 1 year ago

Can you checkout if my fork (#72) fixes that issue?

Since the fork was merged, it unfortunately doesn't. I just tested with the code above. The same problem happens.

JAicewizard commented 1 year ago

WDYM? The code in the issue should be fixed in my fork, as I use that fork for a production app where it works. It is also not merged yet. How are you importing the code?

Areopagitics commented 1 year ago

My bad ... I thought it was merged already.

BTW. I'm already looking to SliverMainAxisGroup, which will provide Sticky Headers out of the box in flutter.

JAicewizard commented 1 year ago

This shoudl probably stay open, but thanks for pointing that out! Then we can also finally move away from this library

JAicewizard commented 4 months ago

@Areopagitics I tried to work with SliverMainAxisGroup, but I am confident it doesn't workin in reverse scroll direction. Could you reopen this?