重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
1.问题
成都创新互联公司是一家集网站建设,花山企业网站建设,花山品牌网站建设,网站定制,花山网站建设报价,网络营销,网络优化,花山网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。由于Android Framework源码很庞大,所以读源码必须带着问题来读!没有问题,创造问题再来读!否则很容易迷失在无数的方法与属性之中,最后无功而返。
那么,关于ViewPager有什么问题呢?
1). setOffsreenPageLimit()方法是如何实现页面缓存的?
2). 在布局文件中,ViewPager布局内部能否添加其他View?
3). 为什么ViewPager初始化时,显示了一个页面却不会触发onPageSelected回调?
问题肯定不止这三个,但是有这三个问题基本可以找到本次分析的重点了。读者朋友也可以自己先提出一些问题,再看下面的分析,看看是否可以从分析过程中找到答案。
2.从onMeasure()下手
ViewPager继承自ViewGroup,是Android Framework提供的一个控件,而Android系统显示控件的流程就是: Activity加载布局实例化所有控件 —> rootView遍历所以控件 —> 对需要重绘的控件执行测量,布局,绘制的操作。
而转化到某个控件来说,它的流程就是:构造方法 —> onMeasure —> onLayout —> onDraw
由于ViewPager的构造方法中只是初始化了一些与本文主题无关的属性就略过不讲,那么自然而然onMeasure方法就来到了我们眼前。
那么在onMeasure中ViewPager做了些什么呢?先把源码摆出来,我进行了一些删减。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //测量ViewPager自身大小 setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); final int measuredWidth = getMeasuredWidth(); // child的宽高,占满父控件 int childWidthSize = measuredWidth - getPaddingLeft() - getPaddingRight(); int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); //1.测量Decor int size = getChildCount(); for (int i = 0; i < size; ++i) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp != null && lp.isDecor) {//仅对Decor进行测量 //省略若干代码,主要负责对Decor控件的测量 ... } } } mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); // 2.从Adapter中获取childView mInLayout = true; populate(); mInLayout = false; // 3.测量非Decor的childView size = getChildCount(); for (int i = 0; i < size; ++i) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp == null || !lp.isDecor) { final int widthSpec = MeasureSpec.makeMeasureSpec( (int) (childWidthSize * lp.widthFactor), MeasureSpec.EXACTLY); child.measure(widthSpec, mChildHeightMeasureSpec); } } } }