Flutter 实现的简单滑块认证

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter 实现的简单滑块认证相关的知识,希望对你有一定的参考价值。

参考技术A import 'package:flutter/material.dart';

class SliderBlockVerify extends StatefulWidget
/// 滑块右边颜色
final Color positiveColor;
/// 滑块左边颜色
final Color negativeColor;
/// 显示内容
final String text;
/// 控件总体宽度
final double width;
/// 控件总体高度
final double height;
/// 滑块显示的图片
final ImageProvider image;
/// 滑块的宽度
final double imageWidth;
/// 完成的回调
final GestureTapCallback finishCallBack;

SliderBlockVerify(
@required this.image,
@required this.finishCallBack,
this.positiveColor = Colors.green,
this.negativeColor = Colors.grey,
this.text = "滑到右边以确认",
this.width = 250,
this.height = 44,
this.imageWidth = 60,
) : assert(image != null),
assert(finishCallBack != null);

@override
_SliderBlockVerifyState createState() => _SliderBlockVerifyState();


class _SliderBlockVerifyState extends State<SliderBlockVerify>
// double percentage = 0;
double initial = 0.0;
double distance = 0.0;

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


@override
Widget build(BuildContext context)
return Container(
width: widget.width,
height: widget.height,
child: GestureDetector(
onPanStart: _onPanStart,
onPanUpdate: _onPanUpdate,
onPanEnd: _onPanEnd,
child: Stack(
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
_positive,
_negative,
],
),
_text,
_icon,
],
),
),
);


Widget get _positive
return Offstage(
offstage: distance==0?true:false,
child: Container(
height: widget.height,
width: distance,
color: widget.positiveColor,
),
);


Widget get _negative
return Offstage(
offstage: distance==(widget.width - widget.imageWidth)?true:false,
child:Container(
height: widget.height,
width: widget.width - distance,
color: widget.negativeColor
),
);


Widget get _text
return Positioned(
child: Container(
alignment: Alignment.center,
width: widget.width,
height:widget.height,
child: Text(
widget.text
),
),
);


Widget get _icon
return Positioned(
child: Container(
margin: _iconEdgeInsets,
width: widget.imageWidth,
child: Image(
image: widget.image,
width: widget.imageWidth,
height: widget.height,
fit: BoxFit.fitWidth,
alignment: Alignment.center,
),
),
);


EdgeInsets get _iconEdgeInsets
double left = 0;
if(distance > widget.width - widget.imageWidth)
left = widget.width - widget.imageWidth;
else
left = distance;

return EdgeInsets.only(left: left);


_onPanStart(DragStartDetails details)
initial = details.globalPosition.dx;


_onPanUpdate(DragUpdateDetails details)
distance = details.globalPosition.dx - initial;
distance = distance.clamp(0.0, widget.width - widget.imageWidth);
setState(()

);


_onPanEnd(DragEndDetails details)
initial = 0.0;
if(distance >= widget.width - widget.imageWidth -30)
distance = widget.width - widget.imageWidth;
if(widget.finishCallBack != null)
widget.finishCallBack();

else
distance = 0.0;

setState(()

);

Flutter 堆叠 GestureDetector 和滑块问题

【中文标题】Flutter 堆叠 GestureDetector 和滑块问题【英文标题】:Flutter stacked GestureDetector and slider problem 【发布时间】:2022-01-22 04:41:06 【问题描述】:

我有一个带有 GestureDetector 的堆栈,用于将图标转换为按钮和围绕它的圆形滑块。

Stack(
 alignment: Alignment.center,
 children: <Widget>[
  BulbSlider(),
  Positioned(
   top: 25,
   child: GestureDetector(
    onTap: () 
     debugPrint('pressed');
     Vibrate.feedback(FeedbackType.selection);
    ,
    child: Icon(
     Icons.play_circle_fill_rounded,
     color: kOrange,
     size: 250,
    ),
   ),
  ),
 ],
),

screenshot

这是截图。 我的问题是,如果我尝试拖动手柄,则无法使用滑块,但如果单击滑块的轨道,它会起作用。如果我在滑块和按钮之间单击(所以在图标之外),GestureDetectoris 触发的按钮也存在问题。

我也尝试反转这两个小部件,因此我将滑块放在 GestureDetector 顶部,但在这种情况下,滑块效果很好,但 GestureDetector 未检测到任何点击。

代码如下:

Stack(
 alignment: Alignment.center,
 children: <Widget>[
  Positioned(
   top: 25,
   child: GestureDetector(
    onTap: () 
     debugPrint('pressed');
     Vibrate.feedback(FeedbackType.selection);
    ,
    child: Icon(
     Icons.play_circle_fill_rounded,
     color: kOrange,
     size: 250,
    ),
   ),
  ),
  BulbSlider(),
 ],
),

如果它可以帮助我把滑块的代码放在这里:

import 'package:flutter/material.dart';
import 'package:sleek_circular_slider/sleek_circular_slider.dart';
import '/const/colors.dart';

class BulbSlider extends StatefulWidget 
  const BulbSlider(Key? key) : super(key: key);
  @override
  _State createState() => _State();


