初探Android Scroll——scrollTo()与scrollBy()
来源:互联网 发布:淘宝企业店铺开店资料 编辑:程序博客网 时间:2024/05/01 11:24
Scroll是android中很常见的交互方式,使用得好可以使我们的应用更具有体验性。本着学习与探究的精神,我尝试来解析一下我所知道的android scroll,这篇文章是我对scrollTo()和scrollBy()的一些理解。
1. View边界问题
在学习ScrollTo()和ScrollBy()之前,我们有必要来了解一下android的坐标系,如下图所示:
通常我们所看到的就是这个坐标系,也就是手机的左上角为原点(0,0)水平方向为x轴,垂直方向为y轴,整个屏幕就是个在x和y轴正方向的有限矩形区域。我们再来看下android的ui结构,如下图:
可以看到,我们所能看到的手机屏幕视图就是一个ViewGroup,而ViewGroup也是继承自View。回顾一下view的绘制,可以知道,其实我们所看到的视图内容是画在画布Canvas上的,当然canvas也拥有一个坐标系,我们在通过drawXXX()方法画图时就需要知道图形的具体坐标。
因为我们一般都是以我们屏幕(或者说view)为参考系的,view本身的变化,我们肉眼是看不到的,只能看到相对view的canvas的变化。所以我们通过移动canvas可以造成view内容移动的视觉。
我们来定义一个view,重写onDraw()画出一个200*200的蓝色矩形,以下是java代码:
publicclass MyViewextends View { public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.FILL); canvas.drawRect(0,0,200,200,paint); }}
呈现出来的如下(由于布局代码很简单,就不贴上来了):
从代码中我们可以看到这样一个过程:我们拿起笔Paint,在画布Canvas上画了一个我们想要的图形,蓝色的正方形,然后通过View看到了它。就好像一个画家画了一幅画,然后把它镶嵌到画框里,我们通过画框,看到了画里有一个人。但如果画家本来是画了一群人,只是把显示一个人的画的部分放到画框里让我们看到呢?再来看,View就是一个画框,Canvas就是画布,Paint是笔,那么我们所看到是不是视图的部分呢?接下来我们来证实这个想法。DrawRect()前4个参数是X,Y轴的起始和结束位置,我们尝试把它设为负数看看有什么效果。
canvas.drawRect(-100,0,200,200,paint);
显示的视图并没有什么不一样,显然“画框”View的左上角是和(0,0)重合了。Canvas中有一个translate(x,y),它起到平移画布的效果,我们将画布右移100,然后再将之前的矩形画到上面。
@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.FILL); canvas.save(); canvas.translate(100,0); canvas.drawRect(-100,0,200,200,paint); canvas.restore();}
这时视图变成以下这样了:
显然我们画在x轴负轴的部分也被显示出来了,这就说明,画布的内容并不只是我们看到的这些,可能有很多内容是被View这个块中空的板遮住了。X,Y的二维平面式没有边界的,所以我们在画布上画的画理论上是无限大的,View只是截取了一部分让我们看到。
我看了一些有关view绘制的文章,有些作者喜欢把View说成是无界的,我觉得这种说法不准确,应该说view是有界的,而Canvas是无界的。我更喜欢View是一个中空的不透明板的说法,我们透过view无限绘图世界的一小部分。
2. 终于到ScrollTo()和ScrollBy()了
或许上面讲了一堆废话,但是尝试了解一些原理,并自己把自己的理解写下来并不是一件容易的事。 ScrollTo()和ScrollBy()是View类通过api,可以通过他们滑动view(其实是滑动view的内容)。通过字词就可以理解,ScrollTo()是滑动到目标位置,ScrollBy()是滑动所给偏移量。我们看下ScrollBy()的实现:
public void scrollBy(int x, int y) { scrollTo(mScrollX + x, mScrollY + y);}
其实对ScrollTo()再次包装,而mScrollX和mScrollY是view相对canvas的偏移量,可以通过view实例方法getScrollX()和getScollY()获取他们的值。我们来测试一下ScrollTo(),布局就只添加一个TextView,部分java代码如下:
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); TextView tv = (TextView) findViewById(R.id.tv); Log.i("TestActivity",tv.getScrollX()+","+tv.getScrollY()); tv.scrollTo(100, 0); Log.i("TestActivity", tv.getScrollX() + "," + tv.getScrollY());}
先输出tv的初始ScrollX和ScrollY,然后滑动到(100,0)再输出当前的结果如下:
我们自定义一个view,来看使用scrollTo()的效果。MyView的java代码:
public class MyView extends View { public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.YELLOW); Paint paint = new Paint(); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.FILL); canvas.drawRect(-100,0,200,200,paint); }}
布局中加入MyView控件:
<com.forzero.moveview.MyView android:layout_width="200dp" android:layout_height="200dp" android:id="@+id/view2" />
Activity的java代码:
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); MyView view2 = (MyView) findViewById(R.id.view2); view2.scrollTo(-100, 0);}
运行前的MyView视图如下:
运行后如下:
通过scrollTo(),可以把之前隐藏的蓝色部分显示出来了,这就证明scrollTo()和scrollBy()只是移动View的内容,我们想要移动view本身可以对其父容器操作,代码如下:
((View)myView.getParent()).scrollBy(-100, 0);
值得注意的是,由于偏移量是view相对canvas的,所以要达到想要的效果则需取数值的相反数。
3. 一个Demo
布局:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true"> <ImageView android:id="@+id/view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@mipmap/ic_launcher" /> </RelativeLayout> <Button android:id="@+id/btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="x:100" /> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/btn1" android:text="x:-100" /> <Button android:id="@+id/btn3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/btn2" android:text="y:100" /> <Button android:id="@+id/btn4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/btn3" android:text="y:-100" /></RelativeLayout>
java代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private ImageView myView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myView = (ImageView) findViewById(R.id.view); findViewById(R.id.btn1).setOnClickListener(this); findViewById(R.id.btn2).setOnClickListener(this); findViewById(R.id.btn3).setOnClickListener(this); findViewById(R.id.btn4).setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn1: ((View)myView.getParent()).scrollBy(-100, 0); break; case R.id.btn2: ((View)myView.getParent()).scrollBy(100, 0); break; case R.id.btn3: ((View)myView.getParent()).scrollBy(0, -100); break; case R.id.btn4: ((View)myView.getParent()).scrollBy(0, 100); break; } }}
效果截图:
- 初探Android Scroll——scrollTo()与scrollBy()
- Android滑动(三)——scrollTo与scrollBy
- [Android] View scrollTo()与scrollBy()
- Android小总结:scrollTo 与 scrollBy
- Android中ScrollTo()与ScrollBy()备忘录
- Android scrollTo()与scrollBy()的区别
- android scrollto 与scrollby 的理解
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
- Android中滑屏初探 - scrollTo 以及 scrollBy方法使用说明
- 04-transform
- 两个栈实现队列
- [乡土民间故事_徐苟三传奇]第五回_黄知县对联丢尽脸
- cvFloodFill漫水填充算法
- 尝试使用request.getRemoteAddr()时获得ipv6地址:0.0.0.0.0.0.0.1的解决方法
- 初探Android Scroll——scrollTo()与scrollBy()
- Mybatis学习(1)开发环境搭建
- RPC总结 ---发文于2013-12-20
- CSS学习笔记14-非屏幕媒体
- [AOJ 2170]Marked Ancestor[并查集][离线][路径压缩]or[线段树]
- 遇到一个把.o文件strip后出现的奇怪问题
- leetcode165---Compare Version Numbers
- [乡土民间故事_徐苟三传奇]第四回_张员外受骗摔新锅
- Android开源框架Universal-Image-Loader基本介绍和使用