美文网首页
自定义View(1)

自定义View(1)

作者: 王世军Steven | 来源:发表于2016-12-15 12:35 被阅读7次

直接继承 View 重写 onDraw 方法.

这种方法主要用于实现一些不规则的效果.一般需要重写onDraw方法.
注意点 :

  1. 需要自己支持 wrap_content 属性.
  2. 需要自己支持 padding 属性.
  3. 添加自定义属性 .

1. 重写onMeasure处理wrap_content .

处理wrap_content代码

    // 默认尺寸.
    private int mWidht = 200;
    private int mHeight = 200;
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 默认设置View尺寸但是wrap_content会失效 
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 获取尺寸.
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        // 对于使用wrap_content 使用默认尺寸.
        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(mWidht,mHeight);
        }else if (widthSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(mWidht,heightSpecSize);
        }else if (heightSpecSize == MeasureSpec.AT_MOST){
            setMeasuredDimension(widthSpecSize,mHeight);
        }
    }

2. 在onDraw方法中处理失效Padding问题.

处理代码 :

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 处理padding.
        final int paddingLeft = getPaddingLeft();
        final int paddingRight = getPaddingRight();
        final int paddingTop = getPaddingTop();
        final int paddingBottom = getPaddingBottom();
        // 可用尺寸需要在总尺寸中减去padding值
        int w = getWidth() - paddingLeft - paddingRight;
        int h = getHeight() - paddingTop - paddingBottom;
        int radius = Math.min(w,h)/2;
        canvas.drawCircle(getWidth() / 2, getHeight() / 2,radius,mPaint);
    }

3. 添加自定义属性.

3.1 在 values 目录下创建自定义属性XML文件.比如 : attrs.circle_view.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CircleView">
        <!-- 自定义颜色属性 -->
        <attr name="circle_color" format="color"/>
    </declare-styleable>
</resources>

3.2 在View的构造方法中解析自定义属性值并做相应处理

   public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 解析自定义属性值.
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.CircleView);
        mColor = a.getColor(R.styleable.CircleView_circle_color,Color.RED);
        a.recycle();

        init();
    }

3.3 在布局文件中使用自定义属性.

使用自定义文件注意点 :

  1. 需要在布局文件中添加 schemeas 声明 : xmlns:app="http://schemas.android.com/apk/res-auto"
    在这个声明中app是自定义属性前缀,自定义属性前缀必须和这里的一样.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/activity_main"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff"
    android:orientation="vertical"
    tools:context="com.blx.pkcs.customview01.MainActivity">
    <com.blx.pkcs.customview01.CircleView
        android:id="@+id/circle_view_1"
        android:layout_width="wrap_content"
        android:layout_margin="5dp"
        app:circle_color="#0BB"
        android:padding="10dp"
        android:layout_height="100dp"
        android:background="#000"
        android:text="Hello World!"/>
</LinearLayout>

4. CircleView.java 完整代码

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
 * 自定义View 绘制圆形.
 * Created by WSJ on 2016/12/15.
 */

public class CircleView extends View {

    private int mColor = Color.RED;
    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);


    public CircleView(Context context) {
        this(context,null);
    }

    public CircleView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 解析自定义属性值.
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.CircleView);
        mColor = a.getColor(R.styleable.CircleView_circle_color,Color.RED);
        a.recycle();
        init();
    }

    private void init() {
        mPaint.setColor(mColor);
    }

    /**
     * 在这个方法中处理padding失效问题.
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 处理padding.
        final int paddingLeft = getPaddingLeft();
        final int paddingRight = getPaddingRight();
        final int paddingTop = getPaddingTop();
        final int paddingBottom = getPaddingBottom();
        int w = getWidth() - paddingLeft - paddingRight;
        int h = getHeight() - paddingTop - paddingBottom;
        int radius = Math.min(w,h)/2;
        canvas.drawCircle(getWidth() / 2, getHeight() / 2,radius,mPaint);
    }
    // 默认尺寸.
    private int mWidht = 200;
    private int mHeight = 200;

    /**
     * 在这个方法中处理wrap_content失效问题.
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 处理Wrap_content 方式.
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(mWidht,mHeight);
        }else if (widthSpecMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(mWidht,heightSpecSize);
        }else if (heightSpecSize == MeasureSpec.AT_MOST){
            setMeasuredDimension(widthSpecSize,mHeight);
        }
    }
}

备注 : Android 开发艺术探索 - 读书笔记

相关文章

网友评论

      本文标题:自定义View(1)

      本文链接:https://www.haomeiwen.com/subject/epzwmttx.html