class _State extends State<BulbSlider> 
  double? myValue;
  String valore = '';
  @override
  void initState() 
    super.initState();
    myValue = 0;
    valore = '1';
  

  otherMethod(String rounded) 
    debugPrint("rounded: " + rounded);
    valore = rounded;
  

  @override
  Widget build(BuildContext context) 
    final slider = SleekCircularSlider(
      min: 1,
      max: 360,
      initialValue: 1,
      appearance: CircularSliderAppearance(
        size: 300,
        startAngle: 140,
        angleRange: 260,
        animationEnabled: true,
        customColors: CustomSliderColors(
          hideShadow: true,
          trackColor: kCards,
          dotColor: kWhite,
          progressBarColor: kOrange,
        ),
        customWidths: CustomSliderWidths(
          shadowWidth: 30,
          trackWidth: 8,
          progressBarWidth: 8,
          handlerSize: 10,
        ),
        infoProperties: InfoProperties(
          mainLabelStyle: TextStyle(
              color: kWhite, fontSize: 20, fontWeight: FontWeight.w700),
          //topLabelStyle:
          //    TextStyle(color: kWhite, fontSize: 20, fontWeight: FontWeight.w700),
          //topLabelText: 'Seconds',
          modifier: (double value) 
            final sec = (value.toInt()) / 100;

            return ''; // '$sec s';
          ,
        ),
      ),
      onChange: (double weight) 
        setState(() 
          String newValue = weight.ceil().toInt().toString();
          debugPrint(newValue);
          otherMethod(newValue);
        );
      ,
    );
    return Container(
      child: Column(
        children: <Widget>[
          Center(child: slider),
          Text(valore),
        ],
      ),
    );
  


你知道如何解决吗? 谢谢

【问题讨论】:

【参考方案1】:

您可以如下裁剪手势检测的有效区域:

Material(
  // You can check the effective area of inkwell
  // color: Colors.deepOrangeAccent,
  borderRadius: BorderRadius.circular(250 / 2),
  child: InkWell(
    onTap: () ,
    borderRadius: BorderRadius.circular(250 / 2),
    child: const Icon(Icons.play_circle_fill_rounded,
      color: kOrange,
      size: 250,
    ),
  ),
)

在你的情况下,

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

const kCards  = Colors.red;
const kOrange = Colors.orange;
const kWhite  = Colors.white;

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


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

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  


class MyHomePage extends StatefulWidget 
  const MyHomePage(Key? key, required this.title) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Stack(
        alignment: Alignment.center,
        children: <Widget>[
          const BulbSlider(),
          Positioned(
            top: 25,
            child: Material(
              // You can check the effective area of the inkwell
              // color: kOrange,
              borderRadius: BorderRadius.circular(250 / 2),
              child: InkWell(
                onTap: () 
                  print('Hello there!');
                ,
                borderRadius: BorderRadius.circular(250 / 2),
                child: const Icon(
                  Icons.play_circle_fill_rounded,
                  color: kOrange,
                  size: 250,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  


class BulbSlider extends StatefulWidget 
  const BulbSlider(Key? key) : super(key: key);
  @override
  _State createState() => _State();


class _State extends State<BulbSlider> 
  double? myValue;
  String valore = '';
  @override
  void initState() 
    super.initState();
    myValue = 0;
    valore = '1';
  

  otherMethod(String rounded) 
    debugPrint("rounded: " + rounded);
    valore = rounded;
  

  @override
  Widget build(BuildContext context) 
    final slider = SleekCircularSlider(
      min: 1,
      max: 360,
      initialValue: 1,
      appearance: CircularSliderAppearance(
        size: 300,
        startAngle: 140,
        angleRange: 260,
        animationEnabled: true,
        customColors: CustomSliderColors(
          hideShadow: true,
          trackColor: kCards,
          dotColor: kWhite,
          progressBarColor: kOrange,
        ),
        customWidths: CustomSliderWidths(
          shadowWidth: 30,
          trackWidth: 8,
          progressBarWidth: 8,
          handlerSize: 10,
        ),
        infoProperties: InfoProperties(
          mainLabelStyle: const TextStyle(
              color: kWhite, fontSize: 20, fontWeight: FontWeight.w700),
          //topLabelStyle:
          //    TextStyle(color: kWhite, fontSize: 20, fontWeight: FontWeight.w700),
          //topLabelText: 'Seconds',
          modifier: (double value) 
            // final sec = (value.toInt()) / 100;
            return ''; // '$sec s';
          ,
        ),
      ),
      onChange: (double weight) 
        setState(() 
          String newValue = weight.ceil().toInt().toString();
          debugPrint(newValue);
          otherMethod(newValue);
        );
      ,
    );
    return Column(
      children: <Widget>[
        Center(child: slider),
        Text(valore),
      ],
    );
  

来源 - FlutterBeads。

【讨论】:

感谢您的回复,它可以工作,但现在我有一个无法删除的大白色区域(仅在深色背景下可见)。这是截图imgur.com/gallery/LP2f2ac你知道吗? 您可以取消注释颜色并将其更改为 Colors.transparent 吗?很抱歉给您带来不便 另外,这指出您的材质原色是白色(默认)。我认为你应该使用 MaterialApp 的主题来管理你的颜色。这样,您的主题将在小部件之间保持一致,并为您节省一些手动颜色设置。您可以查看here。

以上是关于Flutter 实现的简单滑块认证的主要内容,如果未能解决你的问题,请参考以下文章

Flutter-分段滑块

Flutter - 范围滑块

FLUTTER 如何实现 Digest 认证

Flutter 堆叠 GestureDetector 和滑块问题

从 Stream (Flutter) 控制轮播滑块

Flutter ー Authentication 认证