[Android实例] Scroll原理-附ScrollView源码分析 (转载)

想象一下你拿着放大镜贴很近的看一副巨大的清明上河图, 那放大镜里可以看到的内容是很有限的,
而随着放大镜的上下左右移动,就可以看到不同的内容了

android中手机屏幕就相当于这个放大镜, 而看到的内容是画在一个无限大的画布上~
画的内容有限, 而手机屏幕可以看到的东西更有限~ 但是背景画布是无限的

如果把放大镜的移动比作scroll操作,那么可以理解,这个scroll的距离是无限制的~
只不过scroll到有图的地方才能看到内容

参考ScrollView理解, 当child内容过长时,有一部分内容是"看不到"的,相当于"在屏幕之外",
而随着我们的拖动滚动,则慢慢看到剩下的内容,相当于我们拿着放大镜向下移动~

而代码中的这个scroll方法系统提供了两个:
scrollTo和scrollBy

源码如下

/**

* 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 if (mScrollX != x || mScrollY != y) {

int oldX = mScrollX;

int oldY = mScrollY;

mScrollX = x;

mScrollY = y;

invalidateParentCaches();

onScrollChanged( mScrollX, mScrollY, oldX, oldY);

if (!awakenScrollBars()) {

postInvalidateOnAnimation();

}

}

}

/**

* 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) {

}

mScrollX 表示离视图起始位置的x水平方向的偏移量

mScrollY表示离视图起始位置的y垂直方向的偏移量

可以通过getScrollX() 和getScrollY()方法分别获得

两个方法的区别就是to参数是绝对值,by是相对于当前滚动到的位置的增量值

比如:
mScrollX=100, mScrollY=100
scrollTo(20, 20) -> mScrollX=20, mScrollY=20;
scrollBy(20, 20) -> mScrollX=120,mScrollY=120;

注意:
这里mScrollX和mScrollY的值是偏移量,是相对于视图起始位置的偏移量~
所以任何view,无论布局是怎么样的,只要是刚初始化未经过scroll的,偏移量都是0~
即mScrollX/Y是相对于自己初始位置的偏移量,而不是相对于其容器的位置坐标

-----------------------------------------------------------------------------

下面是就ScrollView的源码拆开了的分析,并加入了一些补充扩展,
主要内容包括
1.最基本的随着touch滚动的效果
2.fling效果,即滑动后抬起手后继续关心滚动的效果
3.over scroll效果,即拖动超出边界的处理

上述123系统都有提供相关实现方法,但是ScrollView默认只有1,2的实现效果,
over scroll需要我们自行进行一定处理后才可以看到~
下面就ScrollView的源码进行分析,且提供三个自定义ScrollView(难度依次递进)实现上面的三种效果,已打包成demo

后面源码分析时,系统是乱七八糟直接写一起时,分析的被比较细也比较乱,
demo中三个自定义ScrollView相当于按照难度梯度抽取出来的,
即view2是在view1基础上修改添加功能的,view3是在view2基础上修改添加功能的
可以从demo下手帮助理解其中原理
-----------------------------------------------------------------------------

scroll相当于一个拖动,我们可以用scrollTo/By控制其滚动到某个位置,
那一般ScrollView控件这种都是随着我们的手势生效的,内部原理是如何的呢~

下面来研究下系统ScrollView控件源码里面的具体实现~
系统考虑的东西比较多,研究起来较为复杂,所以先就核心部分拆开一点点研究~

手的拖动肯定是跟touch即触摸事件挂钩了~直接定位到ScrollView中的该方法
(onTouchEvent干什么用的就不扫盲了)

首先是ACTION_DOWN

case MotionEvent.ACTION_DOWN: {

mIsBeingDragged = getChildCount() != 0;

if (!mIsBeingDragged) {

return false;

}

/*

* If being flinged and user touches, stop the fling. isFinished

* will be false if being flinged.

*/

if (!mScroller.isFinished()) {

mScroller.abortAnimation();

if (mFlingStrictSpan != null) {

mFlingStrictSpan.finish();

mFlingStrictSpan = null;

}

}

