Home > OS >  How to be able to add a scrollbar to a website using flutter?
How to be able to add a scrollbar to a website using flutter?

Time:08-03

This is my flutter website:

enter image description here

I want to add a scrollbar on my website like this for example:

enter image description here

this is my code:

import 'dart:core';
import 'dart:ui';
import 'package:braintrinig/animation/LongBreak.dart';
import 'package:braintrinig/animation/ShortBreak.dart';
import 'package:braintrinig/animation/StartPomodoro.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_nav_bar/google_nav_bar.dart';
import 'package:interval_ticker_provider/interval_ticker_provider.dart';
import 'dart:async';

import 'package:responsive_sizer/responsive_sizer.dart';

class HomePageTimerUI extends StatefulWidget  {

  const HomePageTimerUI({Key? key}) : super(key: key);

  @override
  State<HomePageTimerUI> createState() => _HomePageTimerUIState();
}

class _HomePageTimerUIState extends State<HomePageTimerUI>  with TickerProviderStateMixin {
  late TabController _tabController;

  late Timer timer;
  late AnimationController controller;

  String get countText {
    Duration count = controller.duration! * controller.value;
    return controller.isDismissed
        ? '${controller.duration!.inHours.toString().padLeft(2, '0')}:${(controller.duration!.inMinutes % 60).toString().padLeft(2, '0')}:${(controller.duration!.inSeconds % 60).toString().padLeft(2, '0')}'
        : '${count.inHours.toString().padLeft(2, '0')}:${(count.inMinutes % 60).toString().padLeft(2, '0')}:${(count.inSeconds % 60).toString().padLeft(2, '0')}';
  }


  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 3, vsync: this);
  }


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

  void notify() {
    if (countText == '00:00:00') {
    _tabController.animateTo(1, duration: const Duration(milliseconds: 300));
  }
}

  @override
  Widget build (BuildContext context) {
     return Container(
                height: 600,
                width: double.infinity,
                child: DefaultTabController(
                    length: 3,
                    child: Scaffold(
                      appBar: AppBar(
                        elevation: 0,
                        backgroundColor: Colors.transparent,
                        bottom: PreferredSize(
                          preferredSize: Size.fromHeight(55),
                          child: Container(
                            color: Colors.transparent,
                            child: SafeArea(
                              child: Column(
                                children: <Widget>[
                                  TabBar(
                                      controller: _tabController,
                                      indicator: UnderlineTabIndicator(
                                          borderSide: BorderSide(
                                              color: Color(0xff3B3B3B), width: 4.0),
                                          insets: EdgeInsets.fromLTRB(
                                              12.0, 12.0, 12.0, 11.0)),
                                      indicatorWeight: 15,
                                      indicatorSize: TabBarIndicatorSize.label,
                                      labelColor: Color(0xff3B3B3B),
                                      labelStyle: TextStyle(
                                          fontSize: 12,
                                          letterSpacing: 1.3,
                                          fontWeight: FontWeight.w500),
                                      unselectedLabelColor: Color(0xffD7D7D7),
                                      tabs: [
                                        Tab(
                                          text: "POMODORO",
                                          icon: Icon(Icons.work_history, size: 40),
                                        ),
                                        Tab(
                                          text: "SHORT BREAK",
                                          icon: Icon(Icons.ramen_dining, size: 40),
                                        ),
                                        Tab(
                                          text: "LONG BREAK",
                                          icon: Icon(
                                              Icons.battery_charging_full_rounded,
                                              size: 40),
                                        ),
                                      ])
                                ],
                              ),
                            ),
                          ),
                        ),
                      ),
                      body: TabBarView(
                        controller: _tabController,
                        children: <Widget>[
                          Center(
                            child: StartPomodoro(),
                          ),
                          Center(
                            child: ShortBreak(),
                          ),
                          Center(child: LongBreak()),
                        ],
                      ),
                      bottomNavigationBar: Container(
                        height: 110,
                        color: Color(0xffFAFAFA),
                        child: Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20),
                          child: GNav(
                            iconSize: 40,
                            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                            backgroundColor: Color(0xffFAFAFA),
                            color: Color(0xffD7D7D7),
                            activeColor: Color(0xff3B3B3B),
                            tabBackgroundColor: Color(0xffF0F0F0),
                            gap: 8,
                            onTabChange: (index) {
                              print(index);
                            },
                            padding: EdgeInsets.all(15),
                            tabs: [
                              GButton(
                                icon: Icons.settings,
                                text: 'Settings',),
                              GButton(
                                icon: Icons.person,
                                text: "Profile",),
                              GButton(
                                icon: Icons.task,
                                text: "Tasks",),
                              GButton(
                                icon: Icons.show_chart,
                                text: "Performance",
                              ),
                            ],
                          ),
                        ),
                      ),)));
  }
}

