通常会疑惑,当使用不同的布局方式时,子view得布局属性就不太一样,比如当父布局是LinearLayout时,子view就能有效的使用它的一些布局属性如layout_weight、weightSum、等;当使用的是RelativeLayout时,其子view就能使用属于它的有效的属性;当然使用FrameLayout时,其属性集就少多了,也就常说的FrameLayout是最简单的布局方式了。

简单的说我们就是想要实现自定的属性可以再子view里面使用。

那么我们先来探索下ViewGroup中的LayoutParams吧。

viewGroup也是继承自view,主要是实现布局容器。

那么它有个内部基类LayoutParams。当然,这个viewGroup中的LayoutParams是所有的FrameLayout、RelativeLayout、、、的LayoutParams的基础类。当继承后,子layoutParams就拥有了父亲的所有的属性集合

这个类注释了,是用于view去告诉他们的父布局他们想咋滴,也就是说这个是子view和父布局的通讯方式吧

现在来看看ViewGroup中的addView的实现流程

public void addView(View child, int index) {
...
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
....
}
addView(child, index, params);
}
public void addView(View child, int index, LayoutParams params) {
...
addViewInner(child, index, params, false);
} private void addViewInner(View child, int index, LayoutParams params,
        boolean preventRequestLayout) {
  ... if (!checkLayoutParams(params)) {
params = generateLayoutParams(params);
} if (preventRequestLayout) {
child.mLayoutParams = params;
} else {
child.setLayoutParams(params);
}
}

通过整个addview的片段流程可以看到。

首先是checkLayoutParams,目的是检测这个参数是否为空,如果为空的话就给它生成一个普通的LayoutParams;

    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p != null;
}
  protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
   return p;
  }
  public LayoutParams generateLayoutParams(AttributeSet attrs) {
   return new LayoutParams(getContext(), attrs);
  }

可以得到前面两个方法protected主要是给子类去实现的,第三个方法是公开的。还是有些蹊跷的。所以要实现布局参数转换成自定义的参数,这三个方法就显得尤为重要了。

最后把这个params赋予子view,那么params是谁实现的,子view中的mLayoutParams就是什么类型的。这就是为什么我们在代码中改变view的LayoutParams时,把它转换成其他类型了就会报错的原因。

当然最为容易明白的还是先去研究下FrameLayout吧,因为这个类看下来不过300行代码。它其中的FrameLayout.LayoutParams中自定义了一个Gravity属性。

    public static class LayoutParams extends MarginLayoutParams {

        public int gravity = -1;

        public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs); TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout_Layout);
gravity = a.getInt(com.android.internal.R.styleable.FrameLayout_Layout_layout_gravity, -1);
a.recycle();
} public LayoutParams(int width, int height) {
super(width, height);
} public LayoutParams(int width, int height, int gravity) {
super(width, height);
this.gravity = gravity;
} ....
public LayoutParams(LayoutParams source) {
super(source); this.gravity = source.gravity;
}
}

  并且也实现了add流程中所提的三个方法:

    @Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new FrameLayout.LayoutParams(getContext(), attrs);
} @Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
} @Override
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}

最后FrameLayout才能在OnMeasure或者onLayout方法中对子view 进行大展身手:


研究完了原理后,我也实现了一下这个动作,也得到了一些对方法的使用猜测

代码如下:

