Как мне программно имитировать onTap на кнопке в Flutter?

#flutter #gesturedetector

#flutter #gesturedetector

Вопрос:

Например:

 // Update: This GestureDetector is embedded inside a third party package
// that will invoke a series of animation along with the onTap button
GestureDetector(
   onTap: () => print('Hey There!'),
   child: Widget1(),
)


// Then another place in the same screen
GestureDetector(
    onDoubleTap: () { 
           //Call the onTap of Widget1's GestureDetector
           print('I'm Here');
        }
    child: Widget2(),
)
  

Я хотел, чтобы при двойном нажатии пользователя Widget2 он также вызывал onTap обратный вызов Widget1 .

Обновление: итак, я не хочу просто вызывать функцию, переданную в onTap из GestureDetector Widget1 , а скорее программно нажимать на onTap из Widget1 GestureDetector

Как мне это сделать?

Ответ №1:

Вы можете сделать что-то вроде этого —

Создайте свой детектор жестов —

    GestureDetector gestureDetector = GestureDetector(
      onTap: () {
        setState(() {
          _lights = !_lights;
        });
      },
      child: Container(
        color: Colors.yellow.shade600,
        padding: const EdgeInsets.all(8),
        child: const Text('TURN LIGHTS ON'),
      ),
    );
  

Создайте кнопку (или любой виджет, который вы хотели бы использовать) для вызова onTap в GestureDetector gestureDetector.onTap() точно так же, как вы вызываете метод в другом виджете. (Здесь я использую FlatButton )-

           FlatButton(
            color: Colors.blue,
            textColor: Colors.white,
            disabledColor: Colors.grey,
            disabledTextColor: Colors.black,
            padding: EdgeInsets.all(8.0),
            onPressed: () {
              //Trigger the GestureDetector onTap event.
              gestureDetector.onTap();
            },
            child: Text("Click Here"),
          ),
  

Теперь вы можете нажать на FlatButton, чтобы вызвать onTap событие в GestureDetector.

Вот полный пример —

 import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Gesture Detector On Tap'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  bool _lights = false;

  @override
  Widget build(BuildContext context) {
    GestureDetector gestureDetector = GestureDetector(
      onTap: () {
        setState(() {
          _lights = !_lights;
        });
      },
      child: Container(
        color: Colors.yellow.shade600,
        padding: const EdgeInsets.all(8),
        child: const Text('TURN LIGHTS ON'),
      ),
    );

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Container(
          alignment: FractionalOffset.center,
          color: Colors.white,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Icon(
                  Icons.lightbulb_outline,
                  color: _lights ? Colors.yellow.shade600 : Colors.black,
                  size: 60,
                ),
              ),
              gestureDetector,
              SizedBox(height: 50.0),
              FlatButton(
                color: Colors.blue,
                textColor: Colors.white,
                disabledColor: Colors.grey,
                disabledTextColor: Colors.black,
                padding: EdgeInsets.all(8.0),
                onPressed: () {
                  gestureDetector.onTap();
                },
                child: Text("Click Here"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
  

Вы получите что-то вроде этого —

введите описание изображения здесь

Ответ №2:

Обновление: итак, я не хочу просто вызывать функцию, переданную в onTap GestureDetector Widget1, а скорее программно использовать onTap GestureDetector Widget1

Цель onTap — вызвать функцию обратного вызова внутри onTap. Итак, я не уверен, почему вы просто хотите нажать на кнопку, кроме вызова функций, которые должны вызываться при нажатии на эту кнопку (можете ли вы подробнее рассказать об этом?).

Если вы хотите имитировать нажатие для тестирования, вы можете сделать это с помощью драйвера Flutter, используя driver.tap()

Ответ №3:

После нескольких неудачных запусков это то, что сработало для меня. Я использую Riverpod, а formFocusIdProvider в этом примере кода является простым stateProvider.

Я на самом деле не понимаю, зачем мне нужно было добавлять задержку, но без этого поведение было непредсказуемым при перерисовке виджета.

Этот код находится в методе сборки.

 ref.listen(formFocusIdProvider, (previous, next) {
  if (<some condition>) {
    Future.delayed(const Duration(milliseconds: 200), () {
      if (mounted) {
        onTapFunction();
      }
    });
  }
});
  

Ответ №4:

просто создайте первую функцию отдельно

 void firstFunction(){
print('hey There!');
}
  

вот так, затем вызовите его во втором виджете
итак, ваш код будет выглядеть следующим образом:

 GestureDetector(
   onTap: () => firstFunction(),
   child: Widget1(),
)
// Then another place in the same screen
GestureDetector(
onDoubleTap: () { 
   firstFunction();
   print('I'm Here');
}
child: Widget2(),
)
  

Комментарии:

1. Спасибо за ответ. Но то, что я ищу, — это не просто вызвать переданную ему функцию. Это потому, что GestureDetector фактически встроен в другой внешний пакет, и когда пользователь нажимает на него, он запускает серию анимации вместе с ним. Итак, я хочу иметь возможность имитировать onTap вместо простого вызова переданной ему функции. Позвольте мне обновить вопрос, чтобы лучше объяснить это