本文原创 ,转载必须注明出处:http://blog.csdn.net/qinjuning

今天给大家介绍下Android中滑屏功能的一个基本实现过程以及原理初探,最后给大家重点讲解View视图中scrollTo 与

scrollBy这两个函数的区别 。

首先 ,我们必须明白在Android View视图是没有边界的,Canvas是没有边界的,只不过我们通过绘制特定的View时对

Canvas对象进行了一定的操作,例如 : translate(平移)、clipRect(剪切)等,以便达到我们的对该Canvas对象绘制的要求 ,

我们可以将这种无边界的视图称为“视图坐标”-----它不受物理屏幕限制。通常我们所理解的一个Layout布局文件只是该视

图的显示区域,超过了这个显示区域将不能显示到父视图的区域中 ,对应的,我们可以将这种有边界的视图称为“布局坐标

------ 父视图给子视图分配的布局(layout)大小。而且, 一个视图的在屏幕的起始坐标位于视图坐标起始处,如下图所示。

这么来说吧 ,世界本是无边无界的,可是我们的眼睛我们的心约束了我们所看到的“世界” 。

如下所示:

黑色框框表示该子视图的布局坐标, 褐色框框表示该子视图的视图坐标--该坐标是无限的,超过了父视图给子视图

规定的区域后,不再显示该超出内容。

那么下面的问题就是:如何将我们的视图的任意坐标能显示到该视图的中心坐标上呢? 由于该布局位置是只能显示特定的

一块视图内容 ,因此我们需要通过scrollTo()或者scrollBy()方法将我们期望的视图“滚动”至布局坐标上。

在View.java中提供了了如下两个变量以及相应的属性方法去读取滚动值 ,如下: View.java类中

[java] view plain copy print ?
  1. /**
  2. *Theoffset,inpixels,bywhichthecontentofthisviewisscrolled
  3. *horizontally.
  4. *{@hide}
  5. */
  6. protectedintmScrollX;//该视图内容相当于视图起始坐标的偏移量,X轴方向
  7. /**
  8. *Theoffset,inpixels,bywhichthecontentofthisviewisscrolled
  9. *vertically.
  10. *{@hide}
  11. */
  12. protectedintmScrollY;//该视图内容相当于视图起始坐标的偏移量,Y轴方向
  13. /**
  14. *Returnthescrolledleftpositionofthisview.Thisistheleftedgeof
  15. *thedisplayedpartofyourview.Youdonotneedtodrawanypixels
  16. *fartherleft,sincethoseareoutsideoftheframeofyourviewon
  17. *screen.
  18. *
  19. *@returnTheleftedgeofthedisplayedpartofyourview,inpixels.
  20. */
  21. publicfinalintgetScrollX(){
  22. returnmScrollX;
  23. }
  24. /**
  25. *Returnthescrolledtoppositionofthisview.Thisisthetopedgeof
  26. *thedisplayedpartofyourview.Youdonotneedtodrawanypixelsabove
  27. *it,sincethoseareoutsideoftheframeofyourviewonscreen.
  28. *
  29. *@returnThetopedgeofthedisplayedpartofyourview,inpixels.
  30. */
  31. publicfinalintgetScrollY(){
  32. returnmScrollY;
  33. }


注意,所谓的“by which the content of this view is scrolled”表示该偏移量只针对于该View中onDraw()方法里的

具体内容实现,而不针对绘制背景图片等 。具体原因可参考<Android中View绘制流程以及invalidate()等相关方法分析>

提示:下文中提到的当前视图内容是在绘制在布局坐标处的内容。

public voidscrollTo(int x, int y)

说明:在当前视图内容偏移至(x , y)坐标处,即显示(可视)区域位于(x , y)坐标处。

方法原型为: View.java类中

[java] view plain copy print ?
  1. /**
  2. *Setthescrolledpositionofyourview.Thiswillcauseacallto
  3. *{@link#onScrollChanged(int,int,int,int)}andtheviewwillbe
  4. *invalidated.
  5. *@paramxthexpositiontoscrollto
  6. *@paramytheypositiontoscrollto
  7. */
  8. publicvoidscrollTo(intx,inty){
  9. //偏移位置发生了改变
  10. if(mScrollX!=x||mScrollY!=y){
  11. intoldX=mScrollX;
  12. intoldY=mScrollY;
  13. mScrollX=x;//赋新值,保存当前便宜量
  14. mScrollY=y;
  15. //回调onScrollChanged方法
  16. onScrollChanged(mScrollX,mScrollY,oldX,oldY);
  17. if(!awakenScrollBars()){
  18. invalidate();//一般都引起重绘
  19. }
  20. }
  21. }

public voidscrollBy(int x, int y)

说明:在当前视图内容继续偏移(x , y)个单位,显示(可视)区域也跟着偏移(x,y)个单位。

方法原型为: View.java类中

[java] view plain copy print ?
  1. /**
  2. *Movethescrolledpositionofyourview.Thiswillcauseacallto
  3. *{@link#onScrollChanged(int,int,int,int)}andtheviewwillbe
  4. *invalidated.
  5. *@paramxtheamountofpixelstoscrollbyhorizontally
  6. *@paramytheamountofpixelstoscrollbyvertically
  7. */
  8. //看出原因了吧。。mScrollX与mScrollY代表我们当前偏移的位置,在当前位置继续偏移(x,y)个单位
  9. publicvoidscrollBy(intx,inty){
  10. scrollTo(mScrollX+x,mScrollY+y);
  11. }


第一个小Demo非常简单 ,大家重点理解与掌握scrollTo() 与 scrollBy()函数的用法和区别。

