View 的滑动
View 的滑动
学习自
《Android开发艺术探索》
滑动漫谈
因为Android手机屏幕大小的原因,所以为了显式更多的信息,我们必须采用滚动的方式来处理,因为滚动就涉及到了滑动,有的滑动十分生硬,而有的滑动却是圆润并且绚丽的,View的滑动就是我们本章要学习的内容。
使用scrollTo/scrollBy
注意,这种方式只是改变了View内容的位置,并没有改变View的位置,以Button为例,那就是仅仅改变了Button中的文本的位置,而没有改变Button的位置。
scrollTo 实现了指定位置的绝对滑动
/**
* Set the scrolled position of your view. This will cause a call to
* {@link #onScrollChanged(int, int, int, int)} and the view will be
* invalidated.
* 设置View的滚动的位置,这一操作将会回到onScrollChange事件
* 这一操作将会使View失效
* @param x the x position to scroll to
* x 滑动到的x坐标
* @param y the y position to scroll to
* y 滑动到的y坐标
*/
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();
}
}
}
scrollBy 实现了基于当前位置的相对滑动
/**
* Move the scrolled position of your view. This will cause a call to
* {@link #onScrollChanged(int, int, int, int)} and the view will be
* invalidated.
* @param x the amount of pixels to scroll by horizontally
* x 横向滚动的像素的总和
* @param y the amount of pixels to scroll by vertically
* y 纵向滚动的像素的总和
*/
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}
代码分析,通过查看scrollBy的代码,我么发现scrollBy的实现也是基于scrollTo的,所以我们需要分析scrollTo的代码,在scrollTo的代码中,有 mScrollX 和 mScrollY 这两个值需要我们多注意一下,其中,mScrollX 值代表的是view的内容和View左边缘的距离,mScrollY带边的view的内容与view上边缘的值。
通过动画
通过补间动画来完成移动
这里省略的补间动画实现的介绍,因为补间动画并不会真正的改变View的位置,而只是改变的View的影像。这里就不说,因为已经有了属相动画来替代补间动画。
通过属性动画俩完成移动
scrollBtn.setOnClickListener {
ObjectAnimator
.ofFloat(scrollBtn, "translationX", 0.0F, 100.0F)
.setDuration(1000L)
.start()
}
改变布局参数
通过改变ViewLayoutParams的值,我们也可以实现View的移动。方式如下
scrollBtn.setOnClickListener {
var params = scrollBtn.layoutParams as ViewGroup.MarginLayoutParams
params.leftMargin = 100
scrollBtn.requestLayout()
}
总结
上面的三种方法都可以实现View的滑动。我们来总结一下
- scrollTo/scrollBy,仅仅改变的是View内容的位置,而不嫩改变View自身的位置
- 使用动画,如果是Android3.0及以上的版本使用动画实现滑动是一个非常好的方式,如果在3.0已下就需要处理View的移动的问题了,推荐使用在没有交互的View上,如果使用的3.0以上则另当别论。
- 是真正的改变了View的位置,推荐使用在有交互性的View上。
平滑的滑动
通过上面的集中方法我们已经可以实现View的滑动,但是上面的方法除了通过动画的方式外,实现的效果都比较生硬,所以现在我们来学习一下,如何平滑地实现滑动。
Scroller
Scroller类并能帮助我们进行滑动操作,它仅仅是为我们完成滑动过程中的计算,实际的滑动的功能还需要我们自己实现,ViewPager中就中就采用了Scroller来实现,下面我们以一个Dome(将一个TextView向右滑动)的形式来学习Scroller。