// Remember where the motion event started

mLastMotionY = ev.getY();

mActivePointerId = ev.getPointerId(0);

break;

}

有三段代码,第二三段带注释,下面是介绍:

1.ScrollView没有child则不做处理,这个不解释,都没child滚个蛋啊
如果有child则设置标志位mIsBeingDragged即"开始拖动"(看英文就可以理解了)

2.看注释理解~如果还在滑动用户触碰了屏幕,则立刻停止滑动
mScroller是一个OverScroller对象,是处理滚动的,
类介绍里提到这个功能和Scroller类差不多,大部分情况下可以替代之,
区别可以简单的理解为OverScroller允许超出边界,后面会介绍Scroller类~
至于mFlingStrictSpan无视之

3.看注释理解~记住点击的位置
scrollerView,处理垂直滚动,这里就只记录Y坐标了
mActivePointerId是用来处理多点触控时的稳定性的,这里先记住作用就行了

-----------------------------------------------------------------------------

然后是ACTION_MOVE,这个是重点,随着move我们希望控件也能随着我们的手的拖动滚动到所需位置

case MotionEvent.ACTION_MOVE:

if (mIsBeingDragged ) {

// Scroll to follow the motion event

final int activePointerIndex = ev.findPointerIndex(mActivePointerId);

final float y = ev.getY(activePointerIndex);

final int deltaY = ( int) ( mLastMotionY - y);

mLastMotionY = y;

final int oldX = mScrollX;

final int oldY = mScrollY;

final int range = getScrollRange();

final int overscrollMode = getOverScrollMode();

final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||

(overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);

if (overScrollBy(0, deltaY, 0, mScrollY,

0, range, 0, mOverscrollDistance, true)) {

// Break our velocity if we hit a scroll barrier.

mVelocityTracker.clear();

}

onScrollChanged( mScrollX, mScrollY , oldX, oldY);

if (canOverscroll) {

final int pulledToY = oldY + deltaY;

if (pulledToY < 0) {

mEdgeGlowTop.onPull((float) deltaY / getHeight());

if (! mEdgeGlowBottom.isFinished()) {

mEdgeGlowBottom.onRelease();

}

} else if (pulledToY > range) {

mEdgeGlowBottom.onPull((float) deltaY / getHeight());

if (! mEdgeGlowTop.isFinished()) {

mEdgeGlowTop.onRelease();

}

}

if ( mEdgeGlowTop != null

&& (! mEdgeGlowTop.isFinished() || !mEdgeGlowBottom.isFinished())) {

invalidate();

}

}

}

break;

系统注释还是很良心的,一般以功能点为单位注释,这里还是根据注释去看
分两段:随着触摸事件的滚动,还有顶部底部边缘阴影的处理
阴影处理的先忽视

这里的触摸点获取不是直接event.getY,而是通过下面两句代码获取的

final int activePointerIndex = ev.findPointerIndex( mActivePointerId);

final float y = ev.getY(activePointerIndex);

上面已经介绍过了mActivityPointerId的保证多点触碰稳定性的作用,
包括onTouchEvent里面的ACTION_POINTER_DOWN/UP也是为了处理多点情况的,
为了不发散太多就不细介绍了(其实我也不是研究太透彻)
知道这样处理能防止多点触控的干扰,可以稳定获取到我们需要的触摸的y坐标就行了

根据现在的触摸坐标y和上次位置的y坐标mLastMotionY算出差值,即这次移动的距离deltaY
最后以获取到的这些数据进行滚动操作~
ScrollView中在这里使用的是overScrollBy方法,该方法是其父类view的方法,定位过去看下
其实如果要简单处理的话直接掉scrollTo方法就可以了~参见demo中MyScrollView1
如果觉得ScrollView里逻辑无法理解,那就可以先把上面demo的view1研究懂以后再继续下文

注意,scroll由于是没有限制的,即可以滚动到任何位置,显然不符合我们的需要,
所以我们要限制滚动范围,只在有内容的绘制部分滚动

由于ScrollView只是纵向Y轴上滚动,所以只限定y上滚动范围即可,
如下图示,红框是scrollview,蓝框是child,滚动范围应该是箭头所示部分~
即0 到 child.height-scrollview,height

而demo里view1中也添加了这么一段(demo是横向滚动)

// Clamp values if at the limits and record

final int left = 0;

final int right = getScrollRangeX();

// 防止滚动超出边界

if(scrollX > right) {

scrollX = right;

} else if(scrollX < left) {

scrollX = left;

}

-----------------------------------------------------------------------------

因为scrollView考虑的比较多,所以处理麻烦点,按照源码追踪到view中的overScrollerBy方法

/**

* Scroll the view with standard behavior for scrolling beyond the normal

* content boundaries. Views that call this method should override

* {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the

* results of an over -scroll operation.

*

* Views can use this method to handle any touch or fling -based scrolling.

*

* @param deltaX Change in X in pixels

* @param deltaY Change in Y in pixels

* @param scrollX Current X scroll value in pixels before applying deltaX

* @param scrollY Current Y scroll value in pixels before applying deltaY

* @param scrollRangeX Maximum content scroll range along the X axis

* @param scrollRangeY Maximum content scroll range along the Y axis

* @param maxOverScrollX Number of pixels to overscroll by in either direction

*          along the X axis.

* @param maxOverScrollY Number of pixels to overscroll by in either direction

*          along the Y axis.

* @param isTouchEvent true if this scroll operation is the result of a touch event.

* @return true if scrolling was clamped to an over -scroll boundary along either

*          axis, false otherwise.

*/

@SuppressWarnings({"UnusedParameters"})

protected boolean overScrollBy( int deltaX, int deltaY,

int scrollX, int scrollY,

int scrollRangeX, int scrollRangeY,

int maxOverScrollX, int maxOverScrollY,

boolean isTouchEvent) {

final int overScrollMode = mOverScrollMode;

final boolean canScrollHorizontal =

final boolean canScrollVertical =

computeVerticalScrollRange() > computeVerticalScrollExtent();

final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||

(overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);

final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||

(overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);

int newScrollX = scrollX + deltaX;

if (!overScrollHorizontal) {

maxOverScrollX = 0;

}

int newScrollY = scrollY + deltaY;

if (!overScrollVertical) {

maxOverScrollY = 0;

}

// Clamp values if at the limits and record

final int left = -maxOverScrollX;

final int right = maxOverScrollX + scrollRangeX;

final int top = -maxOverScrollY;

final int bottom = maxOverScrollY + scrollRangeY;

boolean clampedX = false;

if (newScrollX > right) {

newScrollX = right;

clampedX = true;

} else if (newScrollX < left) {

newScrollX = left;

clampedX = true;

}

boolean clampedY = false;

if (newScrollY > bottom) {

newScrollY = bottom;

clampedY = true;

} else if (newScrollY < top) {

newScrollY = top;

clampedY = true;

}

onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);

return clampedX || clampedY;

}

方法的作用:
总结起来就是计算over scroll时scrollX/Y的值~ 并将其记录在onOverScrolled方法里

参数意义:
前8个分两组,1357是针对x轴的,2468则是y轴的,这里scrollView只纵向滚动,所以只处理y轴
比较难理解的是后俩参数

1.scrollRange
是某方向上滚动的范围,可以参考上面的图片,只不过要把padding部分考虑进去
下面是系统获取范围的方法

private int int scrollRange = 0;

if (getChildCount() > 0) {

View child = getChildAt(0);

scrollRange = Math. max(0,

child.getHeight() - (getHeight() - mPaddingBottom - mPaddingTop));

}

return scrollRange;

}

不难理解,最大距离的情况就是childview移动到了最顶部,然后滑动到最底部,上面这个方法算的就是这个最大距离

2.maxOverScroll

为越界滚动最大距离,即在之前范围的基础上再加上这个越界最大距离~

ScrollView在这里设置的是系统默认值0

比如以前纵向的滚动范围是0~300,那如果这个值设为50,则最终over scroll的范围就是-50~350,方法内算法如下

// Clamp values if at the limits and record

final int left = -maxOverScrollX;

final int right = maxOverScrollX + scrollRangeX;

final int top = -maxOverScrollY;

final int bottom = maxOverScrollY + scrollRangeY;

top=-maxOverScrollY ~ bottom=maxOverScrollY+scrollRangY

带入我们假设的值,那就是0~300, 注意,这个300是Y坐标300~

这里假设我们的maxOverScrollY不是系统默认的Y而是 50,
那虽然滚动范围不变还是500-200=300~ 但是实际上可以滚动的范围是大于300的~
效果类似于ios那种,listview到达顶部以后继续拖还可以移动~ 也可以脑补下拉刷新listview的效果

在拖到顶部以后,还可以overScroll继续拖动,
而继续拖动的最大距离就是maxOverScrollY,如图左边小箭头的长度
底部同理

那整个边界范围就变了~
从原来的y = 0 ~ 300 变成了
-maxOverScrollY ~ scrollRangeY + maxOverScrollY
看图很好理解,就变成了
y = -50 ~ 350
横向同理

下面代码就是判断了
如果现在滚动的新坐标超过了over的极限值,则将极限值赋值给新坐标~
简单而言就是滑动到极限越界距离以后就卡住他,让他"划不动",
这里英文clamp为"钳住"的意思,英语好的可以帮助快速理解~

x/y方向达到极限距离的同时会分别记录下一个标志符,最后|作为返回值,
即任何一个方向上有划不动的情况时则返回true,否则false

最后通过onOverScrolled暴露给子类,这里view里面的onOverScrolled方法是empty不做任何处理的~里面注释也是卖萌,"我是故意的~"

上面一大串overScrollBy方法源码分析这里总结一下
该方法就相当于在scrollTo/By的基础上添加了对overScroll情况的处理, 但父类view中只处理数据,没有实际的scroll操作,父类view处理完数据后将其记录在onOverScrolled方法中,
子类继承onOverScrolled方法再根据得到的数据scrollTo/By处理即可~

举个简单的例子帮助理解,比如这个view相当于一个大加工厂,
那overScrollBy方法相当于一个加工车间,比如是做串串的(竹签上有海带素鸡一类的那种)- -
把原材料加工好成串串后,直接就丢到一个储藏的仓库里~不做任何其他操作

而继承view的子类ScrollView就相当于来拿货的销售商,来了以后不管生产过程,直接去这个储藏的仓库里,
把货拿出来然后该卖的卖,该自己吃的自己吃,该二次加工的二次加工~进行具体的操作~
这个仓库就可以理解为onOverScrolled方法~

可以理解为一个监听,比如scrollview提供一个onScroll监听,父类只用该方法记录数据,
而子类复写之就可以获取到所需数据,如当前滚动到位置,根据需要处理了

回到源码ScrollView的onOverScrolled方法
其实简单处理的话直接在onOverScrolled里面scrollTo就可以了,但是系统考虑到scrollbar,animating scroll等情况所以处理的比较复杂
如果下面这段代码无法理解,可以先跳过本段,直接到ACTION_UP部分,
可以在看完后面OverScroll实现(demo中view3)介绍,研究懂后再回头看这段代码

@Override

protected void onOverScrolled( int scrollX, int scrollY,

boolean clampedX, boolean // Treat animating scrolls differently; see #computeScroll() for why.

if (!mScroller.isFinished()) {

mScrollX = scrollX;

mScrollY = scrollY;

invalidateParentIfNeeded();

if ( mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange());

}

} else {

super.scrollTo(scrollX, scrollY);

}

awakenScrollBars();

}

这里是if分成两部分的,注释说明为,对于还在进行中的滚动要区别处理,

区分处理的原因可以参考computeScroll()方法

@Override

public void if (mScroller.computeScrollOffset()) {

// This is called at drawing time by ViewGroup.  We don‘t want to

// re-show the scrollbars at this point, which scrollTo will do,

// so we replicate most of scrollTo here.

//

//         It‘s a little odd to call onScrollChanged from inside the drawing.

//

//         It is, except when you remember that computeScroll() is used to

//         animate scrolling. So unless we want to defer the onScrollChanged()

//         until the end of the animated scrolling, we don‘t really have a

//         choice here.

//

//         I agree.  The alternative, which I think would be worse, is to post

//         something and tell the subclasses later.  This is bad because there

//         will be a window where mScrollX/Y is different from what the app

//         thinks it is.

//

int oldX = mScrollX;

int oldY = mScrollY;

int x = mScroller.getCurrX();

int y = mScroller.getCurrY();

if (oldX != x || oldY != y) {

final int range = getScrollRange();

final int overscrollMode = getOverScrollMode();

final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||

(overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);

overScrollBy(x - oldX, y - oldY, oldX, oldY, 0, range,

0, mOverflingDistance, false);

onScrollChanged(mScrollX, mScrollY, oldX, oldY);

if (canOverscroll) {

if (y < 0 && oldY >= 0) {

mEdgeGlowTop.onAbsorb(( int) mScroller.getCurrVelocity());

} else if (y > range && oldY <= range) {

mEdgeGlowBottom.onAbsorb(( int) mScroller.getCurrVelocity());

}

}

}

awakenScrollBars();

// Keep on drawing until the animation has finished.

postInvalidate();

} else {

if (mFlingStrictSpan != null) {

mFlingStrictSpan.finish();

mFlingStrictSpan = null;

}

}

}

注释翻译下

这个方法会在viewgroup draw绘制的时候调用,

我们不想在这个时候再次显示scrollbar滚动条,这个scrollTo方法会处理,

所以我们在这里复制了scrollTo方法的大部分内容

下面代码和onTouch里的MOVE中代码一样(上文有引用过这部分代码)

回到onOverScrolled方法中,结合看意思就是

如果mScroller.isFinished滚动动画已经结束了,那正常scrollTo方法滚动

如果未结束,那调用一个不会显示scrollBar滚动条的scrollTo方法

(上面注释说过,处理原因就是为了方法滚动条再次显示,

且代码大部分复制scrollTo,即相当于一个不显示滚动条的scrollTo方法)

且如果未滚动完成,还要加个判断, 如果是滚动到不能再滚动了,即clampedY=true

则进行回弹操作mScroller.springBack

再次引用上面车间加工串串的例子加深理解

demo中自己处理就相当于,卖串串的自己加工串串(计算数据), 直接卖(scrollTo)~

系统的ScrollView呢,就是把串串交给加工车间view精加工一下(overScrollBy),

最后从onOverScrolled仓库中取加工好的串串再去卖(scrollTo)

-----------------------------------------------------------------------------

回到onTouch,之后是ACTION_UP操作

按照平常滚屏的习惯,UP抬起时,一般还会有一个惯性继续滚动一段距离~

(这里我们把滚动叫做scroll,这个有惯性的甩~抛~的动作叫做fling~)

首先用VelocityTracket获取y向的速度,根据速度去处理fling

(按照通常思维,速度越快,甩的越远~)

case MotionEvent. ACTION_UP:

if ( mIsBeingDragged) {

final VelocityTracker velocityTracker = mVelocityTracker;

velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

int initialVelocity = ( int) velocityTracker.getYVelocity(mActivePointerId );

if (getChildCount() > 0) {

if ((Math. abs(initialVelocity) > mMinimumVelocity)) {

} else {

if ( mScroller.springBack(mScrollX, mScrollY, 0, 0, 0,

getScrollRange())) {

invalidate();

}

}

}

mActivePointerId = INVALID_POINTER;

endDrag();

}

break;

这里有判断,当速度超过一个最小阀值的时候,就视为一个fling~则调用fling()方法

否则视为普通的scroll,那判断这个时候是否需要回弹操作,有的话invalidate刷新页面

下面是核心方法~甩~

/**

* Fling the scroll view

*

* @param velocityY The initial velocity in the Y direction. Positive

*                  numbers mean that the finger/cursor is moving down the screen,

*                  which means we want to scroll towards the top.

*/

public void fling(int velocityY) {

if (getChildCount() > 0) {

int height = getHeight() - mPaddingBottom - mPaddingTop;

int bottom = getChildAt(0).getHeight();

mScroller.fling(mScrollX, mScrollY, 0, velocityY, 0, 0, 0,

Math. max(0, bottom - height), 0, height/2);

final boolean movingDown = velocityY > 0;

if (mFlingStrictSpan == null) {

mFlingStrictSpan = StrictMode.enterCriticalSpan("ScrollView-fling" );

}

invalidate();

}

}

诸如这类"高级"的滚动,都使用了Scroller类处理~详见

http://www.eoeandroid.com/thread-553376-1-1.html

fling里面实际上调用的是mScroller的fling方法,我们定位到OverScroller类该方法

内部原理太多,这里只解释方法的作用和参数的意义了

方法作用:根据一个fling手势开始fling行为~移动的距离取决于fling的初始速度~

参数传进来的值为

mScrollX, mScrollY, 0, velocityY, 0, 0, 0, Math. max(0, bottom - height), 0, height/2

一共10个参数分两组,奇数为x轴处理,偶为y

2 4 6 8 10五个参数分别介绍(x向的同理)

startY 开始甩的y坐标 - 值为当前滚动位置mScrollY

velocityY y轴上的速度 - 值为velocityTracker计算出来的速度值

minY y轴上可以到的最小坐标 - 值为0

maxY y抽上可以到的最大坐标 - 值为child的高度减去viewgroup除padding以外的高度~

(这个值和之前计算的scrollRangeY一样,只不过那个是长度,这个是坐标~

想理解可以参考之前的图片)

overY 越界滑动的范围 - 值为viewgroup除padding高度以外的一半

fling里面的具体速度距离的算法...略过~

插一句

如果是没有over的scroll或者fling,那直接用Scroller类就可以了,系统考虑的比较全,
所以ScrollView里面用的是OverScroller类~

同样的fling方法Scroller就没有最后两个和over相关的参数

下面是一个不考虑over情况用Scroller实现fling效果的demo

-----------------------------------------------------------------------------

回到over scroll的处理

上面提到,系统ScrollView源码中是有处理over scroll的,只不过ScrollView中的对应参数overDistance为0,造成了ScrollView没有over scroll的效果

这里我们可以自己尝试实现下~

其实非常简单,demo12中ouTouch的MOVE里面的scrollTo方法改成和ScrollView一样的,

即利用父类view的overScrollBy方法转一圈~

只不过调用overScrollBy方法时,记得传入的maxOverScrollX/Y不能是0,不然就没意义了

这样拖动的时候就可以over scroll了~

既然有over scroll那我们肯定需要回弹效果,即松手后自动滚动回来~

前面说过这种高级的要用Scroller类,而牵涉到over的,自然就用到OverScroller类了~

fling方法和Scroller一样,多一个overX方法,即fling时over scroll的最大距离,

demo里我设定成了maxOverScrollX的一半,可以自行调整

fling的回弹是自动的,但我们fling行为是有个最小速度判断的,因而在UP时还要加个,

没有fling时,如果开始了一个回弹效果,则刷新视图~

以下是over scroll的优化效果

over scroll从体验上来说,我们希望是有一个阻塞的效果的,

即如果普通状态下,手指移动100距离,那view也滚动100距离,

但是over scroll时,手指移动100距离,view滚动距离应该按比例降低~

这样一种效果才更加"真实"

此外demo中还在onOverScrolled回调用添加了一个拉断效果,

即当拖动到over scroll的极限距离时,虽然没有UP但是强制进行回弹操作,

相当于模拟了一个"拉断"的效果

-----------------------------------------------------------------------------

缺陷, 没有考虑measure,所以MyScrollView中子类size有点问题,demo中暂时写死了child宽度,

measure的原理介绍会在后面有时间整理出~希望大家持续关注

照例,回复可以免积分下载~

链接:http://pan.baidu.com/s/1dDCL4nZ 密码:idth

时间: 2024-11-06 21:06:25

[Android实例] Scroll原理-附ScrollView源码分析 (转载)的相关文章

Android应用层View绘制流程与源码分析

Android应用层View绘制流程与源码分析 1 背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原理,记不记得最终分析结果就是下面的关系: 看见没有,如上图中id为content的内容就是整个View树的结构,所以对每个具体View对象的操作,其实就是个递归的实现. 前面<Android触摸屏事件派发机制详解与源码分析一(View篇)>文章的3-1

SpringMVC关于json、xml自动转换的原理研究[附带源码分析 --转

SpringMVC关于json.xml自动转换的原理研究[附带源码分析] 原文地址:http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-convert.html 目录 前言 现象 源码分析 实例讲解 关于配置 总结 参考资料 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:http://www.cnblogs.com/fangjian0423/p/springMVC-in

Android的软件包管理服务PackageManagerService源码分析

Android系统下的apk程序都是通过名为PackageManagerService的包管理服务来管理的.PacketManagerService是安卓系统的一个重要服务,由SystemServer启动,主要实现apk程序包的解析,安装,更新,移动,卸载等服务.不管是系统apk(/system/app),还是我们手工安装上去的,系统所有的apk都是由其管理的. 以android 4.0.4的源码为例,android4.0.4/frameworks/base/services/java/com/

Android应用程序启动过程——Launcher源码分析

当我们在Launcher界面单击一个应用程序图标时就会启动一个程序,那这一个过程究竟发生了些哪样呢?让我们跟踪Launcher源码来分析一下吧. 先上流程图: step1.追踪Launcher  从源码中我们可以发现Launcher其实也是一个程序,它继承于Activity.找到该文件中的onCreate()方法,代码片段如下: protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceSta

Android 中View的绘制机制源码分析 三

到目前为止,measure过程已经讲解完了,今天开始我们就来学习layout过程,不过在学习layout过程之前,大家有没有发现我换了编辑器,哈哈,终于下定决心从Html编辑器切换为markdown编辑器,这里之所以使用"下定决心"这个词,是因为毕竟Html编辑器使用好几年了,很多习惯都已经养成了,要改变多年的习惯确实不易,相信这也是还有很多人坚持使用Html编辑器的原因.这也反应了一个现象,当人对某一事物非常熟悉时,一旦出现了新的事物想取代老的事物时,人们都有一种抵触的情绪,做技术的

Android 中View的绘制机制源码分析 二

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/46842891 本篇文章接着上篇文章的内容来继续讨论View的绘制机制,上篇文章中我们主要讲解了View的measure过程,今天我们就来学习ViewGroup的measure过程,由于ViewGroup只是一个抽象类,所以我们需要以一个具体的布局来分析measure过程,正如我上篇文章说的,我打算使用LinearLayout为例讲解measure过程,如果你还没有读过上篇文章,那么建议你先

Android视图View绘制流程与源码分析(全)

来源:[工匠若水 http://blog.csdn.net/yanbober] 1 背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原理,记不记得最终分析结果就是下面的关系: 看见没有,如上图中id为content的内容就是整个View树的结构,所以对每个具体View对象的操作,其实就是个递归的实现. 前面<Android触摸屏事件派发机制详解与源码分析一(

Android图片加载库Picasso源码分析

图片加载在Android开发中是非常重要,好的图片加载库也比比皆是.ImageLoader.Picasso.Glide.Fresco均是优秀的图片加载库. 以上提到的几种图片加载库各有特色.用法与比较,网上已经很多了. 出于学习的角度,个人认为从Picasso入手较好.代码量小,同时API优美,很适合我们学习. 今天笔者就Picasso的源码进行分析,抛出一些图片加载的技术细节供园友参考. PS:建议园友先大致看一下源码. 我们对图片加载的要求 1.加载速度要快 2.资源消耗要低 3.加载图片不

SpringMVC关于json、xml自动转换的原理研究[附带源码分析]

本文讨论SpringMVC关于json.xml自动转换的原理. 实现这个功能只需要三个配置 1.springmvc配置文件 dispatcher-servlet.xml中的关键配置如下 <mvc:resources location="/static/" mapping="/static/**"/> <!-- 配置包扫描器 --> <context:component-scan base-package="com.winner