您的位置:首页 > 移动开发 > Android开发

自定义View需注意问题

2016-05-24 08:38 375 查看
1 ViewGroup类中包含两个静态内部类:LayoutParams 和MarginLayoutParams

public abstract class ViewGroup extends View implements ViewParent, ViewManager {
...省略
public static class LayoutParams {
...省略
}
public static class MarginLayoutParams extends   ViewGroup.LayoutParams {
...省略
}
...省略
}


这两个布局属性是提供给被它所包含的子View使用的。如

layout_width,layout_height等等。自定义ViewGroup如果要提供自定义的布局需要继承MarginLayoutParams 来重写其中的布局方法,比如LinearLayout ,如下

<LinearLayout
android:layout_width="150dp"
android:layout_height="150dp" >
<!-- 使用自定义view -->
<com.stone.view.CustomView1
android:layout_width="wrap_content"
android:layout_height="fill_parent"
custom:score="60%"
custom:rotation="-45"
custom:color="#3f00ff00" />
</LinearLayout>


上述自定义View中的布局参数(6,7两行)是包裹他的布局所定义的,如果自定义View被一个自定义的ViewGroup包裹,那么ViewGroup需要定义自己的布局参数。

LinearLayout的布局类源码如下:

public static class LayoutParams extends ViewGroup.MarginLayoutParams {

@ViewDebug.ExportedProperty(category = "layout")
public float weight;

/**
* Gravity for the view associated with these LayoutParams.
*
* @see android.view.Gravity
*/
@ViewDebug.ExportedProperty(category = "layout", mapping = {
@ViewDebug.IntToString(from =  -1,                       to = "NONE"),
@ViewDebug.IntToString(from = Gravity.NO_GRAVITY,        to = "NONE"),
@ViewDebug.IntToString(from = Gravity.TOP,               to = "TOP"),
@ViewDebug.IntToString(from = Gravity.BOTTOM,            to = "BOTTOM"),
@ViewDebug.IntToString(from = Gravity.LEFT,              to = "LEFT"),
@ViewDebug.IntToString(from = Gravity.RIGHT,             to = "RIGHT"),
@ViewDebug.IntToString(from = Gravity.START,            to = "START"),
@ViewDebug.IntToString(from = Gravity.END,             to = "END"),
@ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL,   to = "CENTER_VERTICAL"),
@ViewDebug.IntToString(from = Gravity.FILL_VERTICAL,     to = "FILL_VERTICAL"),
@ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
@ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL,   to = "FILL_HORIZONTAL"),
@ViewDebug.IntToString(from = Gravity.CENTER,            to = "CENTER"),
@ViewDebug.IntToString(from = Gravity.FILL,              to = "FILL")
})
public int gravity = -1;

/**
* {@inheritDoc}
*/
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
TypedArray a =
c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.LinearLayout_Layout);

weight = a.getFloat(com.android.internal.R.styleable.LinearLayout_Layout_layout_weight, 0);
gravity = a.getInt(com.android.internal.R.styleable.LinearLayout_Layout_layout_gravity, -1);

a.recycle();
}

/**
* {@inheritDoc}
*/
public LayoutParams(int width, int height) {
super(width, height);
weight = 0;
}

public LayoutParams(int width, int height, float weight) {
super(width, height);
this.weight = weight;
}

/**
* {@inheritDoc}
*/
public LayoutParams(ViewGroup.LayoutParams p) {
super(p);
}

/**
* {@inheritDoc}
*/
public LayoutParams(ViewGroup.MarginLayoutParams source) {
super(source);
}

public LayoutParams(LayoutParams source) {
super(source);

this.weight = source.weight;
this.gravity = source.gravity;
}

@Override
public String debug(String output) {
return output + "LinearLayout.LayoutParams={width=" + sizeToString(width) +
", height=" + sizeToString(height) + " weight=" + weight +  "}";
}
}


public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
...
/**
* The layout parameters associated with this view and used by the parent
* {@link android.view.ViewGroup} to determine how this view should be
* laid out.
* {@hide}
*/
//每个View均拥有LayoutParams属性,View添加到ViewGroup时的布局参数
protected ViewGroup.LayoutParams mLayoutParams;

public void setLayoutParams(ViewGroup.LayoutParams params) {
if (params == null) {
throw new NullPointerException("Layout parameters cannot be null");
}
mLayoutParams = params;
resolveLayoutParams();
if (mParent instanceof ViewGroup) {
((ViewGroup) mParent).onSetLayoutParams(this, params);
}
requestLayout();
}
...
}


2 invalidate(),requestLayout()以及requestFocus()均为View类中的方法,这三个方法最终会调用到ViewRoot中的schedulTraversale()方法,该函数然后发起一个异步消息,消息处理中调用performTraverser()方法对整个View进行遍历。

参考Android中View绘制流程以及invalidate()等相关方法分析

3 layout_weight属性详解(源码解读)

android中layout_weight的理解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android