今天说说自定义控件,稍微偏底层一点的东西。今天的主要任务是自己完全写代码,写一个ViewGroup,实现一个类似ViewPager这样的一个功能。

   大家自定义View肯定写过,不过估计写的也不多。等大家上班以后,全都是自定义的View和ViewGroup。

   实现这样滑动的效果可以使用ViewPager。其实像ViewPager,ListView,SlidingMenu或者popupWindow,他们都有个共同点,就是界面上的View(大小)是不变的,只是位置在变,而只要是位置在变,通通都是使用的一样的技术。它们的底层原理都是一样的。但是这些组件,不管你学多少,永远都学不完。一开始学这些组件的时候,是一种知识的积累,但学多了以后我们就要回头想一想,它们是怎么实现的。如果我们自己来做,我们怎么去实现。等到上班的时候,那些系统的组件有可能无法实现我们的要求。

   

   其中一个技术点是scrollTo和scrollBy这两个方法,以下面的Demo为例。

   下面的控制按钮能控制上面View的移动。

   scrollBy这个方法是View的一个方法,是一个底层的方法,所以我们在Android中看到的所有的元素都有这样的方法。这个方法是干嘛的呢,scrollBy方法使得这个View整体的移动一个距离,比如有一个viewGroup里面有很多子View,如果要想改变这些子View的位置的话,那么有几种方法呢?两种,一种是改变这个View真实的的位置,但是这样改的话,如果ViewGroup里面的子View有很多,就要把每一个子View都要做改动,像listView就是这样实现的;而如果我想将ViewGroup里面的子View整体移动,这样就不需要将每个子View都做改变了,而是可以将他们做一个整体的偏移。对ViewGroup做scrollBy,就可以使ViewGroup中的所有子View都实现偏移。

   scrollBy的源码:(由当前位置再移动(x,y)的偏移量)

/**

* 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

*/

public void scrollBy(int x, int y) {

scrollTo(mScrollX + x, mScrollY + y);

  }

  scrollTo的源码:(移动到(x,y)位置)

/**

* 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;

invalidateParentCaches();

onScrollChanged(mScrollX, mScrollY, oldX, oldY);

if (!awakenScrollBars()) {

postInvalidateOnAnimation();

}

}

   }

  这两个方法,偏移的是View中的内容,而View自己的位置是不变的。

  

  BaiHeTest例子:(包含歌词例子)

  是一个侧边栏滑动菜单,工作中一定会去实现这样的一个效果。有的可能想到使用SlidingMenu这个开源框架,有的可能想到使用Animation。

  Animation动画实现的方式,Animation的特点是只改变我们看到的效果,而不改变其真实的物理属性,所以例子中Button的物理位置是不改变的。Animation只能看做是动画,而不能做出交互式的效果。因此,使用Animation不能(准确)实现侧边栏菜单。

  scrollTo和scrollBy方法实现:

  帧布局,上面包含按钮,下面是侧边菜单。直接上面布局scrollTo到一个位置(-200,0),(负值往右偏移),使用一个flag判断是否已经打开了。这样可以实现。如果想看起来有个类似动画的效果,可以使用下面两句代替scrollTo:

   scroller.startScroll(layout2.getScrollX(), layout2.getScrollY(), -200, 0);

   handler.sendEmptyMessage(FLUSH);

  这时候就需要看看Scroller这个类,它就类似一个计算中心,通常是用Scroller对象记录或计算View滚动的位置,当我们点击Button的时候,Scroller调用startScroll方法,这个方法中的四个参数分别是基准点位置及偏移量,这个方法里只是记录了这些参数,

public void startScroll(int scrollX, int scrollY, int distanceX, int distanceY) {

startX = scrollX;

startY = scrollY;

this.distanceX = distanceX;

this.distanceY = distanceY;

isFinish = false;

startTime = SystemClock.uptimeMillis();

   }

  然后再发送handler信息,handler里先判断scroller.computeScrollOffset(),这个返回true时表示还在移动,

/**

* 计算偏移量,这个方法得出当前执行到哪个位置了

* @return true 还在移动  false:移动已经停止,duration = 1000l

*/

public boolean computeScrollOffset() {

if (isFinish) {

return false;

}

long timePassed = SystemClock.uptimeMillis()- startTime;

if (timePassed < duration) {

currentX = (int) (startX + distanceX  * timePassed / duration);

currentY = (int) (startY + distanceY * timePassed/ duration );

System.out.println("currentX:::" + currentX);

} else if (timePassed >= duration) {

currentX = startX + distanceX;

currentY = startY + distanceY;

isFinish = true;

}

return true;

   }

  

  定义的handler:

private Handler handler = new Handler(){

@Override

public void handleMessage(Message msg) {

if(msg.what == FLUSH){

if(scroller.computeScrollOffset()){

layout2.scrollTo(scroller.getCurrX(), 0);

handler.sendEmptyMessage(FLUSH);

}

}

}

};

