当前位置: 首页 > news >正文

【Android】View 的滑动

【Android】View 的滑动

在Android中,View的滑动是用户交互中的常见操作。实现View滑动的方法有很多,这里主要介绍6种滑动方法。

1. layout()方法

View 进行绘制的时候会调用 onLayout()方法来设置显示的位置,因此我们可以通过修改的 View 的left、top、right、bottom 这4种属性来控制View的坐标。

public class CustomView extends View {private int lastX;private int lastY;public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public CustomView(Context context, AttributeSet attrs) {super(context, attrs);}public CustomView(Context context) {super(context);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 记录按下位置lastX = x;lastY = y;break;case MotionEvent.ACTION_MOVE:// 计算移动距离int offsetX = x - lastX;int offsetY = y - lastY;// 更新视图位置layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);break;}return true;}
}

2. offsetLeftAndRight()与offsetTopAndBottom()

这两种方法和 layout() 方法的效果差不多,使用方法也差不多。将 ACTION_MOVE 中的代码替换成如下代码:

case MotionEvent.ACTION_MOVE:// 计算移动距离	int offsetX = x - lastX;int offsetY = y - lastY;// 对 left 和 right 进行偏移offsetLeftAndRight(offsetX);// 对 top 和 bottom 进行偏移offsetTopAndBottom(offsetY);break;

3. LayoutParams(改变布局参数)

LayoutParams 主要保存了一个 View 的布局参数,因此我们可以通过 LayoutParams 来改变 View 的布局参数从而达到改变 View 位置的效果。同样,我们将 ACTION_MOVE 中的代码替换成如下代码:

int offsetX = x - lastX;
int offsetY = y - lastY;
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft() + offsetX;
layoutParams.topMargin = getTop() + offsetY;
setLayoutParams(layoutParams);

因为父控件是 LinearLayout,所以这里使用了 LinearLayout.LayoutParams。如果父控件是 RelativeLayout,则要使用 RelativeLayout.LayoutParams。除了使用布局的 LayoutParams 之外,还可以用 ViewGroup.MarginLayoutParams 来实现:

int offsetX = x - lastX;
int offsetY = y - lastY;
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft() + offsetX;
layoutParams.topMargin = getTop() + offsetY;
setLayoutParams(layoutParams);

4. 动画

可以采用 View 动画来移动,在 res 目录新建 anim 文件夹并创建 translate.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"android:fillAfter="true"><translateandroid:duration="1000"android:fromXDelta="0"android:toXDelta="500"/>
</set>

这是一个持续 1 秒的平移动画,使控件向右移动 500px 并停留在终点位置。

然后在 Java 代码中调用:

customView.setAnimation(AnimationUtils.loadAnimation(this, R.anim.translate));

效果如下:

需要注意的是,View 动画并不能改变 View 的位置参数。如果对一个 Button 进行如上的平移滑动操作,当 Button 平移 500 像素停留在当前位置时,我们点击这个 Button 并不会触发点击事件,但在我们点击这个 Button 的原始位置时却触发了点击事件。对于系统来说这个 Button 没有改变原来的位置,所以点击其他位置当然不会触发它的点击事件。

**TranslateAnimation **只改变了 绘制时的位置,不会真正修改 View 的 布局坐标(layout 参数没变)。所以动画结束后,再去获取这个 View 的 getLeft()getTop() 之类的坐标,值还是原来的。

而属性动画则解决了上述问题,因为它不仅可以执行动画,还能够改变 View 的位置参数。使用示例:

ObjectAnimator.ofFloat(customView, "translationX", 0, 500).setDuration(1000).start();

5. ScrollTo 和 scrollBy

scrollTo(x, y) 表示移动到一个具体的坐标点,而 scrollBy(dx, dy) 则表示移动的增量为 dx、dy。源码如下:

public void scrollTo(int x, int y) {if (mScrollX != x || mScrollY != y) {int oldX = mScrollX;int oldY = mScrollY;mScrollX = x;mScrollY = y;invalidateParentCaches();onScrollChanged(mScrollX, mScrollY, oldX, oldY);if (!awakenScrollBars()) {postInvalidateOnAnimation();}}
}public void scrollBy(int x, int y) {scrollTo(mScrollX + x, mScrollY + y);
}

可以看到,scrollBy 移动的时 View 的内容,如果在 ViewGroup 中使用,则是移动其所有的子 View。将ACTION_MOVE 中的代码修改如下:

((View)getParent()).scrollBy(-offsetX, -offsetY);

6. Scroller

在使用 scrollTo/scrollBy 方法进行滑动时,这个过程是瞬间完成的,所以用户体验不太好。这里可以使用 Scroller 来实现有过渡效果的滑动,这个过程不是瞬间完成的,而是在一定的时间间隔完成的。Scroller 本身是不能实现 View 的滑动的,他需要与 View 的 computeScroll() 方法配合才能实现弹性滑动的效果。这里我们实现 CustomView 平滑地向右移动。首先我们要初始化 Scroller,代码如下所示:

public CustomView(Context context, AttributeSet attrs) {super(context, attrs);mScroller = new Scroller(context);
}

接下来重写 computeScroll() 方法,系统会在绘制 View 的时候在 draw() 方法中调用该方法。在这个方法中,我们调用父类的 scrollTo() 方法并通过 Scroller 来不断获取当前的滚动值,每滑动一小段距离我们就调用 invalidate() 方法不断地进行重绘,重绘就会调用 computeScroll() 方法,这样通过不断地移动一个小的距离并连贯起来就实现了平滑移动的效果。

@Override
public void computeScroll() {super.computeScroll();if (mScroller.computeScrollOffset()) {((View)getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());invalidate();}
}

我们在 CustomView 中写一个 smoothScrollTo 方法,调用 Scroller 的 startScroll() 方法,在 2000ms 内沿 X 轴平移 delta 像素,代码如下所示:

public void smoothScrollTo(int x, int y) {int scrollX = getScrollX();int delta = x - scrollX;mScroller.startScroll(scrollX, 0, delta, 0, 2000);invalidate();
}

最后在 Java 代码中调用 CustomView 的 smoothScrollTo() 方法。这里设定 CustomView 沿着 X 轴向右平移 500 像素。

customView.smoothScrollTo(-500, 0);

请添加图片描述

http://www.dtcms.com/a/393680.html

相关文章:

  • 【深度学习的优化理论】如何理解OT与欧几里得距离均值的区别
  • 【Android】Room数据库的基本使用
  • 项目:仿muduo库的高并发服务器
  • Oracle普通用户报错ORA-31603处理
  • 网络安全期末大论文
  • 23种设计模式之【工厂方法模式】-核心原理与 Java实践
  • cocos 添加背景,帧动画,贴图
  • 亚马逊云科技重磅推出 Amazon S3 Vectors:首款大规模支持原生向量的云存储服务
  • SQLite Expert:一款功能强大的SQLite管理工具
  • Python 2025:供应链安全威胁与防御实战
  • 队列+宽搜(BFS)-429.N叉树的层序遍历-力扣(LeetCode)
  • 【Linux命令从入门到精通系列指南】rm 命令详解:安全删除文件与目录的终极实战手册
  • Springboot使用dockerfile-maven-plugin部署镜像
  • 安卓蓝牙键盘和鼠标6.10.4去更新汉化版 手机变为蓝牙键盘和鼠标
  • 工作笔记-----lwip的内存管理策略解析
  • 量子计算学习笔记(1)
  • Python爬虫基础与应用
  • Rabbitmq 集群初始化,配置导入
  • 云计算与虚拟化技术详解
  • elasticsearch 的配制
  • React学习教程,从入门到精通,React Hook 详解 —— 语法知识点、使用方法与案例代码(26)
  • ELK日志分析性能瓶颈问题排查与解决实践指南
  • 【Unity】【Photon】Fusion2中的匹配API 学习笔记
  • (3-1) Html
  • 《人机协同的边界与价值:开放世界游戏系统重构中的AI工具实战指南》
  • 数据库造神计划第十九天---事务(2)
  • Python到剪映草稿生成及导出工具,构建全自动化视频剪辑/混剪流水线
  • WordPress给指定分类文章添加一个自动化高亮(一键复制)功能
  • 5分钟使用Dify实现《射雕英雄传》问答智能体Agent
  • 3. 认识 const