/**
* 自定义测试viewgroup ,探究viewgroup中的addview的流程,已经子view中属性的获取
* Created by taofuxn on 2016/12/27.
*/ public class ViewPropertiesLayout extends ViewGroup { public ViewPropertiesLayout(Context context) {
super(context);
} public ViewPropertiesLayout(Context context, AttributeSet attrs) {
super(context, attrs);
} public ViewPropertiesLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); } @Override
protected boolean checkLayoutParams(LayoutParams p) {
boolean b = p instanceof LayoutParams;
Log.i("AAA","checkLayoutParams "+b);
return b;
} //没调用,当在xml布局中加载的时候不会调用这个方法
@Override
protected LayoutParams generateLayoutParams(LayoutParams p) {
Log.i("AAA","generateLayoutParams p");
return new MyLayoutParam(p);
} //这个方法是通过传入的属性集合生成相应的LayouParams .在viewgroup中是找不到调用的地方,我估计是xml解析的时候调用这个方法并赋予属性集合来生成params.
//因为通过addview的流程和这里的打印log可以看到是先调用这个方法生成了params,再去checklayout方法,最后再把转换的这个对象赋予给了子view的params
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
Log.i("AAA","generateLayoutParams attrs");
return new MyLayoutParam(getContext(),attrs);
} //onmeasure,在viewgroup中是没有对子view进行测量的处理的,所有在onlayout中是获取不到子view的宽高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) { for (int i = 0 ; i < getChildCount() ; i++){
View child = getChildAt(i);
child.layout(l,t,r,100);
//将子view的布局参数强行转换为本布局中自定义的LayoutParams,能这么做的原因是addview里面对子params进行了generate
MyLayoutParam lp = (MyLayoutParam) child.getLayoutParams();
child.setBackgroundColor(lp.color);
}
} public class MyLayoutParam extends LayoutParams{ private int color ; public MyLayoutParam(Context c, AttributeSet attrs) {
super(c, attrs);
TypedArray a = c.obtainStyledAttributes(attrs,R.styleable.custom);
color = a.getColor(R.styleable.custom_layout_bg, Color.CYAN);
a.recycle();
} public MyLayoutParam(int width, int height) {
super(width, height);
} public MyLayoutParam(MyLayoutParam source) {
super(source);
this.color = source.color ;
} public MyLayoutParam(LayoutParams source){
super(source);
}
}
}
 <?xml version="1.0" encoding="utf-8"?>
<com.example.administrator.viewproperties.ViewPropertiesLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_bg="@color/colorAccent"
android:textSize="20sp"
android:text="Hello World!" />
</com.example.administrator.viewproperties.ViewPropertiesLayout>

这个布局只在xml中应用,所有会调用public 的generateLayoutParams(atters)方法来给子view生成自定义的布局参数MyLayoutParam.那么他的执行顺序如下:

只有当子view的layoutparams不是MyLayoutParams的实例时才会调用,generateLayoutParma(p)这个方法生成一个属于自定义布局属性

这样的话我的这自定义布局就有了自己布局参数。感觉比自定义view的自定义属性高大上了很多。

我的探索可能有些错误。希望大神盛情指导

Android之探究viewGroup自定义子属性参数的获取流程的更多相关文章

  1. Android开发学习笔记-自定义TextView属性模版

    如果项目中有很多个控件使用的是同一种样式,则为了方便,可以将样式设置到系统中去,这样使用的时候会方便很多. 下面是自定义样式模版的方法. 1.在style.xml文件中添加自己要设置的样式内容 < ...

  2. Android开发UI之自定义视图属性

    Android框架中,所有自定义的view类都继承自View,也可以继承Button等view的子类 为了允许ADT能够与view交互,必须提供一个能够获取Context和作为属性的Attribute ...

  3. Android开发 AIDL使用自定义对象作参数或返回值

    http://www.pocketdigi.com/20121129/952.html 默认,AIDL支持对象作参数,但需要该对象实现Parcelable接口,且aidl文件应该是该类在同一包下,需要 ...

  4. 【Android - 进阶】之自定义视图浅析

    1       概述 Android自定义View / ViewGroup的步骤大致如下: 1) 自定义属性: 2) 选择和设置构造方法: 3) 重写onMeasure()方法: 4) 重写onDra ...

  5. [Android Pro] Android开发实践:自定义ViewGroup的onLayout()分析

    reference to : http://www.linuxidc.com/Linux/2014-12/110165.htm 前一篇文章主要讲了自定义View为什么要重载onMeasure()方法( ...

  6. Android ViewDragHelper完全解析 自定义ViewGroup神器

    Android ViewDragHelper完全解析 自定义ViewGroup神器   转载请标明出处: http://blog.csdn.net/lmj623565791/article/detai ...

  7. Android自定义XML属性以及遇到的命名空间的问题

    转载请注明出处:http://www.cnblogs.com/kross/p/3458068.html 最近在做一些UI,很蠢很蠢的重复写了很多代码,比如一个自定义的UI Tab,由一个ImageVi ...

  8. Android动画效果之自定义ViewGroup添加布局动画

    前言: 前面几篇文章介绍了补间动画.逐帧动画.属性动画,大部分都是针对View来实现的动画,那么该如何为了一个ViewGroup添加动画呢?今天结合自定义ViewGroup来学习一下布局动画.本文将通 ...

  9. android 自定义View属性

    在android开发过程中,用到系统的View时候可以通过XML来定义一些View的属性.比如ImageView:   android:src  和android:scaleType为ImageVie ...

