View视图中scrollTo 与scrollBy这两个函数的区别 。

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

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

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

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

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

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

如下所示:

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

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

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

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

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

/**
	 * The offset, in pixels, by which the content of this view is scrolled
	 * horizontally.
	 * {@hide}
	 */
	protected int mScrollX;   //该视图内容相当于视图起始坐标的偏移量   , X轴 方向
	/**
	 * The offset, in pixels, by which the content of this view is scrolled
	 * vertically.
	 * {@hide}
	 */
	protected int mScrollY;   //该视图内容相当于视图起始坐标的偏移量   , Y轴方向

	/**
     * Return the scrolled left position of this view. This is the left edge of
     * the displayed part of your view. You do not need to draw any pixels
     * farther left, since those are outside of the frame of your view on
     * screen.
     *
     * @return The left edge of the displayed part of your view, in pixels.
     */
    public final int getScrollX() {
        return mScrollX;
    }

    /**
     * Return the scrolled top position of this view. This is the top edge of
     * the displayed part of your view. You do not need to draw any pixels above
     * it, since those are outside of the frame of your view on screen.
     *
     * @return The top edge of the displayed part of your view, in pixels.
     */
    public final int getScrollY() {
        return mScrollY;
    }

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

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

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

public void scrollTo(int x, int y)

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

方法原型为: View.java类中

    /**
     * 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.
     * @param x the x position to scroll to
     * @param y the y position to scroll to
     */
    public void scrollTo(int x, int y) {
    	//偏移位置发生了改变
        if (mScrollX != x || mScrollY != y) {
            int oldX = mScrollX;
            int oldY = mScrollY;
            mScrollX = x;  //赋新值,保存当前便宜量
            mScrollY = y;
            //回调onScrollChanged方法
            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
            if (!awakenScrollBars()) {
                invalidate();  //一般都引起重绘
            }
        }
    }
    

public voidscrollBy(int x, int y)

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

方法原型为: View.java类中

  /**
     * 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
     * @param y the amount of pixels to scroll by vertically
     */
    // 看出原因了吧 。。 mScrollX 与 mScrollY 代表我们当前偏移的位置 , 在当前位置继续偏移(x ,y)个单位
    public void scrollBy(int x, int y) {
        scrollTo(mScrollX + x, mScrollY + y);
    }

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

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

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

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

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

截图如下:

自定义ViewGroup如下:

//自定义ViewGroup , 包含了三个LinearLayout控件,存放在不同的布局位置,通过scrollBy或者scrollTo方法切换
public class MultiViewGroup extends ViewGroup {

	private Context mContext;

	private static String TAG = "MultiViewGroup";

	public MultiViewGroup(Context context) {
		super(context);
		mContext = context;
		init();
	}

	public MultiViewGroup(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
		init();
	}

	private void init() {
		// 初始化3个 LinearLayout控件
		LinearLayout oneLL = new LinearLayout(mContext);
		oneLL.setBackgroundColor(Color.RED);
        addView(oneLL);

		LinearLayout twoLL = new LinearLayout(mContext);
		twoLL.setBackgroundColor(Color.YELLOW);
		addView(twoLL);

		LinearLayout threeLL = new LinearLayout(mContext);
		threeLL.setBackgroundColor(Color.BLUE);
		addView(threeLL);
	}

	// measure过程
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		Log.i(TAG, "--- start onMeasure --");

		// 设置该ViewGroup的大小
		int width = MeasureSpec.getSize(widthMeasureSpec);
		int height = MeasureSpec.getSize(heightMeasureSpec);
		setMeasuredDimension(width, height);

		int childCount = getChildCount();
		Log.i(TAG, "--- onMeasure childCount is -->" + childCount);
		for (int i = 0; i < childCount; i++) {
			View child = getChildAt(i);
			// 设置每个子视图的大小 , 即全屏
			child.measure(MultiScreenActivity.screenWidth, MultiScreenActivity.scrrenHeight);
		}
	}

	// layout过程
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		// TODO Auto-generated method stub
		Log.i(TAG, "--- start onLayout --");
		int startLeft = 0; // 每个子视图的起始布局坐标
		int startTop = 10; // 间距设置为10px 相当于 android:marginTop= "10px"
		int childCount = getChildCount();
		Log.i(TAG, "--- onLayout childCount is -->" + childCount);
		for (int i = 0; i < childCount; i++) {
			View child = getChildAt(i);
			child.layout(startLeft, startTop,
					startLeft + MultiScreenActivity.screenWidth,
					startTop + MultiScreenActivity.scrrenHeight);
			startLeft = startLeft + MultiScreenActivity.screenWidth ; //校准每个子View的起始布局位置
			//三个子视图的在屏幕中的分布如下 [0 , 320] / [320,640] / [640,960]
		}
	}

}