源自梦想 自定义ViewGroup的整理_1的更多相关文章

  1. 源自梦想 自定义ViewGroup的整理_2

    Android项目: 1.准备资源图片.图片放到hdip里和mdip里对想过的影响:对于320*480的模拟器,默认去mdip里去找图片资源,拿过来的图片可以直接用,清晰度不变.要是所要找的图片在hd ...

  2. Kotlin 第一弹:自定义 ViewGroup 实现流式标签控件

    古人学问无遗力, 少壮工夫老始成.纸上得来终觉浅, 绝知此事要躬行. – 陆游 <冬夜读书示子聿> 上周 Google I/O 大会的召开,宣布了 Kotlin 语言正式成为了官方开发语言 ...

  3. Android 自定义ViewGroup,实现侧方位滑动菜单

    侧方位滑动菜单 1.现在adnroid流行的应用当中很多都是用的侧方位滑动菜单如图:

  4. 简单的例子了解自定义ViewGroup(一)

    在Android中,控件可以分为ViewGroup控件与View控件.自定义View控件,我之前的文章已经说过.这次我们主要说一下自定义ViewGroup控件.ViewGroup是作为父控件可以包含多 ...

  5. Android动画效果之自定义ViewGroup添加布局动画

    前言: 前面几篇文章介绍了补间动画.逐帧动画.属性动画,大部分都是针对View来实现的动画,那么该如何为了一个ViewGroup添加动画呢?今天结合自定义ViewGroup来学习一下布局动画.本文将通 ...

  6. Android自定义控件之自定义ViewGroup实现标签云

    前言: 前面几篇讲了自定义控件绘制原理Android自定义控件之基本原理(一),自定义属性Android自定义控件之自定义属性(二),自定义组合控件Android自定义控件之自定义组合控件(三),常言 ...

  7. Android自定义ViewGroup

    视图分类就两类,View和ViewGroup.ViewGroup是View的子类,ViewGroup可以包含所有的View(包括ViewGroup),View只能自我描绘,不能包含其他View. 然而 ...

  8. [Android Pro] Android开发实践:自定义ViewGroup的onLayout()分析

    reference to : http://www.linuxidc.com/Linux/2014-12/110165.htm 前一篇文章主要讲了自定义View为什么要重载onMeasure()方法( ...

  9. android 手把手教您自定义ViewGroup(一)

    1.概述 在写代码之前,我必须得问几个问题: 1.ViewGroup的职责是啥? ViewGroup相当于一个放置View的容器,并且我们在写布局xml的时候,会告诉容器(凡是以layout为开头的属 ...

随机推荐

  1. I/O小总结

    //判断不存在就创建目录 ,然后拷贝文件 DirectoryInfo di = null; if (!Directory.Exists(n.Attribute("value").V ...

  2. HDU 5702 Solving Order (水题,排序)

    题意:给定几种不同的颜色和它的权值,按它的权值排序. 析:排序. 代码如下: #include <cstdio> #include <string> #include < ...

  3. maven3实战之maven使用入门(使用archetype生成项目骨架)

    maven3实战之maven使用入门(使用archetype生成项目骨架) ---------- maven提供了archetype以帮助我们快速勾勒出项目骨架.以Hello World为例,我们使用 ...

  4. VS2010 远程调试

    1.在客户端电脑建一个账户,账户名和密码和调试端的账户密码一样 2.在客户端电脑进入 管理工具-本地安全策略-本地策略-安全选项 网络访问:本地账户的共享和安全模式”,改为“经典-本地用户以自己的身份 ...

  5. github命令

    git push origin master //把本地源码库push到Github上 git pull origin master //从Github上pull到本地源码库

  6. iOS 消息推送实现 APNS

    本文只是记录一下如何在自己的电脑上配置APNS推送环境,其它的如推送的原理,流程什么的这里就不写了. 一. 去Apple 开发者中心,创建App ID.注意App ID不能使用通配符.并注意添加Pus ...

  7. CSS规则整理

    一. 善用css缩写规则 /*注意上.右.下.左的书写顺序*/1. 关于边距(4边):1px 2px 3px 4px (上.右.下.左)1px 2px 3px (省略的左等于右)1px 2px (省略 ...

  8. 关于Java中的程序,进程和线程的详解...

    程序:一段静态的代码,一组指令的有序集合,它本身没有任何运行的含义,它只是一个静态的实体,是应用软件执行的蓝本. 进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个 ...

  9. mysql主从同步单个表实验记录

    问题的提出: 在CRM管理系统与运营基础数据平台之间需要有数据表进行交换,说是交换,其实是单向的,就是CRM里面的一些数据需要实时同步到运营基础数据平台中. 解决方案: A.采用时间戳的办法进行代码开 ...

  10. 你应该知道的JavaScript中NaN的秘密

    NaN,不是一个数字,是一种特殊的值来代表不可表示的值,使用typeof或其他任何与之比较的处理方式,‘NaN’则会引起一些混乱, 一些操作会导致NaN值的产生.这里有些例子: Math.sqrt(- ...