Android技术知识Android开发Android知识

自定义View(一)

2017-04-19  本文已影响0人  Jackson杰
写在前面

Android已经为我们提供了丰富的组件库,让我们可以实现各种UI效果。但是如果如此众多的组件还不能满足我们的需求,怎么办呢?别急,android组件也为我们提供了非常方便的拓展方法,通过对现有系统组件的继承,可以方便地实习那我们自己的功能。
自定义View作为Android的一项重要技能,一直以来被初学者认为是代表高手的象征,这篇文章就带大家了解下自定义View的过程。

自定义View的分类
自定义View的注意事项
注意事项

在自定义View中,通常有下列比较重要的方法:

下面就用代码展示下自定义View的基本步骤:
public class BasicCustomView extends View {

    private Paint mPaint;

    public BasicCustomView(Context context) {
        super(context);
        initView();
    }

    public BasicCustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public BasicCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    private void initView() {
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
       canvas.translate(width/2,height/2);
        canvas.drawCircle(0,0,100,mPaint);
    }
}

首先验证自定义View是否支持layout_margin,padding,wrap_content等属性,验证代码如下:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_custom_view_basic"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.ahuang.viewandgroup.activity.CustomViewBasicActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <com.example.ahuang.viewandgroup.View.BasicCustomView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="20dp"
            android:background="#111fff"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <com.example.ahuang.viewandgroup.View.BasicCustomView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#111fff"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <com.example.ahuang.viewandgroup.View.BasicCustomView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#111fff"
            android:padding="20dp"/>
    </LinearLayout>

</LinearLayout>

上图证明图我们的自定义View
1.支持layout_margin属性
2.不支持padding属性
3.证明不支持wrap_content

让View支持wrap_content

之所以不支持wrap_content属性,是因为我们的自定义View没有重写onMeasure()方法,View默认的onMeasure()方法只支持EXACTLY模式,所以可以指定控件的具体宽高值或者match_parent属性,如果要自定义的view支持wrap_content属性,就必须重写onMeasure()方法。
加入代码如下:

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      //  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));
    }


    /**
     * 获得测量的宽度
     * @param widthMeasureSpec
     * @return
     */
    private int measureWidth(int widthMeasureSpec){
        int width = 0;
        int mode=MeasureSpec.getMode(widthMeasureSpec); //获得测量模式
        int size=MeasureSpec.getSize(widthMeasureSpec); //获得测量值
        if (mode==MeasureSpec.EXACTLY){ //精准测量模式
            width=size;
        }else {
            width=300;
            if (mode==MeasureSpec.AT_MOST){
                width=Math.min(width,size);
            }
        }
        return  width;
    }


    /**
     * 获得测量的高度
     * @param heightMeasureSpec
     * @return
     */
    private int measureHeight(int heightMeasureSpec){
        int height = 0;
        int mode=MeasureSpec.getMode(heightMeasureSpec); //获得测量模式
        int size=MeasureSpec.getSize(heightMeasureSpec); //获得测量值
        if (mode==MeasureSpec.EXACTLY){ //精准测量模式
            height=size;
        }else {
            height=300;
            if (mode==MeasureSpec.AT_MOST){
                height=Math.min(width,size);
            }
        }
        return  height;
    }

可以看到,重写onMeasure()方法后,VIew已经支持wrap_content了。

让View支持padding属性

修改onDraw()方法如下:

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        final int paddingLeft=getPaddingLeft();
        final int paddingRight=getPaddingRight();
        final int paddingTop=getPaddingTop();
        final int paddingBottom=getPaddingBottom();
        int width = getWidth()-(paddingLeft+paddingRight);
        int height = getHeight()-(paddingTop+paddingBottom);
       canvas.translate(width/2,height/2);
        canvas.drawCircle(0,0,100,mPaint);
    }
 <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <com.example.ahuang.viewandgroup.View.BasicCustomView
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:background="#111fff"
            android:paddingLeft="30dp"
            android:paddingTop="30dp"/>
    </LinearLayout>

我们看到已经支持padding属性了.

代码下载 https://github.com/baojie0327/ViewAndGroup

上一篇 下一篇

猜你喜欢

热点阅读