void _onViewDragDown(DragDownDetails callback) {…}

void _onViewDrag(DragUpdateDetails callback) {…}

void _onViewDragUp(DragEndDetails callback) {…}
}

初始化状态initState()

这个方法是在Widget初始化的时候系统的回调函数,我们需要在该函数中初始化动画

AnimationController controller;
@override
void initState() {
// 初始化动画控制器,这里限定动画时常为200毫秒
controller = new AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
// vsync对象会绑定动画的定时器到一个可视的widget,所以当widget不显示时,动画定时器将会暂停,当widget再次显示时,动画定时器重新恢复执行,这样就可以避免动画相关UI不在当前屏幕时消耗资源。
// 当使用vsync: this的时候,State对象必须with SingleTickerProviderStateMixin或TickerProviderStateMixin;TickerProviderStateMixin适用于多AnimationController的情况。

// 设置动画曲线,就是动画插值器
// 通过这个链接可以了解更多差值器,https://docs.flutter.io/flutter/animation/Curves-class.html,我们这里使用带回弹效果的bounceOut。
CurvedAnimation curve =
new CurvedAnimation(parent: controller, curve: Curves.bounceOut);

// 增加动画监听,当手势结束的时候通过动态计算到达目标位置的距离实现动画效果。curve.value为当前动画的值,取值范围0~1。
curve.addListener(() {
double animValue = curve.value;
double offset = dragUpDownX - dragDownX;
double toPosition;

// 右滑
if (offset > 0) {
if (offset > maxDragX / 5) {
// 打开
toPosition = maxDragX;
isOpenState = true;
} else {
if (isOpenState) {
toPosition = maxDragX;
isOpenState = true;
} else {
toPosition = 0.0;
isOpenState = false;
}
}
} else {
if (offset < (-maxDragX / 2.0)) {
// 关
toPosition = 0.0;
isOpenState = false;
} else {
if (isOpenState) {
toPosition = maxDragX;
isOpenState = true;
} else {
toPosition = 0.0;
isOpenState = false;
}
}
}

dragOffset = (toPosition - dragUpDownX) * animValue + dragUpDownX;
// 刷新位置
setState(() {});
});
}

结束Widget dispose()

当Widget不可用将被回收的时候,系统会回调dispose()方法,我们在这里回收动画。

@override
void dispose() {
controller.dispose();
}

记录按下的位置

double dragDownX = 0.0;
void _onViewDragDown(DragDownDetails callback) {
dragDownX = callback.globalPosition.dx;
}

拖动的时候刷新View的位置

/**

  • 最大可拖动位置
    */
    final double maxDragX = 230.0;
    double dragOffset = 0.0;
    void _onViewDrag(DragUpdateDetails callback) {
    double tmpOffset = callback.globalPosition.dx - dragDownX;

if (tmpOffset < 0) {
tmpOffset += maxDragX;
}

// 边缘检测
if (tmpOffset < 0) {
tmpOffset = 0.0;
} else if (tmpOffset >= maxDragX) {
tmpOffset = maxDragX;
}

// 刷新
if (dragOffset != tmpOffset) {
dragOffset = tmpOffset;
setState(() {});
}
}

离手的时候记录位置并执行动画

/**

  • 脱手时候的位置
    */
    double dragUpDownX = 0.0;
    void _onViewDragUp(DragEndDetails callback) {
    dragUpDownX = dragOffset;
    // 执行动画,每次都从第0帧开始执行
    controller.forward(from: 0.0);
    }

支持移动的Widget

@override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(dragOffset, 0.0),
child: Container(
child: GestureDetector(
onHorizontalDragDown: _onViewDragDown,
onVerticalDragDown: _onViewDragDown,
onHorizontalDragUpdate: _onViewDrag,
onVerticalDragUpdate: _onViewDrag,
onHorizontalDragEnd: _onViewDragUp,
onVerticalDragEnd: _onViewDragUp,
child: Container(

最后

其实要轻松掌握很简单,要点就两个:

  1. 找到一套好的视频资料,紧跟大牛梳理好的知识框架进行学习。
  2. 多练。 (视频优势是互动感强,容易集中注意力)

你不需要是天才,也不需要具备强悍的天赋,只要做到这两点,短期内成功的概率是非常高的。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

阿里P7Android高级教程

下面资料部分截图,诚意满满:特别适合有3-5年开发经验的Android程序员们学习。

附送高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、近期面试跳槽、自身职业规划迷茫的朋友们。

Android核心高级技术PDF资料,BAT大厂面试真题解析;

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
高级技术PDF资料,BAT大厂面试真题解析;**
[外链图片转存中…(img-NsFHVzSF-1715356241215)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