Как изменить цвет виджета, когда он нажат во флаттере? - PullRequest
1 голос
/ 29 мая 2020

У меня есть виджет, и я хочу изменить цвет его фона, пока пользователь нажимает на него, и когда нажатие завершается, он возвращается к своему исходному цвету.

Я пытался использовать GestureDetector, реализация функций onTapDown и onTapUp , но это не работает: для изменения цвета требуется много времени (~ 150 мс), и, если я нажимаю на нормальной скорости, цвет не t change.

Я разработчик Android, и то, что я хочу сделать, делается в Android с помощью следующего селектора:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="..." android:state_pressed="true" />
  <item android:drawable="..." />
</selector>.

Но я не знаю как это сделать с флаттером. Надеюсь, этот фрагмент кода поможет понять, чего я хочу достичь.

Ответы [ 2 ]

0 голосов
/ 29 мая 2020

Вот как бы я это сделал:


class MyWidget extends StatefulWidget {

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

class _MyWidgetState extends State<MyWidget> with SingleTickerProviderStateMixin {

  AnimationController _controller;
  Color myColor = Colors.blue;

  @override
  void initState() {
    _controller = AnimationController(vsync: this,duration: Duration(milliseconds: 400));
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapUp: (_) {
        setState(() {     
        myColor = Colors.blue;
        });
      },
      onTapDown: (_) {
        setState(() {
        myColor = Colors.red;
        });
      },
       child: AnimatedBuilder(animation: _controller,
       builder: (context, child) => Container(
         height: 200,
         width: 200,
         color : myColor,
       )),
    );
  }
}

Вы можете изменить продолжительность в animationController, если она слишком медленная.

0 голосов
/ 29 мая 2020

вы делали это правильно, используя GestureDetector, но вы использовали неправильные методы, вы использовали onLongPressStart и onLongPressEnd, как в примере ниже:

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _changeColor = false;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: GestureDetector(
        onLongPressStart: (_) => setState(() => _changeColor = !_changeColor),
        onLongPressEnd: (_) => setState(() => _changeColor = !_changeColor),
        child: Container(
          color: _changeColor ? Colors.red : Colors.yellow,
          child: Text('Change color'),
        ),
      ),
    );
  }
}

другой способ сделать это с помощью класса MaterialStateColor, предложенного @ pskink

class MyApp extends StatelessWidget {
  Color getTextColor(Set<MaterialState> states) {
    const Set<MaterialState> interactiveStates = <MaterialState>{
      MaterialState.pressed,
      MaterialState.hovered,
      MaterialState.focused,
    };
    if (states.any(interactiveStates.contains)) {
// the color to return when button is in pressed, hovered, focused state
      return Colors.red;
    }
// the color to return when button is in it's normal/unfocused state 
    return Colors.yellow;
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: FlatButton(
        child: Text('FlatButton'),
        onPressed: () {},
        textColor: MaterialStateColor.resolveWith(getTextColor),
      ),
    );
  }
}
...