class MyTextView(context: Context, attrs: AttributeSet) : TextView(context, attrs) {
var mScroller = Scroller(context)
fun smoothScroll(destX: Int, destY: Int) {
var deltaX = destX - x
L.e(deltaX.toString())
this.mScroller.startScroll(x.toInt(), 0, deltaX.toInt(), 0, 1000)
invalidate()
}
override fun computeScroll() {
if (mScroller.computeScrollOffset()) {
this.x = mScroller.currX.toFloat()
postInvalidate()
}
}
}
//调用
scrollBtn.setOnClickListener {
helloTV.smoothScroll(this.helloTV.x.toInt() + 100, 0)
}
Scroller原理浅析
首先我们调用的是Scroller的 startScroll 方法,下面是此方法的源码,其中没有任何和滑动相关的代码,仅仅是将我么传递的参数存储了起来。参数解释:
- startX 开始X轴的坐标
- startY 开始Y的坐标
- dx X轴前进的距离
- dy Y轴前进的距离
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
mMode = SCROLL_MODE;
mFinished = false;
mDuration = duration;
mStartTime = AnimationUtils.currentAnimationTimeMillis();
mStartX = startX;
mStartY = startY;
mFinalX = startX + dx;
mFinalY = startY + dy;
mDeltaX = dx;
mDeltaY = dy;
mDurationReciprocal = 1.0f / (float) mDuration;
}
从 startScroll 方法中我们发现,滚动并没有在这个方法中,那滑动的效果是怎么实现的,答案是通过利用View的重绘机制实现的。请注意我们调用了 invalidate() 方法,此方法会导致View重绘,View重绘时会调用View的 draw 的方法,此方法会调用我们 computeScroll 方法,因为我们已经重写此方法,所以会调用我们重写的方法,在我们重写的 computeScroll方法中,我们移动了View后,调用 postInvalidate 方法再次引发重绘,如此循环直到结束。
上面我们提到了computeScroll,接下来看看此方法:
override fun computeScroll() {
//判断是否需要继续滑动
//true 表示滑动还未结束,需要继续滑动
//false 表示滑动已经完成
if (mScroller.computeScrollOffset()) {
//改变View的位置
this.x = mScroller.currX.toFloat()
//引发重绘
postInvalidate()
}
}
如果你查看了 computeScrollOffset 的源码的话,就会发现其中是计算偏移的长度的,并且返回值表示的是,是否需要继续滑动。到此我们已经对Scroller的工作方式有一个大概的了解了。
利用属性动画
scrollBtn.setOnClickListener {
var animator = ValueAnimator.ofInt(0, 1).setDuration(1000)
animator.addUpdateListener {
var faction = it.animatedFraction
scrollBtn.scrollTo(startX + (dalteX * faction).toInt(), 0)
}
animator.start()
}
使用延时策略
通过Handler或者View的Handler或者View的 postDelayed 方法或者利用线程睡眠的方式,我们也可以实现滑动的效果。
var end = 200
var distance = 0
var offset = 10
private fun scroll() {
Handler().postDelayed({
var temp = offset
distance += offset
if (distance > end) {
temp = distance - end
}
if (distance < end) {
scrollBtn.scrollBy(temp, 0)
scroll()
}
}, 100)
}
View 的滑动的更多相关文章
- view的滑动冲突解决方案
一.常见的滑动冲突场景 1.外部滑动方向和内部滑动方向不一致 2.外部滑动方向和内部滑动方向一致 3.上面两种情况的嵌套 二.滑动冲突处理的原则 场景1的处理原则是:当用户左右滑动时,需要让外部的vi ...
- View的滑动
View的滑动 通过三种方式可以实现View的滑动: 1.通过View本身提供的scrollTo/scrollBy方法来实现滑动 2.通过动画给View施加平移效果来实现滑动 3.通过改变View的L ...
- android中实现view可以滑动的六种方法
在android开发中,经常会遇到一个view需要它能够支持滑动的需求.今天就来总结实现其滑动的六种方法.其实每一种方法的 思路都是一样的,即:监听手势触摸的坐标来实现view坐标的变化,从而实现vi ...
- 解决TableView / ScrollView上的Menu问题(1滑出View区域还可点击2导致点击menu后View不能滑动)
解决TableView / ScrollView上的Menu问题 1划出区域还可点击 重写CCMenu的触摸事件函数 TouchBegin/TouchMove/TouchCancle/TouchEnd ...
- View的滑动冲突
一.常见的滑动冲突 场景1:外部滑动和内部滑动不一致 场景2:外部滑动和内部滑动一致 场景3:上面两种情况的嵌套 二.滑动冲突的处理方法 场景一:根据水平滑动还是竖直滑动判断到底由谁来拦截事件. 场景 ...
- Android View的滑动
Android View的滑动 文章目录 Android View的滑动 一.实现移动 1.1 layout() 1.2 设置位置偏移量 1.3 改变布局参数 1.4 动画 1.5 ScrollTo以 ...
- 一个Demo带你彻底掌握View的滑动冲突
本文已授权微信公众号:鸿洋(hongyangAndroid)在微信公众号平台原创首发. 近期在又一次学习Android自己定义View这一块的内容.遇到了平时开发中常常碰到的一个棘手问题:View的滑 ...
- 解析6种常用View 的滑动方法
View 的滑动是Android 实现自定义控件的基础,实现View 滑动有很多种方法,在这里主要讲解6 种滑动方法,分别是layout().offsetLeftAndRight()与offsetTo ...
- 【朝花夕拾】Android自定义View篇之(十一)View的滑动,弹性滑动与自定义PagerView
前言 由于手机屏幕尺寸有限,但是又经常需要在屏幕中显示大量的内容,这就使得必须有部分内容显示,部分内容隐藏.这就需要用一个Android中很重要的概念——滑动.滑动,顾名思义就是view从一个地方移动 ...
随机推荐
- unity常用小知识点
感觉自己抑郁变得更严重了,超级敏感,经常想崩溃大哭,睡眠超差,实在不想药物治疗,多看看书,多约约朋友,多出去走走. 来几句鸡汤吧,人一定要活得明白一点,任何关系都不要不清不楚,说不定最后受伤的就是自个 ...
- sqoop的安装与配置
最近需要将MySQL的数据导出到HDFS,所以搜到了sqoop2.跟sqoop1相比,sqoop2的好处是直接使用程序连接到集群上的sqoop,远程操作.流程是需要先创建link也可以理解成要操作的对 ...
- 鸟哥的Linux私房菜——第十七章:Linux 账号与身份管理
视频链接:http://www.bilibili.com/video/av10669732/ 1. Linux 的账号与群组1.1 使用者识别: UID 与 GID1.2 使用者账号:/etc/pas ...
- C#实现物联网系统温度解析的函数(支持补码)
基于物联网协议上传数据,其中温度占两个字节,如01 27,表示温度值为29.7.温度负值为补码(也就是温度值为有符号数),例如0XFFFF值为负1(-0.1度). 针对补码要求,修改数据解析函数如下: ...
- java取得当前日期增加一天或多天
代码如下: SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); Calendar c = Calendar.getI ...
- J2EE架构
从整体上讲,J2EE是使用Java技术开发企业级应用的一种事实上的工业标准(Sun公司出于其自身利益的考虑,至今没有将Java及其相关技术纳入标准化组织的体系),它是Java技术不断适应和促进企业级应 ...
- ZYNQ. Interrupt(2)SPI.AXI TIMER
Shared Peripheral Interrupts (SPI) SPI 可以接收来自PL的中断,这里使用PL模块 AXI Timer 的中断模式,并连接到CPU. AXI TIMER 定时器,内 ...
- SocketServer源码学习补充
在前两个文章中整理了关于BaseServer部分以及BaseRequestHandler,以及通过对TCP的处理的流程的整理,这次整理的是剩下的关于用于扩展的部分,这里通过对线程扩展进行整理 Thre ...
- word技巧
1.插入注解(脚注和尾注) 2.复制的图片显示不全怎么办? 横向显示,或者图片另存为然后保存为PPT 3.word修订标记的添加和删除(最终版) 4.word中表格样式调整 5.修改标题的样式和标题的 ...
- MySQL管理工具MySQL Utilities — 介绍与安装(1)
MySQL Utilities介绍 MySQL Utilities 提供一组命令行工具用于维护和管理 MySQL 服务器,包括: 管理工具 (克隆.复制.比较.差异.导出.导入) 复制工具 (安装.配 ...