Android入门笔记之源码解析一
<1>简介
今天下了很多源码,接下来几篇博客来分析这几个源码的架构。
首先是《左边按钮右边菜单》这个简单的源码。
<2>关键步骤
主Activity为SlidingActivity,它使用了自己定制的布局文件。
而在这个布局文件中采用相对布局。
SlidingMenu.java中主要有5个方法,setLeftView、setRightView、setCenterView主要是用来设置左、主、右界面的,其中setCenterView中有SlidingView对象,这个对象主要负责主界面。
RightFragment继承Fragment,采用布局R.layout.right,这个布局文件中有右边的所有控件。
LeftFragment继承Fragment,采用布局R.layoutleftt,这个布局文件中是左边的所有控件。
SampleListFragment继承ListFragment,设置了主界面中的按钮等空间,以及对实现了对左右界面调用的按钮。
SlidingActivity中使用了FragmentTransaction对左、中、右Fragment进行设置。
SlidingView这个类是本源码中最复杂的类,在这个类中实现了滑动。它继承了ViewGroup,mTouchSlop记录了触发移动事件的最短距离。
其中通过Scroller的startScroll方法来实现滑动。OnMeasure用来计算子空间
可获得的空间以及关于这个空间描述的元数据,然后用onLayout来限定子空间的相对于父布局的上下左右距离。
<3>知识点
1、LayoutParams相当于一个Layout的信息包,它封装了Layout的位置、高、宽等信息。假设在屏幕上一块区域是由一个Layout占领的,如果将一个View添加到一个Layout中,最好告诉Layout用户期望的布局方式,也就是将一个认可的layoutParams传递进去。
2、Fragment要点
Fragment作为Activity界面的一部分组成出现
可以在一个Activity中同时出现多个Fragment,并且,一个Fragment亦可在多个Activity中使用。
在Activity运行过程中,可以添加、移除或者替换Fragment(add()、remove()、replace())
Fragment可以响应自己的输入事件,并且有自己的生命周期,当然,它们的生命周期直接被其所属的宿主activity的生命周期影响。
3、LayoutInflater的使用,在实际开发种LayoutInflater这个类还是非常有用的,它的作用类似于 findViewById(),不同点是LayoutInflater是用来找layout下xml布局文件,并且实例化!而findViewById()是找具体xml下的具体 widget控件(如:Button,TextView等)。
4、android中 ViewConfiguration.get(getContext()).getScaledTouchSlop()获取的是什么值?作用是什么呢?
从文档中看,意思应该是触发移动事件的最短距离,如果小于这个距离就不触发移动控件,如viewpager就是用这个距离来判断用户是否翻页
5、onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,Android这么设计的想法也很好理解,由于ViewGroup会包含若干childView,因此需要能够统一监控各种touch事件的机会,因此纯粹的不能包含子view的控件是没有这个方法的,如LinearLayout就有,TextView就没有。
onInterceptTouchEvent()使用也很简单,如果在ViewGroup里覆写了该方法,那么就可以对各种touch事件加以拦截。但是如何拦截,是否所有的touch事件都需要拦截则是比较复杂的,touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。并且,针对down事件处理的返回值直接影响到后续move和up事件的接收和传递。
关于返回值的问题,基本规则很清楚,如果return true,那么表示该方法消费了此次事件,如果return false,那么表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。
6、invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时,调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。
7、Scroller这个类封装了滚动操作。滚动的持续时间可以通过构造函数传递,并且可以指定滚动动作的持续的最长时间。经过这段时间,滚动会自动定位到最终位置,并且通过computeScrollOffset()会得到的返回值为false,表明滚动动作已经结束。
publicvoid startScroll (int startX, int startY, int dx, int dy, intduration)
以提供的起始点和将要滑动的距离开始滚动。
参数
startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
dx 水平方向滑动的距离,正值会使滚动向左滚动
dy 垂直方向滑动的距离,正值会使滚动向上滚动
duration 滚动持续时间,以毫秒计。
8、VelocityTracker监控速度,用来追踪触摸事件(flinging事件和其他手势事件)的速率。用obtain()函数来获得类的实例,用addMovement(MotionEvent)函数将motion event加入到VelocityTracker类实例中,当你使用到速率时,使用computeCurrentVelocity(int)初始化速率的单位,并获得当前的事件的速率,然后使用getXVelocity() 或getXVelocity()获得横向和竖向的速率。
当用户触摸屏幕时将创建一个MotionEvent对象。MotionEvent包含关于发生触摸的位置和时间等细节信息。MotionEvent对象被传递到程序中合适的方法比如View对象的onTouchEvent()方法中。在这些方法中我们可以分析MotionEvent对象那个,以决定要执行的操作。
手指的初次触摸(ACTION_DOWN操作),滑动(ACTION_MOVE操作)和抬起(ACTION_UP)都会创建MotionEvent对象。
10、Android自定义控件步骤如下:
1. 选择一个父类,继承该父类(如View,ViewGroup)
2. 写一系列构造函数
3. 重写一系列on函数(如onMeasure,onLayout,onDraw,onSizeChanged),需要的才重写
4. 写一系列属性,一系列pulibc函数,向外界透露接口
这只是极其概括的总结而已。具体来说,从继承的父类不同,可分为以下三种
A.继承自View,TextView,ButtonView等,也就是没有子元素的类;
B.继承自ViewGroup,LinearLayout等,也就是写一个Layout
C.继承自AdapterView,ListView等,也就是写一个Adapter控件(没做研究)
这三种在写的时候都遵循上述的四个步骤,但侧重点各有不同,其中步骤1,2,4都是要有的。差异关键在步骤3。A一般侧重于重写onMeasure,onDraw函数,特别是onDraw函数;B一般侧重于重写onMeasure,onLayout函数,onDraw函数一般不用重写。其中onMeasure,onLayout函数里面的测量(measure)以及布局(layout)算法是重点也是难点。
<4>代码及解释
效果截图:
源代码地址:
http://download.csdn.net/detail/gmj4850/6300813