AndroidAutoLayout源码解析
一 概述
我在很久之前就开始使用这个库了,之前没有深究,后来觉得这个库有一些bug,就没有再使用,现在一些朋友想用这个库,觉得用着不错,所以现在就翻下源码看看,防止以后会出现奇怪的问题.
原项目github:https://github.com/hongyangAndroid/AndroidAutoLayout
使用介绍请看原项目README.md文件,本文章就不再介绍使用上的东西了
二 源码解析
这次分析采用从外到内的分析,从AutoLinearLayout这个类开始
2.1 AutoLinearLayout
/**
* 百分比线性布局
* Created by zhy on 15/6/30.
*/
public class AutoLinearLayout extends LinearLayout
{
//生成一个AutoLayoutHelper对象
private AutoLayoutHelper mHelper = new AutoLayoutHelper(this);
public AutoLinearLayout(Context context) {
super(context);
}
public AutoLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public AutoLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public AutoLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//编辑模式跳过
if (!isInEditMode())
//为子View应用百分比属性
mHelper.adjustChildren();
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
super.onLayout(changed, l, t, r, b);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs)
{ //生成自己的LayoutParams
return new AutoLinearLayout.LayoutParams(getContext(), attrs);
}
public static class LayoutParams extends LinearLayout.LayoutParams
implements AutoLayoutHelper.AutoLayoutParams
{
private AutoLayoutInfo mAutoLayoutInfo;
public LayoutParams(Context c, AttributeSet attrs)
{
super(c, attrs);
//初始化AutoLayoutInfo对象
mAutoLayoutInfo = AutoLayoutHelper.getAutoLayoutInfo(c, attrs);
}
@Override
public AutoLayoutInfo getAutoLayoutInfo()
{
return mAutoLayoutInfo;
}
public LayoutParams(int width, int height)
{
super(width, height);
}
public LayoutParams(ViewGroup.LayoutParams source)
{
super(source);
}
public LayoutParams(MarginLayoutParams source)
{
super(source);
}
}
}
从上面可以看出,貌似这个类没有做什么事情,在onMeasure方法的时候和LayoutParams的构造方法中
分别调用AutoLayoutHelper的adjustChildren方法和getAutoLayoutInfo方法,其实我们可以猜测出,adjustChildren就是给子View设置百分比属性的,getAutoLayoutInfo就是拿到百分比信息的关键方法,我们跟进去看
2.2 AutoLayoutHelper
- 构造方法
public AutoLayoutHelper(ViewGroup host)
{
mHost = host;
if (mAutoLayoutConifg == null)
{
initAutoLayoutConfig(host);
}
}
/**
* @param host
*/
private void initAutoLayoutConfig(ViewGroup host)
{
mAutoLayoutConifg = AutoLayoutConifg.getInstance();
mAutoLayoutConifg.init(host.getContext());
}
构造方法里面由构建了一个AutoLayoutConifg 对象,并且只是第一次才会初始化,而且看最后一行,这个AutoLayoutConifg的初始化也只是需要一个Context对象,并不是需要这个ViewGroup的属性什么的,单例的,
并且还需要Context对象,名字上又是Config结尾,那么一定是存储一些配置信息,事实上证明的确是这样的,看代码:
/**
* 全局的配置
* 设计稿 像素;屏幕尺寸;使用屏幕大小/除去状态栏高度
* Created by zhy on 15/11/18.
*/
public class AutoLayoutConifg
{
private static AutoLayoutConifg sIntance = new AutoLayoutConifg();
private static final String KEY_DESIGN_WIDTH = "design_width";
private static final String KEY_DESIGN_HEIGHT = "design_height";
//屏幕宽高
private int mScreenWidth;
private int mScreenHeight;
//设计稿宽高
private int mDesignWidth;
private int mDesignHeight;
//是否使用整个屏幕的宽高,默认false,除去状态栏
private boolean useDeviceSize;
private AutoLayoutConifg()
{
}
/**
* 是否配置了设计稿尺寸
*/
public void checkParams()
{
if (mDesignHeight <= 0 || mDesignWidth <= 0)
{
throw new RuntimeException(
"you must set " + KEY_DESIGN_WIDTH + " and " + KEY_DESIGN_HEIGHT + " in your manifest file.");
}
}
public AutoLayoutConifg useDeviceSize()
{
useDeviceSize = true;
return this;
}
public static AutoLayoutConifg getInstance()
{
return sIntance;
}
//....getset
public void init(Context context)
{
getMetaData(context);
//获取屏幕宽高
int[] screenSize = ScreenUtils.getScreenSize(context, useDeviceSize);
mScreenWidth = screenSize[0];
mScreenHeight = screenSize[1];
L.e(" screenWidth =" + mScreenWidth + " ,screenHeight = " + mScreenHeight);
}
//获取设计稿大小
private void getMetaData(Context context)
{
PackageManager packageManager = context.getPackageManager();
ApplicationInfo applicationInfo;
try
{
applicationInfo = packageManager.getApplicationInfo(context
.getPackageName(), PackageManager.GET_META_DATA);
if (applicationInfo != null && applicationInfo.metaData != null)
{
mDesignWidth = (int) applicationInfo.metaData.get(KEY_DESIGN_WIDTH);
mDesignHeight = (int) applicationInfo.metaData.get(KEY_DESIGN_HEIGHT);
}
} catch (PackageManager.NameNotFoundException e)
{
throw new RuntimeException(
"you must set " + KEY_DESIGN_WIDTH + " and " + KEY_DESIGN_HEIGHT + " in your manifest file.", e);
}
L.e(" designWidth =" + mDesignWidth + " , designHeight = " + mDesignHeight);
}
}
到这里咱们就了解 构造过程了,然后我们来看 完整的代码,注释有说明,
public class AutoLayoutHelper
{
private final ViewGroup mHost;
//属性attr,需要进行百分比换算的属性
private static final int[] LL = new int[]
{ //
android.R.attr.textSize,
android.R.attr.padding,//
android.R.attr.paddingLeft,//
android.R.attr.paddingTop,//
android.R.attr.paddingRight,//
android.R.attr.paddingBottom,//
android.R.attr.layout_width,//
android.R.attr.layout_height,//
android.R.attr.layout_margin,//
android.R.attr.layout_marginLeft,//
android.R.attr.layout_marginTop,//
android.R.attr.layout_marginRight,//
android.R.attr.layout_marginBottom,//
android.R.attr.maxWidth,//
android.R.attr.maxHeight,//
android.R.attr.minWidth,//
android.R.attr.minHeight,//16843072
};
//下标,会在getAutoLayoutInfo用到,根据下标生成 对应的属性
private static final int INDEX_TEXT_SIZE = 0;
private static final int INDEX_PADDING = 1;
private static final int INDEX_PADDING_LEFT = 2;
private static final int INDEX_PADDING_TOP = 3;
private static final int INDEX_PADDING_RIGHT = 4;
private static final int INDEX_PADDING_BOTTOM = 5;
private static final int INDEX_WIDTH = 6;
private static final int INDEX_HEIGHT = 7;
private static final int INDEX_MARGIN = 8;
private static final int INDEX_MARGIN_LEFT = 9;
private static final int INDEX_MARGIN_TOP = 10;
private static final int INDEX_MARGIN_RIGHT = 11;
private static final int INDEX_MARGIN_BOTTOM = 12;
private static final int INDEX_MAX_WIDTH = 13;
private static final int INDEX_MAX_HEIGHT = 14;
private static final int INDEX_MIN_WIDTH = 15;
private static final int INDEX_MIN_HEIGHT = 16;
/**
* move to other place?
*/
private static AutoLayoutConifg mAutoLayoutConifg;
public AutoLayoutHelper(ViewGroup host)
{
mHost = host;
if (mAutoLayoutConifg == null)
{
initAutoLayoutConfig(host);
}
}
/**
* @param host
*/
private void initAutoLayoutConfig(ViewGroup host)
{
mAutoLayoutConifg = AutoLayoutConifg.getInstance();
mAutoLayoutConifg.init(host.getContext());
}
/**
* 为ViewGroup的子Views应用百分比属性,本质上海市通过 AutoLayoutInfo
* 这里如果不懂LayoutParams和View以及ViewGroup关系的小伙伴可以去百度一下
*/
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);
}
}
}
}
/**
* 为View生成 AutoLayoutInfo
* @param context
* @param attrs
* @return
*/
public static AutoLayoutInfo getAutoLayoutInfo(Context context,
AttributeSet attrs)
{
AutoLayoutInfo info = new AutoLayoutInfo();
//获取app:layout_auto_basewidth="height|padding" 设置
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoLayout_Layout);
int baseWidth = a.getInt(R.styleable.AutoLayout_Layout_layout_auto_basewidth, 0);
int baseHeight = a.getInt(R.styleable.AutoLayout_Layout_layout_auto_baseheight, 0);
a.recycle();
//获取百分比换算的属性
TypedArray array = context.obtainStyledAttributes(attrs, LL);
int n = array.getIndexCount();
for (int i = 0; i < n; i++)
{
int index = array.getIndex(i);
// String val = array.getString(index);
// if (!isPxVal(val)) continue;
//如果不是px 跳过
if (!DimenUtils.isPxVal(array.peekValue(index))) continue;
int pxVal = 0;
try
{
pxVal = array.getDimensionPixelOffset(index, 0);
} catch (Exception ignore)//not dimension
{
continue;
}
//向AutoLayoutInfo中添加 不同的属性对象
switch (index)
{
case INDEX_TEXT_SIZE:
info.addAttr(new TextSizeAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_PADDING:
info.addAttr(new PaddingAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_PADDING_LEFT:
info.addAttr(new PaddingLeftAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_PADDING_TOP:
info.addAttr(new PaddingTopAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_PADDING_RIGHT:
info.addAttr(new PaddingRightAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_PADDING_BOTTOM:
info.addAttr(new PaddingBottomAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_WIDTH:
info.addAttr(new WidthAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_HEIGHT:
info.addAttr(new HeightAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_MARGIN:
info.addAttr(new MarginAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_MARGIN_LEFT:
info.addAttr(new MarginLeftAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_MARGIN_TOP:
info.addAttr(new MarginTopAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_MARGIN_RIGHT:
info.addAttr(new MarginRightAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_MARGIN_BOTTOM:
info.addAttr(new MarginBottomAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_MAX_WIDTH:
info.addAttr(new MaxWidthAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_MAX_HEIGHT:
info.addAttr(new MaxHeightAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_MIN_WIDTH:
info.addAttr(new MinWidthAttr(pxVal, baseWidth, baseHeight));
break;
case INDEX_MIN_HEIGHT:
info.addAttr(new MinHeightAttr(pxVal, baseWidth, baseHeight));
break;
}
}
array.recycle();
L.e(" getAutoLayoutInfo " + info.toString());
return info;
}
public interface AutoLayoutParams
{
AutoLayoutInfo getAutoLayoutInfo();
}
简单叙述一下,这个类就是帮助LayoutParams生成AutoLayoutInfo的,其实说白了就是拦截一些需要进行百分比换算的属性,然后存储到AutoLayoutInfo中,adjustChildren方法就是遍历子View,然后拿到子View的LayoutParams,再拿到子View的AutoLayoutInfo,AutoLayoutInfo里面维护者一个该View的百分比属性列表,然后进行属性遍历,应用
/**
* 其实这个类基本就是 存储的属性集合
*/
public class AutoLayoutInfo {
/**
* 存储属性
*/
private List<AutoAttr> autoAttrs = new ArrayList<>();
public void addAttr(AutoAttr autoAttr) {
autoAttrs.add(autoAttr);
}
/**
* 应用属性(调用属性自己的apply方法)
* @param view
*/
public void fillAttrs(View view) {
for (AutoAttr autoAttr : autoAttrs) {
autoAttr.apply(view);
}
}
/**
* 获取一个View的百分比属性
* 这里采用的是与运算判断 属性值是否存在
* {@link com.zhy.autolayout.utils.AutoUtils#auto(View, int, int)}
* @param view
* @param attrs
* @param base
* @return
*/
public static AutoLayoutInfo getAttrFromView(View view, int attrs, int base) {
ViewGroup.LayoutParams params = view.getLayoutParams();
if (params == null) return null;
AutoLayoutInfo autoLayoutInfo = new AutoLayoutInfo();
// width & height
if ((attrs & Attrs.WIDTH) != 0 && params.width > 0) {
autoLayoutInfo.addAttr(WidthAttr.generate(params.width, base));
}
if ((attrs & Attrs.HEIGHT) != 0 && params.height > 0) {
autoLayoutInfo.addAttr(HeightAttr.generate(params.height, base));
}
//margin
if (params instanceof ViewGroup.MarginLayoutParams) {
if ((attrs & Attrs.MARGIN) != 0) {
autoLayoutInfo.addAttr(MarginLeftAttr.generate(((ViewGroup.MarginLayoutParams) params).leftMargin, base));
autoLayoutInfo.addAttr(MarginTopAttr.generate(((ViewGroup.MarginLayoutParams) params).topMargin, base));
autoLayoutInfo.addAttr(MarginRightAttr.generate(((ViewGroup.MarginLayoutParams) params).rightMargin, base));
autoLayoutInfo.addAttr(MarginBottomAttr.generate(((ViewGroup.MarginLayoutParams) params).bottomMargin, base));
}
if ((attrs & Attrs.MARGIN_LEFT) != 0) {
autoLayoutInfo.addAttr(MarginLeftAttr.generate(((ViewGroup.MarginLayoutParams) params).leftMargin, base));
}
if ((attrs & Attrs.MARGIN_TOP) != 0) {
autoLayoutInfo.addAttr(MarginTopAttr.generate(((ViewGroup.MarginLayoutParams) params).topMargin, base));
}
if ((attrs & Attrs.MARGIN_RIGHT) != 0) {
autoLayoutInfo.addAttr(MarginRightAttr.generate(((ViewGroup.MarginLayoutParams) params).rightMargin, base));
}
if ((attrs & Attrs.MARGIN_BOTTOM) != 0) {
autoLayoutInfo.addAttr(MarginBottomAttr.generate(((ViewGroup.MarginLayoutParams) params).bottomMargin, base));
}
}
//padding
if ((attrs & Attrs.PADDING) != 0) {
autoLayoutInfo.addAttr(PaddingLeftAttr.generate(view.getPaddingLeft(), base));
autoLayoutInfo.addAttr(PaddingTopAttr.generate(view.getPaddingTop(), base));
autoLayoutInfo.addAttr(PaddingRightAttr.generate(view.getPaddingRight(), base));
autoLayoutInfo.addAttr(PaddingBottomAttr.generate(view.getPaddingBottom(), base));
}
if ((attrs & Attrs.PADDING_LEFT) != 0) {
autoLayoutInfo.addAttr(MarginLeftAttr.generate(view.getPaddingLeft(), base));
}
if ((attrs & Attrs.PADDING_TOP) != 0) {
autoLayoutInfo.addAttr(MarginTopAttr.generate(view.getPaddingTop(), base));
}
if ((attrs & Attrs.PADDING_RIGHT) != 0) {
autoLayoutInfo.addAttr(MarginRightAttr.generate(view.getPaddingRight(), base));
}
if ((attrs & Attrs.PADDING_BOTTOM) != 0) {
autoLayoutInfo.addAttr(MarginBottomAttr.generate(view.getPaddingBottom(), base));
}
//minWidth ,maxWidth , minHeight , maxHeight
if ((attrs & Attrs.MIN_WIDTH) != 0) {
autoLayoutInfo.addAttr(MinWidthAttr.generate(MinWidthAttr.getMinWidth(view), base));
}
if ((attrs & Attrs.MAX_WIDTH) != 0) {
autoLayoutInfo.addAttr(MaxWidthAttr.generate(MaxWidthAttr.getMaxWidth(view), base));
}
if ((attrs & Attrs.MIN_HEIGHT) != 0) {
autoLayoutInfo.addAttr(MinHeightAttr.generate(MinHeightAttr.getMinHeight(view), base));
}
if ((attrs & Attrs.MAX_HEIGHT) != 0) {
autoLayoutInfo.addAttr(MaxHeightAttr.generate(MaxHeightAttr.getMaxHeight(view), base));
}
//textsize
if (view instanceof TextView) {
if ((attrs & Attrs.TEXTSIZE) != 0) {
autoLayoutInfo.addAttr(TextSizeAttr.generate((int) ((TextView) view).getTextSize(), base));
}
}
return autoLayoutInfo;
}
@Override
public String toString() {
return "AutoLayoutInfo{" +
"autoAttrs=" + autoAttrs +
'}';
}
}
2.3 属性封装
有时候不得不说大神就是大神,属性对象的抽取,让扩展变得十分容易
属性对象有个超类 AutoAttr.java
/**
* 属性抽象类,由具体的属性实现,如何设置属性值,其实是px->百分比之后的px
*
* Created by zhy on 15/12/4.
*/
public abstract class AutoAttr
{
public static final int BASE_WIDTH = 1;
public static final int BASE_HEIGHT = 2;
public static final int BASE_DEFAULT = 3;
protected int pxVal;
protected int baseWidth;
protected int baseHeight;
public AutoAttr(int pxVal, int baseWidth, int baseHeight)
{
this.pxVal = pxVal;
this.baseWidth = baseWidth;
this.baseHeight = baseHeight;
}
/**
* 这里只是根据 baseHeight/baseWidth/userDefault 得到转换后的百分比px值
* @param view
*/
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);
}
protected int getPercentWidthSize()
{
return AutoUtils.getPercentWidthSizeBigger(pxVal);
}
protected int getPercentHeightSize()
{
return AutoUtils.getPercentHeightSizeBigger(pxVal);
}
/**
* 是否baseWidth
* @return
*/
protected boolean baseWidth()
{
return contains(baseWidth, attrVal());
}
/**
* 是否设置了以某个方向(width/height)像素作为参考
* @return
*/
protected boolean useDefault()
{
return !contains(baseHeight, attrVal()) && !contains(baseWidth, attrVal());
}
protected boolean contains(int baseVal, int flag)
{
return (baseVal & flag) != 0;
}
/**
* 对应的属性类别
* {@link Attrs}
*/
protected abstract int attrVal();
protected abstract boolean defaultBaseWidth();
/**
* 由具体的属性去设置 如何 设置值
* @param view
* @param val
*/
protected abstract void execute(View view, int val);
@Override
public String toString()
{
return "AutoAttr{" +
"pxVal=" + pxVal +
", baseWidth=" + baseWidth() +
", defaultBaseWidth=" + defaultBaseWidth() +
'}';
}
}
注释已经很清楚了
我们看一个常用属性的具体实现
/**
* Created by zhy on 15/12/5.
*/
public class HeightAttr extends AutoAttr
{
public HeightAttr(int pxVal, int baseWidth, int baseHeight)
{
super(pxVal, baseWidth, baseHeight);
}
@Override
protected int attrVal()
{
return Attrs.HEIGHT;
}
@Override
protected boolean defaultBaseWidth()
{
return false;
}
@Override
protected void execute(View view, int val)
{
ViewGroup.LayoutParams lp = view.getLayoutParams();
lp.height = val;
}
public static HeightAttr generate(int val, int baseFlag)
{
HeightAttr heightAttr = null;
switch (baseFlag)
{
case AutoAttr.BASE_WIDTH:
heightAttr = new HeightAttr(val, Attrs.HEIGHT, 0);
break;
case AutoAttr.BASE_HEIGHT:
heightAttr = new HeightAttr(val, 0, Attrs.HEIGHT);
break;
case AutoAttr.BASE_DEFAULT:
heightAttr = new HeightAttr(val, 0, 0);
break;
}
return heightAttr;
}
}
看起来是不是十分的简单,到这里我们的分析就到一段落了,下面我们试着来扩展一个ViewGroup
三 扩展
3.1 AutoConstraintLayout
package com.zhy.autolayout;
import android.content.Context;
import android.support.constraint.ConstraintLayout;
import android.util.AttributeSet;
import android.view.ViewGroup;
import com.zhy.autolayout.utils.AutoLayoutHelper;
/**
* Created by Administrator on 2017/10/29.
*/
public class AutoConstraintLayout extends ConstraintLayout {
AutoLayoutHelper helper=new AutoLayoutHelper(this);
public AutoConstraintLayout(Context context) {
super(context);
}
public AutoConstraintLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(!isInEditMode()){
helper.adjustChildren();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public static class LayoutParams extends ConstraintLayout.LayoutParams
implements AutoLayoutHelper.AutoLayoutParams{
AutoLayoutInfo mInfo;
public LayoutParams(ConstraintLayout.LayoutParams source) {
super(source);
}
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
mInfo=AutoLayoutHelper.getAutoLayoutInfo(c,attrs);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
@Override
public AutoLayoutInfo getAutoLayoutInfo() {
return mInfo;
}
}
}
然后在AutoLayoutActivity加入我们的拦截就好了
/**
* Created by zhy on 15/11/19.
*/
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";
//不在android.widget包下的需要拦截传入包名+类名
private static final String LAYOUT_CONSTRAINTLAYOUT = "android.support.constraint.ConstraintLayout";
@Override
public 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 (name.equals(LAYOUT_CONSTRAINTLAYOUT))
{
view = new AutoConstraintLayout(context, attrs);
}
if (view != null) return view;
return super.onCreateView(name, context, attrs);
}
}
ok.到这里就结束了,对于属性的扩展暂时没有想到什么例子,有时间可以去他的github逛逛,bug还是挺多的,而且这个库也不再维护了,所以,使用需谨慎,不过我既然选择了,含着泪也要坚持下去=.=