Skip to content

Luy7788/flutter_switch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 

Repository files navigation

flutter_Switch

一个滑动开关UI 效果预览 image-w100

点击右滑动动画,同时下面的PageView页面也跟着画的 image

分析下结构,首先最底下有个灰色的背景,上面有个白色的选中框,最上面是两个Text,然后当点击到空白灰色时,控制白色的选中框移动,而且需要添加一个动画过渡效果。

首先创建一个SwitchButton widget,继承StatefulWidget,方便更新自身状态

class SwitchButton extends StatefulWidget {
  double width = 120;
  double height = 40;
  List<String> tabs;//两个选项
  PageController controller;
  Color unSelectColor; //未选中底色
  Color selectColor; //白色选中框
  int currentIndex; //当前在哪个选项

  SwitchButton({
    Key key,
    this.width,
    this.height,
    this.controller,
    @required this.tabs,
    this.unSelectColor,
    this.selectColor,
    this.currentIndex,
  }) : super(key: key);

  @override
  _SwitchButtonState createState() {
    return _SwitchButtonState();
  }
}

SwitchButtonState中的主要几个点:

  double centerPoint; //中心点
  Duration _duration = Duration(milliseconds: 100); //动画时长

  @override
  void initState() {
    super.initState();
    this.centerPoint = widget.width / 2;//计算中心点
  }

  //切换选项的方法
  changePage(int currentIndex) {
    widget.currentIndex = currentIndex;
    if (widget.controller != null) {
      //控制外层pageview跟着滑动
      widget.controller.animateToPage(
        currentIndex,
        duration: _duration,
        curve: Curves.ease,
      );
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        backgroundWidget(),
        switchWidget(),
      ],
    );
  }

  backgroundWidget() {
    //添加点击,用来点击滑动对应位置
    return GestureDetector(
      child: Container(
        width: widget.width,
        height: widget.height,
        decoration: BoxDecoration(
          //设置底色和圆角
          color: widget.unSelectColor ?? Colors.grey[200],
          borderRadius: BorderRadius.circular(widget.height / 2),
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Text(
              widget.tabs[0] ?? "",
            ),
            Text(
              widget.tabs[1] ?? "",
            ),
          ],
        ),
      ),
      onTap: () {
        //点击事件
        int currentIndex;
        if (widget.currentIndex == 0) {
          currentIndex = 1;
        } else {
          currentIndex = 0;
        }
        //切换选项
        changePage(currentIndex);
      },
    );
  }

 //白色开关控件
  switchWidget() {
    //添加位置的动画
    return AnimatedPositioned(
      //这里根据选中选项,判断左侧的边距
      left: widget.currentIndex == 0 ? 0 : this.centerPoint - _padding,
      duration: _duration,
      child: GestureDetector(
        //添加滑动手势
        onHorizontalDragUpdate: (DragUpdateDetails value) {
          _dragDistance = value.localPosition.dx;
        },
        onHorizontalDragEnd: (DragEndDetails value) {
          //判断滑动手势结束时应该让白色按键往哪滑动
          if (_dragDistance < -10) {
            changePage(0);
          } else if (_dragDistance > 10) {
            changePage(1);
          }
          _dragDistance = 0;
        },
        child: Container(
          width: centerPoint - _padding,
          height: widget.height - _padding * 2,
          decoration: BoxDecoration(
            color: widget.selectColor ?? Colors.white,
            borderRadius: BorderRadius.circular(
              (widget.height - _padding * 2) / 2,
            ),
          ),
          margin: EdgeInsets.all(_padding),
          child: Center(
            child: Text(
              widget.tabs[widget.currentIndex] ?? "",
            ),
          ),
        ),
      ),
    );
  }

具体实现可看demo

About

一个滑动开关UI

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published