谷歌的小弟自定义View篇笔记(杂)

来源:互联网 发布:pc蛋蛋计算器单双算法 编辑:程序博客网 时间:2024/06/18 22:00

1.View系统的宽高是由系统(其父容器)测量的,我们在使用的时候只需要调用getMeasuredWidth()和getMeasuredHeight()就可以了,但是如果这个View的Visibility为gone时,那么系统在measure阶段便不会测量宽和高

  for (int i = 0; i < count; ++i) {            final View child = getVirtualChildAt(i);            if (child == null) {                mTotalLength += measureNullChild(i);                continue;            }            if (child.getVisibility() == View.GONE) {               i += getChildrenSkipCount(child, i);               continue;            }         ................            measureChildBeforeLayout(child, i, widthMeasureSpec, 0,                        heightMeasureSpec, usedHeight);

2.在使用动画的时候需要注意animation的生命周期,比如说:

 private void collapse(final View view) {        int width = view.getMeasuredWidth();        final int height = view.getMeasuredHeight();        Animation animation = new Animation() {            @Override            protected void applyTransformation(float interpolatedTime, Transformation t) {                if(interpolatedTime==1) {                    view.setVisibility(View.GONE);                }else {                    view.getLayoutParams().height = (int) (height-(interpolatedTime*height));                    view.requestLayout();                }            }           @Override            public boolean willChangeBounds() {                return true;            }        };        animation.setDuration(duration); // 正确写法 view.startAnimation(animation);//错误写法   animation.start();    }

因为GC机制(当一个对象在系统中没有其索引的时候将会被清除),像这个函数,如果写成错误写法,那么动画在没有执行完的时候随着方法的完成而退出,从而达不到相应效果。只有像正确写法一样当方法结束之后animation仍然在进行才能达到相应效果。

3.
getmesuredWidth()是包含padding的。
child.layout(int l, int t, int r, int b),l等是包含padding的坐标。

4
一个细节:
首先看两点:
Button b的LayoutParam属性的类型为:ViewGroup.LayoutParam

public static class LayoutParams {

而LinearLayout的LayoutParam为LinearLayout.LayoutParam

public static class LayoutParams extends ViewGroup.MarginLayoutParams {

接下来看问题:
在LinearLayout的源码中有

  final View child = getVirtualChildAt(i);            if (child == null) {                mTotalLength += measureNullChild(i);                continue;            }            if (child.getVisibility() == View.GONE) {               i += getChildrenSkipCount(child, i);               continue;            }            if (hasDividerBeforeChildAt(i)) {                mTotalLength += mDividerHeight;            }            final LayoutParams lp = (LayoutParams) child.getLayoutParams();

注意看最后一行

final LayoutParams lp = (LayoutParams) child.getLayoutParams();

当我在main中写如下代码

  setContentView(R.layout.activity_main);        lin = (LinearLayout) findViewById(R.id.lin);        Button b = new Button(this);        lin.addView(b);

能够成功运行,并不报错。
为什么呢?
这是因为在LinearLayout.addView()时会将button b的ViewGroup.LayoutParam属性转换为LinearLayout.Layoutparam。那么在哪里转换呢?看代码,跟踪addView()其中会执行有这个方法:

 /**     * Set the layout parameters associated with this view. These supply     * parameters to the <i>parent</i> of this view specifying how it should be     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these     * correspond to the different subclasses of ViewGroup that are responsible     * for arranging their children.     *     * @param params The layout parameters for this view, cannot be null     */    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();    }

注释中说明了,这个方法会使不同的subclass Of ViewGroup负责他们的child的Layoutparam,也就是说,linearLayout会负责它的孩子使其layoutparam转换为LinearLayout.LayoutParam。
下面写一个代码验证一下:

 lin = (LinearLayout) findViewById(R.id.lin);        Button b = new Button(this);        Log.i("LayoutParam : ","before " + String.valueOf(b.getLayoutParams() instanceof LinearLayout.LayoutParams));        lin.addView(b);        Log.i("LayoutParam : ","after "+String.valueOf(b.getLayoutParams() instanceof LinearLayout.LayoutParams));

运行结构如下:
这里写图片描述
可见,分析正确。

原创粉丝点击