scrollTo , scrollBy区别的更多相关文章

  1. 图解Android View的scrollTo(),scrollBy(),getScrollX(), getScrollY()

    https://blog.csdn.net/bigconvience/article/details/26697645 Android系统手机屏幕的左上角为坐标系,同时y轴方向与笛卡尔坐标系的y轴方向 ...

  2. View:Android View的scrollTo(),scrollBy(),getScrollX(), getScrollY()的理解

    Android系统手机屏幕的左上角为坐标系,同时y轴方向与笛卡尔坐标系的y轴方向想反.提供了 getLeft(), getTop(), getBottom(), getRight() 这些API来获取 ...

  3. 【Scroller】scrollTo scrollBy startScroll computeScroll 自定义ViewPage 简介 示例

    简介 android.widget.Scroller是用于模拟scrolling行为,它是scrolling行为的一个帮助类.我们通常通过它的 startScroll 函数来设置一个 scrollin ...

  4. Android scrollTo() scrollBy() Scroller解说及应用

    版本号:1.0  日期:2014.6.17  2014.6.18 版权:© 2014 kince 转载注明出处   scrollTo() .scrollBy()及 Scroller在视图滑动中常常使用 ...

  5. getX,getY,getScrollX,getScrollY,ScrollTo(),ScrollBy()辨析

    前言:前两天看了自定义控件,其中有一些东西我觉得有必要深入理解一下 以下图为例: getX(),getY()返回的是触摸点A相对于view的位置 getRaw(),getRawY()返回的是触摸点B相 ...

  6. scrollTo 和 scrollBy

      涉及到滑动,就涉及到VIEW,大家都知道,Android的UI界面都是由一个一个的View以及View的派生类组成,View作为基类,而常用的布局里面的各种布局就是它派生出来的ViewGroup的 ...

  7. android 布局之滑动探究 scrollTo 和 scrollBy 方法使用说明

    涉及到滑动,就涉及到VIEW,大家都知道,Android的UI界面都是由一个一个的View以及View的派生类组成,View作为基类,而常用的布局里面的各种布局就是它派生出来的ViewGroup的子类 ...

  8. Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源码

    在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现.下面要说的就是上次Scroller ...

  9. Android艺术开发探索第三章——View的事件体系(上)

    Android艺术开发探索第三章----View的事件体系(上) 我们继续来看这本书,因为有点长,所以又分了上下,你在本片中将学习到 View基础知识 什么是View View的位置参数 Motion ...

随机推荐

  1. python读写文件时中文的转码问题

    读写文件都要将中文转为unicode字符. 读文件: u = unicode(s, 'gbk') 这里不能使用encode 写文件: u = encode('utf')

  2. ios coredata 无任何错误提示crash

    最近写程序是遇到了一种情况,对coredata 操作时,有一定几率crash,crash时无任何说明,断点调试后发现,fetch出的对象的属性竟然和数据库中的不同,不知道什么情况下导致了context ...

  3. 安装courier-authlib找不到mysqlclient.so文件

    使用configure配置的时候使用 --with-authmysql指明libmysqlclient.so的存放位置即可

  4. linux (RHEL) 添加和删除用户

    linux添加新用户使用 useradd -----create a new user or update default new user information 删除用户使用userdel  -- ...

  5. Innodb 表空间卸载、迁移、装载

    从MySQL的Innodb特性中我们知道,Inndob的表空间有共享和独享的特点,如果是共享的.则默认会把表空间存放在一个文件中(ibdata1),当开启独享表空间参数Innodb_file_per_ ...

  6. 最牛逼android上的图表库MpChart(一) 介绍篇

    最牛逼android上的图表库MpChart一 介绍篇 MpChart优点 MpChart是什么 MpChart支持哪些图表 MpChart效果如何 最牛逼android上的图表库MpChart(一) ...

  7. August 8th 2016, Week 33rd Monday

    Everything is going on, but don't give up trying. 万事随缘,但不要放弃努力. Every time when I want to give up, y ...

  8. mysql 查看存储引擎的状态 show engine innodb status 详解

    首先,让我们来了解一下 SHOW INNODB STATUS 输出的基础,它打印了很多关于 InnoDB 内部性能相关的计数器.统计.事务处理信息等.在 MySQL 5 中,InnoDB 的性能统计结 ...

  9. Linux系统下设置Tomcat自启动

    需要将tomcat加入自启动队列中,则需要进行如下的操作: 以root用户登录系统: cd /etc/rc.d/init.d/ vi tomcat 文件内容参考如下: #!/bin/sh # # to ...

  10. 两个viewport的故事(第二部分)

    原文:http://www.quirksmode.org/mobile/viewports2.html 在这个迷你系列的文章里边我将会解释viewport,以及许多重要元素的宽度是如何工作的,比如&l ...