颤振 ||滚动回到顶部按钮

Flutter || Scroll back to top button

在我的 flutter 项目中,我做了一个浮动按钮,可以帮助您一键自动滚动到页面顶部,当它到达顶部时,它会消失。它完美地工作。但我的问题是我需要双击它才能消失我希望它在到达顶部时自动消失。非常感谢任何帮助。

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

这是我的解决方案。

  1. 注册 'window.onscroll' 以将 webview 的滚动位置发送到 Webview 小部件之外。
  2. 注册接收器以从 webview 接收事件。
  3. 如果滚动为 0,更改 'buttonshow' 值并重建小部件。

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

我将按钮显示触发器从 gestureRecognizers 更改为 position 事件。

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