随机推荐

  1. VS2012中丢失ArcGIS模板的解决方法

    VS2012中丢失ArcGIS模板的解决方法 由于ArcGIS10.0(for .NET)默认是用VS2010作为开发工具的,所以在先安装VS2012后装ArcGIS10.0 桌面版及ArcObjec ...

  2. Nodejs Promise的一点记录

    项目需要,看了点nodejs,其中比较难理解的就是Promise了,记录一下学习bluebird提供的Promise实现. Promise.promisifyAll(obj)方法 作用:把对象的方法属 ...

  3. PHP基础面试题

    1.PHP的意思? 答:PHP是一个基于服务端来创建动态网站的脚本语言,您可以用PHP和HTML生成网站主页 2.谈谈asp,php,jsp的优缺点? 答:ASP全名Active Server Pag ...

  4. jenkins配置源码管理git

    一.首先安装上来jenkins 二.下载安装jenkins的git插件:Git plugin 三.新建一个jenkins项目,选择构建一个自由风格的软件项目: 源码管理选择git,Repository ...

  5. SQL Server2014 哈希索引原理

    SQL Server2014 哈希索引原理 翻译自:http://www.sqlservercentral.com/blogs/sql-and-sql-only/2015/09/08/hekaton- ...

  6. LB 负载均衡的层次结构

    作为后端应用的开发者,我们经常开发.调试.测试完我们的应用并发布到生产环境,用户就可以直接访问到我们的应用了.但对于互联网应用,在你的应用和用户之间还隔着一层低调的或厚或薄的负载均衡层软件,它们不显山 ...

  7. Redis 集群的合纵与连横

    之前一篇写了关于 Redis 的性能,这篇就写写我认为比性能更重要的扩展性方面的主题. 如果再给我一次回到好几年前的机会,对于使用 Redis 我一开始就要好好考虑将来的扩展问题.就像我们做数据库分库 ...

  8. SEO:让搜索引擎对你的网站更有亲和力(译)

    人可以通过查看网站信息了解网站的内容,但是搜索引擎只对标签感兴趣,对内容的识别能力是很低的,如何让蜘蛛通过标签认识你的文章内容呢~ 原文网址:http://schema.org/docs/gs.htm ...

  9. 论HTML5 Audio 标签歌词同步的实现

    HTML5草案里面其实有原生的字幕标签(<track> Tag)的,但使用的是vtt格式的文件,非常规的字幕(.sub, .srt)或歌词文件(.lrc). 用法如下(代码来自W3Scho ...

  10. 关于如何在github上创建团队开发环境

    今天想写个如何在github上创建团队开发环境的博客.送给那些还不知道如何在github上创建团队开发环境的开发人员. 1.首先,当然你要有个github的账号.具体怎么注册我这里就不说了.可以上gi ...