Scroller类的使用总结
Scroll类之所以不好理解是因为没有搞清楚View的绘制流程。
1)简单来讲 viewgroup重绘时依次会调用 dispatchDraw -- drawChild --child.computeScroll()。
computeScroll是一个空函数,可以在里面写代码。
2)Scroller类一些api:
- mScroller.getCurrX() //获取mScroller当前水平滚动的位置
- mScroller.getCurrY() //获取mScroller当前竖直滚动的位置
- mScroller.getFinalX() //获取mScroller最终停止的水平位置
- mScroller.getFinalY() //获取mScroller最终停止的竖直位置
- mScroller.setFinalX(int newX) //设置mScroller最终停留的水平位置,没有动画效果,直接跳到目标位置
- mScroller.setFinalY(int newY) //设置mScroller最终停留的竖直位置,没有动画效果,直接跳到目标位置
- //滚动,startX, startY为开始滚动的位置,dx,dy为滚动的偏移量, duration为完成滚动的时间
- mScroller.startScroll(int startX, int startY, int dx, int dy) //使用默认完成时间250ms
- mScroller.startScroll(int startX, int startY, int dx, int dy, int duration)
- mScroller.computeScrollOffset() //返回值为boolean,true说明滚动尚未完成,false说明滚动已经完成。这是一个很重要的方法,通常放在View.computeScroll()中,用来判断是否滚动是否结束。
其中非常重要的startScroll()和computeScrollOffset()函数。
startScroll函数的功能是设置一些值,最重要的值是设置了一个滚动开始时间和持续时间,其源码如下:
- 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;
- }
computeScrollOffset()是用来计算当前时间点理论上能够滚到的x,y坐标。
如果滚动持续时间到了则返回false,否则返回true并计算坐标。mCurrX和mCurrY得到更新。源码如下:
- public boolean computeScrollOffset() {
- if (mFinished) {
- return false;
- }
- int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
- if (timePassed < mDuration) {
- switch (mMode) {
- case SCROLL_MODE:
- float x = timePassed * mDurationReciprocal;
- if (mInterpolator == null)
- x = viscousFluid(x);
- else
- x = mInterpolator.getInterpolation(x);
- mCurrX = mStartX + Math.round(x * mDeltaX);
- mCurrY = mStartY + Math.round(x * mDeltaY);
- break;
- case FLING_MODE:
- final float t = (float) timePassed / mDuration;
- final int index = (int) (NB_SAMPLES * t);
- float distanceCoef = 1.f;
- float velocityCoef = 0.f;
- if (index < NB_SAMPLES) {
- final float t_inf = (float) index / NB_SAMPLES;
- final float t_sup = (float) (index + 1) / NB_SAMPLES;
- final float d_inf = SPLINE_POSITION[index];
- final float d_sup = SPLINE_POSITION[index + 1];
- velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
- distanceCoef = d_inf + (t - t_inf) * velocityCoef;
- }
- mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
- mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
- // Pin to mMinX <= mCurrX <= mMaxX
- mCurrX = Math.min(mCurrX, mMaxX);
- mCurrX = Math.max(mCurrX, mMinX);
- mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
- // Pin to mMinY <= mCurrY <= mMaxY
- mCurrY = Math.min(mCurrY, mMaxY);
- mCurrY = Math.max(mCurrY, mMinY);
- if (mCurrX == mFinalX && mCurrY == mFinalY) {
- mFinished = true;
- }
- break;
- }
- }
- else {
- mCurrX = mFinalX;
- mCurrY = mFinalY;
- mFinished = true;
- }
- return true;
- }
3)通过1、2我们可以知道如果要实现平滑滚动则需要在computeScroll函数里调用computeScrollOffset()来更新Scroller里面的mCurrX 和mCurrY,然后利用
scrollTo(mCurrX, mCurrY) 来让View的x、y坐标滚动到指定位置。此时并不一定会导致view重绘,手动调用postInvalidate()自上而下重绘view树。
注意scrollTo只会导致该view的内容发生偏移,并不会导致该view的位置偏移。比如对Button进行scrollTo 会导致Button里面的text发生偏移,而Button的位置不会发生偏移。
4) 有了上面的分析后下面是一段小实例,单击按钮后,按钮会慢慢下移。
CustomView.java:
- public class CustomView extends LinearLayout {
- private Scroller mScroller = null;
- private Context mContext;
- public CustomView(Context context) {
- super(context);
- mContext = context;
- init();
- }
- public CustomView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mContext = context;
- init();
- }
- private void init() {
- if (mScroller == null) {
- mScroller = new Scroller(mContext);
- }
- this.setOrientation(VERTICAL);
- Button btn = new Button(mContext);
- btn.setText("按钮");
- LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
- this.addView(btn, params);
- this.setBackgroundColor(Color.YELLOW);
- }
- //调用此方法设置滚动到目标位置
- public void smoothScrollTo(int fx, int fy) {
- int dx = fx - mScroller.getFinalX();
- int dy = fy - mScroller.getFinalY();
- smoothScrollBy(dx, dy);
- }
- //调用此方法设置滚动的相对偏移
- public void smoothScrollBy(int dx, int dy) {
- mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy, 10000);
- invalidate();
- }
- @Override
- public void computeScroll() {
- // TODO Auto-generated method stub
- //查看是否滚动结束了,true表示没有结束
- if (mScroller.computeScrollOffset()) {
- //调用view的滚动函数,进行实际滚动。
- scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
- //只有postInvalidate了才能循环刷新。
- postInvalidate();
- }
- super.computeScroll();
- }
- }
MainActivity.java:
- public class MainActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- final CustomView view = new CustomView(this);
- setContentView(view);
//给button添加onClick监听- view.getChildAt(0).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- view.smoothScrollBy(0, -100);
- }
- });
- }
- }
参考网页:http://www.cnblogs.com/PDW-Android/p/3653253.html
http://blog.csdn.net/gemmem/article/details/7321910
http://www.open-open.com/lib/view/open1328834050046.html
Scroller类的使用总结的更多相关文章
- 简单的ViewPager了解Scroller类
View滑动是自定义ViewGroup中十分常见的一个功能.Android提供了多种View滑动的方法. layout方法 offsetLeftAndRight()与offsetTopAndBotto ...
- 在Android中动画移动一个View的位置,采用Scroller类实现Android动画之 View移动
在Android中动画移动一个View的位置,采用Scroller类实现 今天说最近自己遇到的一个问题,就是要用动画效果来移动一个VIew的位置. 这个具体的情况是,需要做一个SlidingMenu的 ...
- Android中滑屏实现----手把手教你如何实现触摸滑屏以及Scroller类详解
前言: 虽然本文标题的有点标题党的感觉,但无论如何,通过这篇文章的学习以及你自己的实践认知,写个简单的滑屏小 Demo还是just so so的. 友情提示: 在继续往下面读之前,希望您对以下知识点 ...
- Android Scroller类的详细分析
尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/7321910 Scroller这个类理解起来有一定的困难,刚开始接触Scrol ...
- Android 界面滑动实现---Scroller类 从源码和开发文档中学习(让你的布局动起来)
在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现.. 例子相关博文:Androi ...
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码
在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现.下面要说的就是上次Scroller ...
- Android自己定义组件系列【2】——Scroller类
在上一篇中介绍了View类的scrollTo和scrollBy两个方法,对这两个方法不太了解的朋友能够先看<自己定义View及ViewGroup> scrollTo和scrollBy尽管实 ...
- Android VelocityTracker类和Scroller类
VelocityTracker类:用于跟踪触屏事件的速度,通常使用VelocityTracker的步骤如下: static VelocityTracker obtain():获取一个VelocityT ...
- Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源代码
在android学习中,动作交互是软件中重要的一部分.当中的Scroller就是提供了拖动效果的类,在网上.比方说一些Launcher实现滑屏都能够通过这个类去实现.以下要说的就是上次Scroller ...
随机推荐
- Serialization之BinaryFormatter
前言 BinaryFormatter序列化二进制序列化使用二进制编码来生成精简的序列化,以用于存储或基于套接字的网络流等. 内容 下面通过一个小小的例子来给大家说明什么是BinaryFormatter ...
- ASP.NET-GridView之固定表数据滚动
有时候,在线Web开发时,需要显示的数据往往会超过我们规定的表格长度,所以为了方便显示大量数据,为了美观,这里提出了两种显示数据方式. ①可以滚动显示数据但是表头未能获取 效果显示 前端DEMO &l ...
- ASPxGridView 下拉框不让输入
DropDownStyle="DropDownList"该属性使combox控件不能手动输入数据,只能在下拉列表中选择
- opencv第一课,安装配置
下载工具:本教程以OpenCV3.2.0为例. 解压:本教程解压到D盘,解压的其它地方也是可以的,解压完后得到一个名为opencv目录. 配置系统变量:选择此电脑(计算机)->右键属性选择-&g ...
- poi进行excle操作
一 excle导出: 所需要jar包 <dependency> <groupId>org.apache.poi</groupId> <artifactId&g ...
- README.md使用
1.标题: # 一级标题 ## 二级标题 ### 三级标题 2.换行: <br> 3.代码: ``` 代码在中间 ``` 4.表格: 表头 | 表头 | 表头 ---- | ----- | ...
- Vue-Router路由Vue-CLI脚手架和模块化开发 之 路由的动态跳转
在上一篇的博文中,实现的跳转是在页面中进行实现的 利用vue-router实例方法,使用js对路由进行动态跳转: 1.router.push:参数为路由对象,跳转到指定路由,跳转后会产生历史记录: & ...
- 将优狐智能插座接入 Domoticz
前言 前几天在某淘宝优惠中看到一个 WiFi 智能插座卖 29 块包邮,心想要是里面是 ESP8266 模块说不定可以刷上固件玩玩,就买了俩回来,记下折腾过程. 拆解 WiFi 智能插座的淘宝介绍页 ...
- eclipse gradle 找不到依赖解决办法
右击工程,选择gradle 在点击Refresh Gradle Project 即可,..不得不说,gradle 在eclipse 下真没maven 好用.....
- C语言ctype.h字符函数和字符串
ctype.h存的是与字符相关的函数: 这些函数虽然不能处理整个字符串,但是可以处理字符串中的字符: ToUpper()函数,利用toupper()函数处理字符串中的每个字符,转换成大写: Punct ...