Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter || Scroll back to top button

In my flutter project I made a floating button that help to auto scroll to the top of the page with one click, and when it reach the top it disappear. It work perfectly. But my problem is that I need to double click in it so it can disappear I want it to automatically disappear if it reach the top. Any help is highly appreciated.

     void scrollToTop(){
    _controller.runJavascript("window.scrollTo({top: 0, behavior: 'smooth'});");
    floatingButtonVisibility();
  }

  void floatingButtonVisibility() async {
    int y = await  _controller.getScrollY();
    if(y>50){
      setState(() {
        buttonshow = true;
      });
    }else {
      setState(() {
        buttonshow = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body:  WebView(
          initialUrl: 'https://flutter.dev',
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: (WebViewController webViewController) {
            _controller = webViewController;
          },
          gestureRecognizers: Set()
            ..add(
                Factory<VerticalDragGestureRecognizer>(() => VerticalDragGestureRecognizer()
                  ..onDown = (tap) {
                    floatingButtonVisibility();
                  }))

      ),
      floatingActionButton: Visibility(
        visible: buttonshow,
        child: FloatingActionButton(
          onPressed: () {
            scrollToTop();
          },
          backgroundColor: Colors.blue,
          child: const Icon(Icons.navigation),
        ),
      ),
    );
  }
}
like image 824
soukaina Avatar asked Nov 15 '25 09:11

soukaina


1 Answers

Here is my solution.

  1. Register 'window.onscroll' in to send webview's scroll position to outside of Webview widget.
  2. Register receiver to receive event from webview.
  3. If scroll is 0, change 'buttonshow' value and rebuild widget.

enter image description here

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  WebViewController _controller;
  bool buttonshow = false;

  @override
  void initState() {
    super.initState();
  }

  void scrollToTop() {
    _controller.evaluateJavascript(
        "window.onscroll = function () {scrollEventChannel.postMessage(window.scrollY)};");
    _controller
        .evaluateJavascript("window.scrollTo({top: 0, behavior: 'smooth'});");
    floatingButtonVisibility();
  }

  void floatingButtonVisibility() async {
    int y = await _controller.getScrollY();
    if (y > 50) {
      setState(() {
        buttonshow = true;
      });
    } else {
      setState(() {
        buttonshow = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebView(
          initialUrl: 'https://flutter.dev',
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: (WebViewController webViewController) {
            _controller = webViewController;
          },
          javascriptChannels: {
            JavascriptChannel(
                name: 'scrollEventChannel',
                onMessageReceived: (JavascriptMessage message) {
                  print('>>>>: ${message.message}');
                  if (message.message == '0') {
                    setState(() {
                      buttonshow = false;
                    });
                  }
                }),
          },
          gestureRecognizers: Set()
            ..add(Factory<VerticalDragGestureRecognizer>(
                () => VerticalDragGestureRecognizer()
                  ..onDown = (tap) {
                    floatingButtonVisibility();
                  }))),
      floatingActionButton: Visibility(
        visible: buttonshow,
        child: FloatingActionButton(
          onPressed: () {
            scrollToTop();
          },
          backgroundColor: Colors.blue,
          child: const Icon(Icons.navigation),
        ),
      ),
    );
  }
}

I changed button show trigger from gestureRecognizers to postion event.

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  WebViewController _controller;
  bool buttonshow = false;

  @override
  void initState() {
    super.initState();
  }

  void scrollToTop() {
    _controller
        .evaluateJavascript("window.scrollTo({top: 0, behavior: 'smooth'});");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebView(
        initialUrl: 'https://flutter.dev',
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (WebViewController webViewController) {
          _controller = webViewController;
        },
        onPageFinished: (String url) async {
          _controller.evaluateJavascript(
              "window.onscroll = function () {scrollEventChannel.postMessage(window.scrollY)};");
        },
        javascriptChannels: {
          JavascriptChannel(
              name: 'scrollEventChannel',
              onMessageReceived: (JavascriptMessage message) {
                print('>>>>: ${message.message}');

                int position = int.parse(message.message);
                if (position == 0) {
                  setState(() {
                    buttonshow = false;
                  });
                } else if (position > 60) {
                  setState(() {
                    buttonshow = true;
                  });
                }
              }),
        },
      ),
      floatingActionButton: Visibility(
        visible: buttonshow,
        child: FloatingActionButton(
          onPressed: () {
            scrollToTop();
          },
          backgroundColor: Colors.blue,
          child: const Icon(Icons.navigation),
        ),
      ),
    );
  }
}
like image 78
KuKu Avatar answered Nov 17 '25 08:11

KuKu