flutter_sticky_headers icon indicating copy to clipboard operation
flutter_sticky_headers copied to clipboard

[BUG] Jumpy header inside CustomScrollView with center key

Open Areopagitics opened this issue 1 year ago • 9 comments

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),
        ],
      );
  }
}

Areopagitics avatar Oct 22 '22 20:10 Areopagitics

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 avatar Dec 25 '22 21:12 JAicewizard

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.

JAicewizard avatar Jan 26 '23 12:01 JAicewizard

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.

justincbeck avatar May 11 '23 15:05 justincbeck

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

JAicewizard avatar May 12 '23 13:05 JAicewizard

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.

Areopagitics avatar Jul 02 '23 01:07 Areopagitics

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?

JAicewizard avatar Jul 02 '23 14:07 JAicewizard

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.

Areopagitics avatar Jul 03 '23 17:07 Areopagitics

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

JAicewizard avatar Jul 03 '23 17:07 JAicewizard

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

JAicewizard avatar May 09 '24 12:05 JAicewizard