Skip to content

Why all views in header are not transparent? #171

Description

@Madina-S

_buildTabBar() container background is not transparent, and even cannot assign different colors. But _buildCalendarHeader() is transparent. TabBar background can be changed, but cannot apply transparency, why?


import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:talim_pro/core/base/base_page.dart';
import 'package:talim_pro/core/constants.dart';
import 'package:talim_pro/core/theme/app_colors.dart';
import 'package:talim_pro/core/theme/app_text_styles.dart';
import 'package:talim_pro/dashboard/widgets/custom_paged_calendar.dart';

import 'dashboard_cubit.dart';
import 'dashboard_state.dart';

class DashboardPage2
    extends BasePage<DashboardCubit, DashboardBuildable, DashboardListenable> {
  DashboardPage2({super.key});

  final _segments = const ['Process', 'Calendar'];
  final ScrollController outerScrollController = ScrollController();

  @override
  void init(BuildContext context) {
    context.read<DashboardCubit>().getProcesses();
  }

  @override
  void dispose() {
    outerScrollController.dispose();
    super.dispose();
  }

  @override
  Widget builder(BuildContext context, DashboardBuildable state) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final cellWidth = MediaQuery.of(context).size.width / 7;
    final dayDesiredHeight = 64.h;
    final statusBarHeight = MediaQuery.of(context).padding.top;

    return DefaultTabController(
      length: _segments.length,
      initialIndex: state.currentIndex,
      child: NotificationListener(
        onNotification: (notification) {
          // if (notification is ScrollEndNotification) _snapToNearest();
          return false;
        },
        child: ExtendedNestedScrollView(
          controller: outerScrollController,
          onlyOneScrollInBody: true,
          pinnedHeaderSliverHeightBuilder: () {
            final commonHeight = statusBarHeight + tabBarHeight;
            return state.currentIndex == 0
                ? commonHeight
                : commonHeight + calendarHeaderHeight;
          },
          headerSliverBuilder: (context, innerBoxIsScrolled) {
            return [
              SliverPersistentHeader(
                pinned: true,
                floating: false,
                delegate: _UnifiedHeaderDelegate(
                  statusBarHeight: statusBarHeight,
                  greetingExtraHeight: greetingAppBarHeight,
                  tabBarHeight: tabBarHeight,
                  calendarHeaderHeight: calendarHeaderHeight,
                  currentIndex: state.currentIndex,
                  segments: _segments,
                  onTabSelected: (index) {
                    context.read<DashboardCubit>().changeSegment(index);
                    DefaultTabController.of(context).animateTo(index);
                  },
                  month: state.currentDate,
                ),
              ),
            ];
          },
          body: Builder(
            builder: (context) {
              final tabController = DefaultTabController.of(context);

              return TabBarView(
                controller: tabController,
                physics: const NeverScrollableScrollPhysics(),
                children: [
                  _buildProcessList(context, state),
                  _buildCustomPageCalendar(
                    context,
                    isDark,
                    cellWidth / dayDesiredHeight,
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }

  Widget _buildProcessList(BuildContext context, DashboardBuildable state) {
    final items = state.feedItems;
    return CustomScrollView(
      slivers: [
        SliverPadding(
          padding: EdgeInsets.fromLTRB(16.w, 0, 16.w, 102.h),
          sliver: SliverList(
            delegate: SliverChildBuilderDelegate((context, index) {
              return Text('$index');
            }, childCount: items.length),
          ),
        ),
      ],
    );
  }

  Widget _buildCustomPageCalendar(
    BuildContext context,
    bool isDark,
    double dayAspectRatio,
  ) {
    return CustomPagedCalendar();
  }
}

class _UnifiedHeaderDelegate extends SliverPersistentHeaderDelegate {
  final double statusBarHeight;
  final double greetingExtraHeight;
  final double tabBarHeight;
  final double calendarHeaderHeight;
  final int currentIndex;
  final List<String> segments;
  final Function(int) onTabSelected;
  final String month;

  _UnifiedHeaderDelegate({
    required this.statusBarHeight,
    required this.greetingExtraHeight,
    required this.tabBarHeight,
    required this.calendarHeaderHeight,
    required this.currentIndex,
    required this.segments,
    required this.onTabSelected,
    required this.month,
  });

  @override
  double get minExtent =>
      statusBarHeight +
      tabBarHeight +
      (currentIndex == 1 ? calendarHeaderHeight : 0);

  @override
  double get maxExtent => minExtent + greetingExtraHeight;

  @override
  Widget build(
    BuildContext context,
    double shrinkOffset,
    bool overlapsContent,
  ) {
    final double t = (shrinkOffset / greetingExtraHeight).clamp(0.0, 1.0);
    final double opacity = (1.0 - t).clamp(0.0, 1.0);
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final bgColor = Theme.of(context).scaffoldBackgroundColor;

    return Container(
      color: Colors.transparent,
      child: ClipRect(
        child: Stack(
          children: [
            if (t > 0 && currentIndex == 0)
              Positioned(
                top: 0,
                left: 0,
                right: 0,
                height: statusBarHeight + topShaderHeight,
                child: IgnorePointer(
                  child: DecoratedBox(
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        begin: Alignment.topCenter,
                        end: Alignment.bottomCenter,
                        colors: [bgColor, bgColor.withValues(alpha: 0)],
                      ),
                    ),
                  ),
                ),
              ),

            Column(
              children: [
                SizedBox(
                  height: max(
                    statusBarHeight,
                    statusBarHeight + greetingExtraHeight - shrinkOffset,
                  ),
                  child: _buildGreeting(context, opacity, shrinkOffset),
                ),
                _buildTabBar(context),
                if (currentIndex == 1) _buildCalendarHeader(context, isDark),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildGreeting(
    BuildContext context,
    double opacity,
    double shrinkOffset,
  ) {
    return Stack(
      children: [
        Positioned(
          top: statusBarHeight - shrinkOffset,
          left: 0,
          right: 0,
          child: Opacity(
            opacity: opacity,
            child: SizedBox(
              height: greetingExtraHeight,
              child: Stack(
                children: [
                  Positioned(
                    left: 16.w,
                    top: 16.h,
                    child: CircleAvatar(
                      radius: 22.r,
                      backgroundColor: Colors.grey,
                    ),
                  ),
                  Positioned(
                    top: 16.h,
                    left: 70.w,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [Text('Hello'), Text("Mr/Ms")],
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildTabBar(BuildContext context) {
    return Container(
      color: Colors.black.withValues(alpha: 0.2),
      height: tabBarHeight,
      child: Padding(
        padding: EdgeInsets.all(16.w),
        child: TabBar(
          onTap: onTabSelected,
          tabs: [
            Tab(text: 'Tab1'),
            Tab(text: 'Tab2'),
          ],
        ),
      ),
    );
  }

  Widget _buildCalendarHeader(BuildContext context, bool isDark) {
    return Container(
      color: Colors.red,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Padding(
            padding: EdgeInsets.fromLTRB(16.w, 12.h, 16.w, 6.h),
            child: Text(
              month,
              style: AppTextStyles.calendarCurrentMonthLabel.copyWith(
                color: AppColors.calendarCurrentMonthLabel(isDark),
              ),
            ),
          ),
          SizedBox(height: 22.h),
          Container(
            height: 1.h,
            color: AppColors.calendarWeekdayContainerBorder(isDark),
          ),
        ],
      ),
    );
  }

  @override
  bool shouldRebuild(covariant _UnifiedHeaderDelegate oldDelegate) {
    return oldDelegate.currentIndex != currentIndex ||
        oldDelegate.month != month ||
        oldDelegate.statusBarHeight != statusBarHeight ||
        oldDelegate.greetingExtraHeight != greetingExtraHeight ||
        oldDelegate.tabBarHeight != tabBarHeight ||
        oldDelegate.calendarHeaderHeight != calendarHeaderHeight;
  }
}```

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions