Android中屏幕适配框架AutoLayout源码解读
来源:互联网 发布:win8 mac修改器 编辑:程序博客网 时间:2024/06/05 10:20
个人推荐
随着越来越多的开发者使用hongyang大神的AutoLayout框架进行Android屏幕适配,我就去看了看这套框架做了哪些东西,结果发现AutoLayout框架本身代码量很少,但是思路值得我们开发者学习.
源码博客地址
http://blog.csdn.net/lmj623565791/article/details/49990941/
当我们做屏幕适配的时候,我们适配的是什么
在Android中做屏幕适配的时候,我们适配的其实是各种控件的大小,间距等参数,所以适配的时候最重要的是拿到当前页面的各种尺寸参数,而我们知道,Android中Activity在创建的时候,会走onCreateView回调,表示接下来就要进行view的创建步骤,方法中传过来三个参数,一个是name,一个是context,还有一个是Attributeset.写过自定义控件的朋友都知道,任何一个view的构造参数中都有一个参数是Attributeset,这个Attributeset顾名思义,就是Attribute + set,即当前页面的各种属性参数集合,利用这个对象我们就可以构建当前页面的各种布局间距,完美进行屏幕适配.AutoLayoutActivity代码如下:
public class AutoLayoutActivity extends AppCompatActivity
{
private static final String LAYOUT_LINEARLAYOUT = “LinearLayout”;
private static final String LAYOUT_FRAMELAYOUT = “FrameLayout”;
private static final String LAYOUT_RELATIVELAYOUT = “RelativeLayout”;
@Overridepublic View onCreateView(String name, Context context, AttributeSet attrs){ View view = null; if (name.equals(LAYOUT_FRAMELAYOUT)) { view = new AutoFrameLayout(context, attrs); } if (name.equals(LAYOUT_LINEARLAYOUT)) { view = new AutoLinearLayout(context, attrs); } if (name.equals(LAYOUT_RELATIVELAYOUT)) { view = new AutoRelativeLayout(context, attrs); } if (view != null) return view; return super.onCreateView(name, context, attrs);}
}
在使用框架的时候,我们的Activity需要继承自AutoLayoutActivity,而这个Autoactivity内部,只有一个onCreateView方法,是不是非常简单,这个方法就是拿到当前页面的Attributeset,传给对应的Layout布局,这个Layout布局就是我们页面的根布局,有LinearLayout,RelativeLayout,FrameLayout三种.所以当我们自己的Activity在走到onCreateView的时候,会调用AutoLayout的该方法,从而拿到的布局从我们自己的LinearLayout,RelativeLayout,FrameLayout变成了AutoLinearLayout ,AutoRelativeLayout, AutoFrameLayout.接下来我们看看AutoLinearLayout,AutoRelativeLayout,AutoFrameLayout这些布局里面都干了些什么事呢,以AutoRelativeLayout为例,代码如下:
public class AutoRelativeLayout extends RelativeLayout
{
private final AutoLayoutHelper mHelper = new AutoLayoutHelper(this);
public AutoRelativeLayout(Context context){ super(context);}public AutoRelativeLayout(Context context, AttributeSet attrs){ super(context, attrs);}public AutoRelativeLayout(Context context, AttributeSet attrs, int defStyle){ super(context, attrs, defStyle);}@TargetApi(Build.VERSION_CODES.LOLLIPOP)public AutoRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes);}@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs){ return new LayoutParams(getContext(), attrs);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ if (!isInEditMode()) mHelper.adjustChildren(); super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom){ super.onLayout(changed, left, top, right, bottom);}public static class LayoutParams extends RelativeLayout.LayoutParams implements AutoLayoutHelper.AutoLayoutParams{ private AutoLayoutInfo mAutoLayoutInfo; public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); mAutoLayoutInfo = AutoLayoutHelper.getAutoLayoutInfo(c, attrs); } public LayoutParams(int width, int height) { super(width, height); } public LayoutParams(ViewGroup.LayoutParams source) { super(source); } public LayoutParams(MarginLayoutParams source) { super(source); } @Override public AutoLayoutInfo getAutoLayoutInfo() { return mAutoLayoutInfo; }}
}
我们可以看到,AutoRelativeLayout继承自RelativeLayout,同时构造了内部类LayoutParams也是继承自RelativeLayout的LayoutParams.我们先来看下LayoutParams的改动,因为我们知道LayoutParams表示当前Layout的布局参数.在构造函数里面,我们通过AutoLayoutHelper的getautolayoutinfo方法,生成了AutolayoutInfo,这个AutolayoutInfo代表的就是当前Layout的参数信息.再来看看AutoRelativeLayout的改动,可以看到改动就两个地方,一个是generateLayoutParams这个方法,返回的是他自己的内部类LayoutParams,另一个是在onmeasure方法中,调用了AutoLayoutHelper的adjustchildren方法,而这个方法是启动AutoLayout布局适配的方法,从以上步骤也可以看出,框架是通过一个AutoLayoutHelper类帮助我们去协调各个模块的运作.接下来我们将沿着adjustchildren这个方法一步一步揭晓适配的秘密.
public void adjustChildren()
{
AutoLayoutConifg.getInstance().checkParams();
for (int i = 0, n = mHost.getChildCount(); i < n; i++) { View view = mHost.getChildAt(i); ViewGroup.LayoutParams params = view.getLayoutParams(); if (params instanceof AutoLayoutParams) { AutoLayoutInfo info = ((AutoLayoutParams) params).getAutoLayoutInfo(); if (info != null) { info.fillAttrs(view); } } }}
可以看到,首先通过checkparams检查清单文件是否配置metadata,没有配置的话将会报错.然后,拿到LayoutParams中的AutoLayoutInfo,就是我们之前看到过的.AutoLayoutInfo有一个fillattrs方法,看看这个方法做了什么:
public void fillAttrs(View view)
{
for (AutoAttr autoAttr : autoAttrs)
{
autoAttr.apply(view);
}
}
再看看Autoattr 和 apply方法是什么:
public void apply(View view)
{
boolean log = view.getTag() != null && view.getTag().toString().equals("auto"); if (log) { L.e(" pxVal = " + pxVal + " ," + this.getClass().getSimpleName()); } int val; if (useDefault()) { val = defaultBaseWidth() ? getPercentWidthSize() : getPercentHeightSize(); if (log) { L.e(" useDefault val= " + val); } } else if (baseWidth()) { val = getPercentWidthSize(); if (log) { L.e(" baseWidth val= " + val); } } else { val = getPercentHeightSize(); if (log) { L.e(" baseHeight val= " + val); } } if (val > 0) val = Math.max(val, 1);//for very thin divider execute(view, val);}
原来,autoattr是一个抽象基类,子类是各种实现他的attr,比如heightattr,padingattr,widthattr等等,apply方法就是在基类中把参数的值先做屏幕适配转换,再传给子类,子类通过execute方法把这个值跟自己的layoutparams中的变量具体去赋值,这样做子类就不用一一去做屏幕适配转换.
至此,autolayout内部适配流程大致捋清.通过对LayoutParams中的各种attr的值,根据屏幕去做适配,从而完成整个Aativity的适配,其中AutoLayoutHelper负责各个类之间的协调工作,生成当前LayoutInfo参数信息,比如启动Layout适配.
联系作者
如果对Android适配有问题欢迎联系作者
QQ 562759989 微信 haikelei
- Android中屏幕适配框架AutoLayout源码解读
- android屏幕适配autolayout
- 【框架】屏幕适配Autolayout的运用
- Android autolayout万能的屏幕适配
- 屏幕适配Autolayout
- 屏幕适配、Autoresizing、Autolayout
- AutoLayout——Android屏幕自动适配
- AutoLayout——Android屏幕自动适配
- Android屏幕适配 autolayout(不错的选择)
- AutoLayout——Android屏幕自动适配
- Android AutoLayout全优屏幕适配方式
- iOS autolayout 页面布局 屏幕适配
- 屏幕适配-----Autoresizing和AutoLayout
- 拾遗系列(三)屏幕适配:Autolayout
- 全方位解读Android多媒体框架源码
- 全方位解读Android多媒体框架源码
- 全方位解读Android多媒体框架源码
- android AChartEnginee讲解之源码框架解读
- 微信小程序实战篇-分类页面制作
- Pig Latin
- 关于Qml ComboBox的问题
- 局域网创建CentOS的yum源服务器
- SpringMVC框架学习总结
- Android中屏幕适配框架AutoLayout源码解读
- iOS Security汇总
- 学习笔记——system(DIR)
- C#程序中:如何启用进程、结束进程、查找进程
- java的运行过程和平台的独立性
- CodeM美团点评编程大赛初赛A轮
- Qt5使用内存泄露检测工具—VLD
- Hibernate 二级缓存配置
- JDK笔记-IO流读写