第二个小Demo则有了Launcher的模样,能够左右切换屏幕 。实现功能如下: 采用了一个自定义ViewGroup,该ViewGroup

对象包含了3个LinearLayout子视图,并且以一定的布局坐标(由layout()方法指定)显示在ViewGroup上。 接下来,即可调用该

ViewGroup对象的scrollTo或者scrollBy()方法切换指定视图内容了,即切换屏幕。 呵呵 ,挺好玩的吧 。

如果对View绘制流程不懂的,可以参考我的这篇博客<Android中View绘制流程以及invalidate()等相关方法分析> 。

截图如下:

自定义ViewGroup如下:

[java] view plain copy print ?
  1. //自定义ViewGroup,包含了三个LinearLayout控件,存放在不同的布局位置,通过scrollBy或者scrollTo方法切换
  2. publicclassMultiViewGroupextendsViewGroup{
  3. privateContextmContext;
  4. privatestaticStringTAG="MultiViewGroup";
  5. publicMultiViewGroup(Contextcontext){
  6. super(context);
  7. mContext=context;
  8. init();
  9. }
  10. publicMultiViewGroup(Contextcontext,AttributeSetattrs){
  11. super(context,attrs);
  12. mContext=context;
  13. init();
  14. }
  15. privatevoidinit(){
  16. //初始化3个LinearLayout控件
  17. LinearLayoutoneLL=newLinearLayout(mContext);
  18. oneLL.setBackgroundColor(Color.RED);
  19. addView(oneLL);
  20. LinearLayouttwoLL=newLinearLayout(mContext);
  21. twoLL.setBackgroundColor(Color.YELLOW);
  22. addView(twoLL);
  23. LinearLayoutthreeLL=newLinearLayout(mContext);
  24. threeLL.setBackgroundColor(Color.BLUE);
  25. addView(threeLL);
  26. }
  27. //measure过程
  28. @Override
  29. protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
  30. Log.i(TAG,"---startonMeasure--");
  31. //设置该ViewGroup的大小
  32. intwidth=MeasureSpec.getSize(widthMeasureSpec);
  33. intheight=MeasureSpec.getSize(heightMeasureSpec);
  34. setMeasuredDimension(width,height);
  35. intchildCount=getChildCount();
  36. Log.i(TAG,"---onMeasurechildCountis-->"+childCount);
  37. for(inti=0;i<childCount;i++){
  38. Viewchild=getChildAt(i);
  39. //设置每个子视图的大小,即全屏
  40. child.measure(MultiScreenActivity.screenWidth,MultiScreenActivity.scrrenHeight);
  41. }
  42. }
  43. //layout过程
  44. @Override
  45. protectedvoidonLayout(booleanchanged,intl,intt,intr,intb){
  46. //TODOAuto-generatedmethodstub
  47. Log.i(TAG,"---startonLayout--");
  48. intstartLeft=0;//每个子视图的起始布局坐标
  49. intstartTop=10;//间距设置为10px相当于android:marginTop="10px"
  50. intchildCount=getChildCount();
  51. Log.i(TAG,"---onLayoutchildCountis-->"+childCount);
  52. for(inti=0;i<childCount;i++){
  53. Viewchild=getChildAt(i);
  54. child.layout(startLeft,startTop,
  55. startLeft+MultiScreenActivity.screenWidth,
  56. startTop+MultiScreenActivity.scrrenHeight);
  57. startLeft=startLeft+MultiScreenActivity.screenWidth;//校准每个子View的起始布局位置
  58. //三个子视图的在屏幕中的分布如下[0,320]/[320,640]/[640,960]
  59. }
  60. }
  61. }


PS :大家可以分别给这几个LinearLayout试着添加几个子View,例如TextView, Button等

至于Launcher上滑屏功能的实现,我尝试着去掌握,可能天资愚钝吧,对Scoller类很是感冒,现今还没有掌握好,不过在此

给大家推荐几个不错的学习资源 。以后有需要的话,还是采用拿来主义吧。 囧

1、 Scoller类介绍:android 中文 api (64) —— Scroller

2、相关资源汇总:http://blog.csdn.net/dellheng/article/details/7164275

3,launcher修改--左右滑动屏幕切换源码追踪

示例源代码位于:http://download.csdn.net/detail/qinjuning/4054840




补充(收回上面一段话,- -):关于如何实现触摸滑屏---- 仿Launcher滑屏以及Scoller类的使用,请参阅我的

另外一篇博文:Android中滑屏实现----手把手教你如何实现触摸滑屏以及Scroller类详解

更多相关文章

  1. OpenGL ES 纹理过滤模式-glTexParameteri
  2. 快速了解Android(安卓)onMeasure() onLayout()
  3. Activity 属性设置参数说明
  4. android 查看解压后的.xml文件代码(axmlprinter2)
  5. Android(安卓)Pull解析
  6. Introduction to Model View Presenter on Andriod
  7. AMD windows7安装和打开genymotion、android studio遇到的问题
  8. Android(安卓)中文API (94) ―― MediaController
  9. android 自定义Dialog(背景图等)

随机推荐

  1. Android(安卓)创建fragment时向fragment
  2. Android原生集成react-native(二)-热更新
  3. React-native 集成react-native-getui 爬
  4. Android 自定义view的简单应用(3) 时钟
  5. Android系统的开机画面显示过程分析(3)
  6. android 数据库 数据倒序排列
  7. 初学Android,电池电量提示(七十五)
  8. 【ListView】自定义控件:下拉刷新
  9. Android 4.4 SystemUI 的面板quicksettin
  10. Android(安卓)CI - Jenkins