通常会疑惑,当使用不同的布局方式时,子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. *HDU 1398 母函数

    Square Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  2. 解决WARN: Timeout/setRollbackOnly of ACTIVE coordinator !的问题

    该问题是CoordinatorImp上面的一个定时器造成的,一个活动的session如果在一定的时间内没有执行完毕就会rollback,就算没有sql执行也会不断的进行. 可以参考该链接:https: ...

  3. PHP基础知识之foreach

    定义: foreach (array_expression as $value)------------循环时传递key foreach (array_expression as $key => ...

  4. windows和linux中搭建python集成开发环境IDE——如何设置多个python环境

    本系列分为两篇: 1.[转]windows和linux中搭建python集成开发环境IDE 2.[转]linux和windows下安装python集成开发环境及其python包 3.windows和l ...

  5. Eclipse自动补全设置

    如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为ecl ...

  6. python字符串的使用

    之前在网上看了关于python最基础的一些教程,看着都通俗易懂,但是在写的过程中却感觉还是很生涩.关于字符串的使用还是应该多写多练!如何将“teacher_id = 123 #老师ID”转换成字典或者 ...

  7. .NET面试题系列[14] - LINQ to SQL与IQueryable

    .NET面试题系列目录 名言警句 "理解IQueryable的最简单方式就是,把它看作一个查询,在执行的时候,将会生成结果序列." - Jon Skeet LINQ to Obje ...

  8. 体验 ASP.NET Core 1.1 中预编译 MVC Razor 视图

    这是从 ASP.NET Core 1.1 官方发布博文中学到的一招,可以在 dontet publish 时将 Razor 视图编译为 .dll 文件. 需要在 project.json 中添加如下配 ...

  9. [Voice communications] 看得到的音频流

    上文介绍了 Web Audio API 的相关知识,以及如何在你的 web 程序中引入 音频流,内容都是介绍性的,所以没有写太多 DEMO.本文重点讲解如何利用 Web Audio API 中的中间节 ...

  10. Orchard 微软CMS项目介绍

    我之前的项目中使用了Orchard, 它依据依赖注入的思想而做的模块化让我深深为之着迷,这里开始宣传一下这个架构. 包含的概念非常之多,我现在也不甚了解.Orchard就是自己想控制它改变它的话需要非 ...