自定义框架(一)

本文详细介绍了Android中自定义View的方法及流程,并通过实例演示了如何定义和使用自定义属性来增强View的功能。从构造方法到绘图过程,再到自定义属性的声明与获取,全面解析自定义View的开发技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 基础知识
  • 自定义属性

基础知识

public class TestView extends View {

    public TestView(Context context) {
        super(context);
        Log.d("mDebug", "TestView context");
    }



    public TestView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        Log.d("mDebug", "TestView context,attrs,defStyle attrs="+attrs.getAttributeValue(0));
    }



    public TestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Log.d("mDebug", "TestView context, attrs="+attrs.getAttributeValue(0));
    }



    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        Log.d("mDebug", "onDraw");
    }

    @Override
    protected void onFinishInflate() {
        // TODO Auto-generated method stub
        super.onFinishInflate();
        Log.d("mDebug", "onFinishInflate");
    }



    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        // TODO Auto-generated method stub
        super.onSizeChanged(w, h, oldw, oldh);
        Log.d("mDebug", "onSizeChanged,w="+w+",h="+h+",oldw="+oldw+",oldh="+oldh);
    }

}
10-16 16:32:24.241 31212-31212/com.hp.myframework D/mDebug: TestView context, attrs=100.0dip
10-16 16:32:24.241 31212-31212/com.hp.myframework D/mDebug: onFinishInflate
10-16 16:32:24.319 31212-31212/com.hp.myframework D/mDebug: onMeasure:1073742124    1073742124
10-16 16:32:24.343 31212-31212/com.hp.myframework D/mDebug: onSizeChanged,w=300,h=300,oldw=0,oldh=0
10-16 16:32:24.368 31212-31212/com.hp.myframework D/mDebug: onDraw
10-16 16:32:24.503 31212-31212/com.hp.myframework D/mDebug: onMeasure:1073742124    1073742124
10-16 16:32:24.504 31212-31212/com.hp.myframework D/mDebug: onDraw

构造方法->onFinishInflate()->onMeasure->onSizeChanged->onDraw

自定义 View的常用方法:
onFinishInflate() 当View中所有的子控件 均被映射成xml后触发
onMeasure(int, int) 确定所有子元素的大小
onLayout(boolean, int, int, int, int) 当View分配所有的子元素的大小和位置时触发
onSizeChanged(int, int, int, int) 当view的大小发生变化时触发
onDraw(Canvas) view渲染内容的细节
onKeyDown(int, KeyEvent) 有按键按下后触发
onKeyUp(int, KeyEvent) 有按键按下后弹起时触发
onTrackballEvent(MotionEvent) 轨迹球事件
onTouchEvent(MotionEvent) 触屏事件
onFocusChanged(boolean, int, Rect) 当View获取 或失去焦点时触发
onWindowFocusChanged(boolean) 当窗口包含的view获取或失去焦点时触发
onAttachedToWindow() 当view被附着到一个窗口时触发
onDetachedFromWindow() 当view离开附着的窗口时触发,提示该方法和 onAttachedToWindow() 是相反的。
onWindowVisibilityChanged(int) 当窗口中包含的可见的view发生变化时触发

如何自定义属性

1.在res/values中的attrs.xml中自定义属性。

<resources>
    <!--  ===================自定义属性==========================          -->
    <declare-styleable name="MyTextView">
        <attr name="text_color" format="boolean"/>
    </declare-styleable>

</resources>

2.在xml布局中引用

    <com.hp.myframework.MyView.MyTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="显示的内容"
        app:text_color="true"
        android:gravity="center_horizontal"
        />

3.在自定义的view里面获取xml中使用的属性

  public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 拿到我自定义的属性
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
        mcolor = a.getBoolean(R.styleable.MyTextView_text_color, false);
        a.recycle();
    }

4.解析属性并作出效果

@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (mcolor) {
            mPaint = getPaint();
            mViewWidth = getMeasuredWidth();
            /**
             * LinearGradient也称作线性渲染,LinearGradient的作用是实现某一区域内颜色的线性渐变效果
             * public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)
             * x0:表示渐变的起始点x坐标
             * y0:表示渐变的起始点y坐标
             * x1:表示渐变的终点x坐标
             * y1:表示渐变的终点y坐标
             * color0:表示渐变开始颜色
             * color1:表示渐变结束颜色
             * tile:表示平铺方式;
             *      CLAMP的作用是如果渲染器超出原始边界范围,则会复制边缘颜色对超出范围的区域进行着色
             *      REPEAT的作用是在横向和纵向上以平铺的形式重复渲染位图
             *      MIRROR的作用是在横向和纵向上以镜像的方式重复渲染位图
             *
             * public LinearGradient (float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile);
             * colors:表示渐变的颜色数组
             * positions:用来指定颜色数组的相对位置;通常,参数positions设为null,表示颜色数组以斜坡线的形式均匀分布
             */
            mLinearGradient = new LinearGradient(
                    0,
                    0,
                    mViewWidth,
                    0,
                    new int[]{Color.BLUE, 0xffffffff, Color.BLUE},
                    null, Shader.TileMode.CLAMP
            );
            mPaint.setShader(mLinearGradient);
            mGradientMatrix = new Matrix();
        }


    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mGradientMatrix != null) {
            mTranslate += mViewWidth / 5;
            if (mTranslate > 2 * mViewWidth) {
                mTranslate = -mViewWidth;
            }
            mGradientMatrix.setTranslate(mTranslate, 0);
            mLinearGradient.setLocalMatrix(mGradientMatrix);
            postInvalidateDelayed(100);//在非UI线程中刷新UI界面
        }

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值