pomodoro.dart

import 'dart:async';
import 'package:braintrinig/animation/home_page_timer_ui.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:core';
import 'dart:math' as math;
import 'package:flutter_ringtone_player/flutter_ringtone_player.dart';
import 'package:responsive_sizer/responsive_sizer.dart';

import 'ShortBreak.dart';

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

  @override
  State<StartPomodoro> createState() => _StartPomodoroState();
}

class _StartPomodoroState extends State<StartPomodoro>
    with TickerProviderStateMixin {
  List<bool> isSelected = [true, false];
  late Timer timer;
  late AnimationController controller;

  String get countText {
    Duration count = controller.duration! * controller.value;
    return controller.isDismissed
        ? '${controller.duration!.inHours.toString().padLeft(2, '0')}:${(controller.duration!.inMinutes % 60).toString().padLeft(2, '0')}:${(controller.duration!.inSeconds % 60).toString().padLeft(2, '0')}'
        : '${count.inHours.toString().padLeft(2, '0')}:${(count.inMinutes % 60).toString().padLeft(2, '0')}:${(count.inSeconds % 60).toString().padLeft(2, '0')}';
  }

  double progress = 1.0;
  bool LongBreak = true;

  void notify() {
    if (countText == '00:00:00') {}
  }

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 0),
    );
    controller.addListener(() {
      notify();
      if (controller.isAnimating) {
        setState(() {
          progress = controller.value;
        });
      } else {
        setState(() {
          progress = 1.0;
          LongBreak = true;
        });
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    ThemeData themeData = Theme.of(context);
    return ResponsiveSizer(builder: (context, orientation, screenType) {
      return Device.screenType == ScreenType.mobile
          ? Scaffold(
              backgroundColor:
                  LongBreak ? Color(0xffD94530) : Color(0xff6351c5),
              body: GestureDetector(
                onTap: () {
                  if (controller.isDismissed) {
                    showModalBottomSheet(
                      context: context,
                      builder: (context) => Container(
                        height: 300,
                        child: CupertinoTimerPicker(
                          initialTimerDuration: controller.duration!,
                          onTimerDurationChanged: (time) {
                            setState(() {
                              controller.duration = time;
                            });
                          },
                        ),
                      ),
                    );
                  }
                },
                child: AnimatedBuilder(
                    animation: controller,
                    builder: (context, child) {
                      return Stack(
                        children: <Widget>[
                          Align(
                            alignment: Alignment.bottomCenter,
                            child: Container(
                              color: Color(0xffD94530),
                              height: controller.value *
                                  MediaQuery.of(context).size.height *
                                  0.715,
                            ),
                          ),
                          Padding(
                            padding: EdgeInsets.all(8.0),
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: <Widget>[
                                Expanded(
                                  child: Align(
                                    alignment: Alignment.bottomCenter,
                                    child: Align(
                                      alignment: FractionalOffset.bottomCenter,
                                      child: SingleChildScrollView(
                                        child: Column(
                                          mainAxisAlignment:
                                              MainAxisAlignment.end,
                                          crossAxisAlignment:
                                              CrossAxisAlignment.center,
                                          children: <Widget>[
                                            Text(
                                              countText,
                                              style: TextStyle(
                                                fontSize: 90.0,
                                                color: Color(0xffFAFAFA),
                                              ),
                                            ),
                                          ],
                                        ),
                                      ),
                                    ),
                                  ),
                                ),
                                Expanded(
                                  child: Row(
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    crossAxisAlignment:
                                        CrossAxisAlignment.center,
                                    children: [
                                      AnimatedBuilder(
                                          animation: controller,
                                          builder: (context, child) {
                                            return Padding(
                                              padding: EdgeInsets.symmetric(
                                                  vertical: 2.0,
                                                  horizontal: 15.0),
                                            );
                                          }),
                                      AnimatedBuilder(
                                          animation: controller,
                                          builder: (context, child) {
                                            return Padding(
                                              padding: EdgeInsets.symmetric(
                                                  vertical: 2.0,
                                                  horizontal: 15.0),
                                              child:
                                                  FloatingActionButton.extended(
                                                      backgroundColor:
                                                          Color(0xffFAFAFA),
                                                      onPressed: () {
                                                        if (controller
                                                            .isAnimating) {
                                                          controller.stop();
                                                          setState(() {
                                                            LongBreak = false;
                                                          });
                                                        } else {
                                                          controller.reverse(
                                                              from: controller
                                                                          .value ==
                                                                      0
                                                                  ? 1.0
                                                                  : controller
                                                                      .value);
                                                          setState(() {
                                                            LongBreak = false;
                                                          });
                                                        }
                                                      },
                                                      icon: Icon(
                                                        controller.isAnimating
                                                            ? Icons.pause
                                                            : Icons.play_arrow,
                                                        color:
                                                            Color(0xff3B3B3B),
                                                      ),
                                                      label: Text(
                                                        controller.isAnimating
                                                            ? "Pause"
                                                            : "Pomoworko",
                                                        style: TextStyle(
                                                            color: Color(
                                                                0xff3B3B3B)),
                                                      )),
                                            );
                                          }),
                                      SizedBox(width: 20, height: 100),
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ],
                      );
                    }),
              ),
            )
          : Scaffold(
              backgroundColor:
                  LongBreak ? Color(0xffD94530) : Color(0xff6351c5),
              body: GestureDetector(
                onTap: () {
                  if (controller.isDismissed) {
                    showModalBottomSheet(
                      context: context,
                      builder: (context) => Container(
                        height: 300,
                        child: CupertinoTimerPicker(
                          initialTimerDuration: controller.duration!,
                          onTimerDurationChanged: (time) {
                            setState(() {
                              controller.duration = time;
                            });
                          },
                        ),
                      ),
                    );
                  }
                },
                child: AnimatedBuilder(
                    animation: controller,
                    builder: (context, child) {
                      return Stack(
                        children: <Widget>[
                          Align(
                            alignment: Alignment.bottomCenter,
                            child: Container(
                              color: Color(0xffD94530),
                              height: controller.value *
                                  MediaQuery.of(context).size.height *
                                  0.615,
                            ),
                          ),
                          Padding(
                            padding: EdgeInsets.all(8.0),
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: <Widget>[
                                Expanded(
                                  child: Align(
                                    alignment: Alignment.bottomCenter,
                                    child: Align(
                                      alignment: FractionalOffset.bottomCenter,
                                      child: SingleChildScrollView(
                                        child: Column(
                                          mainAxisAlignment:
                                              MainAxisAlignment.end,
                                          crossAxisAlignment:
                                              CrossAxisAlignment.center,
                                          children: <Widget>[
                                            Text(
                                              countText,
                                              style: TextStyle(
                                                fontSize: 90.0,
                                                color: Color(0xffFAFAFA),
                                              ),
                                            ),
                                          ],
                                        ),
                                      ),
                                    ),
                                  ),
                                ),
                                Expanded(
                                  child: Row(
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    crossAxisAlignment:
                                        CrossAxisAlignment.center,
                                    children: [
                                      AnimatedBuilder(
                                          animation: controller,
                                          builder: (context, child) {
                                            return Padding(
                                              padding: EdgeInsets.symmetric(
                                                  vertical: 2.0,
                                                  horizontal: 15.0),
                                            );
                                          }),
                                      AnimatedBuilder(
                                          animation: controller,
                                          builder: (context, child) {
                                            return Padding(
                                              padding: EdgeInsets.symmetric(
                                                  vertical: 2.0,
                                                  horizontal: 15.0),
                                              child:
                                                  FloatingActionButton.extended(
                                                      backgroundColor:
                                                          Color(0xffFAFAFA),
                                                      onPressed: () {
                                                        if (controller
                                                            .isAnimating) {
                                                          controller.stop();
                                                          setState(() {
                                                            LongBreak = false;
                                                          });
                                                        } else {
                                                          controller.reverse(
                                                              from: controller
                                                                          .value ==
                                                                      0
                                                                  ? 1.0
                                                                  : controller
                                                                      .value);
                                                          setState(() {
                                                            LongBreak = false;
                                                          });
                                                        }
                                                      },
                                                      icon: Icon(
                                                        controller.isAnimating
                                                            ? Icons.pause
                                                            : Icons.play_arrow,
                                                        color:
                                                            Color(0xff3B3B3B),
                                                      ),
                                                      label: Text(
                                                        controller.isAnimating
                                                            ? "Pause"
                                                            : "Pomoworko",
                                                        style: TextStyle(
                                                            color: Color(
                                                                0xff3B3B3B)),
                                                      )),
                                            );
                                          }),
                                      SizedBox(width: 20, height: 100),
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ],
                      );
                    }),
              ),
            );
    });
  }
}

class CustomTimerPainter extends CustomPainter {
  CustomTimerPainter({
    required this.animation,
    required this.backgroundColor,
    required this.color,
  }) : super(repaint: animation);

  final Animation<double> animation;
  final Color backgroundColor, color;

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = backgroundColor
      ..strokeWidth = 10.0
      ..strokeCap = StrokeCap.butt
      ..style = PaintingStyle.stroke;

    canvas.drawCircle(size.center(Offset.zero), size.width / 2.0, paint);
    paint.color = color;
    double progress = (1.0 - animation.value) * 2 * math.pi;
    canvas.drawArc(Offset.zero & size, math.pi * 1.5, -progress, false, paint);
  }

  @override
  bool shouldRepaint(CustomTimerPainter old) {
    return animation.value != old.animation.value ||
        color != old.color ||
        backgroundColor != old.backgroundColor;
  }
}

How to achieve the scrollbar?

I tried to implement Responsive Sizer, mostly to align the animation to the top bar and I thought that it could be a great idea to separate mobile and website, but it doesn't work

Device.screenType == ScreenType.mobile
  ? Scaffold
  : Scaffold (web)

(that's what I thinked in the beginning, but it don't make any changes on my website changing MediaQuery.of(context).size.height * 0.715, to MediaQuery.of(context).size.height * 0.615, (its because the animation has certain lag when the timer starts))

How to be able to align the animation when timer starts to mobile and website and don't have any type of lag in the website side?

Thank you in advance if you can help in these two questions

CodePudding user response:

Have you tried the Scrollbar view widget for implementing the Scrollbar?

It goes like this:

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

void main() => runApp(const MyApp());

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

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: const MyStatelessWidget(),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scrollbar(
      child: GridView.builder(
        itemCount: 120,
        gridDelegate:
            const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
        itemBuilder: (BuildContext context, int index) {
          return Center(
            child: Text('item $index'),
          );
        },
      ),
    );
  }
}

Make sure that you have a fixed height widget in the Scrollbar, or there maybe chances for errors like the pixel overflow

CodePudding user response:

Wrap the content of the body of scaffold with a scrollbar widget

Scrollbar(
 thicknesses: 10,
 child: GestureDetector()
)
  • Related