Android自定义view学习笔记

来源:互联网 发布:95式自动步枪弹道数据 编辑:程序博客网 时间:2024/06/05 09:04

1. 重写OnMesure()用于测量view宽度和高度

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)      {          super.onMeasure(widthMeasureSpec, heightMeasureSpec);      }

当自定义view设置固定数值或者设置为 MATCH_PARENT时不需要重写OnMesure(),系统测量为屏幕大小。 当设置了WRAP_CONTENT时,我们需要自己进行测量。

1.1 重写前先了解下MeasureSpec的specMode

MeasureSpec的specMode,一共三种类型:
- EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
- AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT
- UNSPECIFIED:表示子布局想要多大就多大,很少使用

2. 自定义View

layout.xml
<RelativeLayout 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"    tools:context="com.example.lee.myapp.MyviewActivity">    <com.example.lee.myapp.MyTextView        xmlns:my="http://schemas.android.com/apk/res-auto"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:padding="10dp"        android:text="Title"        android:textColor="@android:color/holo_orange_dark"        android:textSize="16sp"        my:mySubText="subTitle"        my:mySubTextColor="@android:color/darker_gray"        my:subMarginTop="10dp"        my:mySubTextSize="12sp"/></RelativeLayout>
attr.xml
<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="MyTextView">        <!--使用android自带语义明确属性 -->        <attr name="android:text"></attr>        <attr name="android:textColor"></attr>        <attr name="android:textSize"></attr>        <!--自定义个性化属性 -->        <attr name="mySubText" format="string"></attr>        <attr name="mySubTextColor" format="color"></attr>        <attr name="mySubTextSize" format="dimension"></attr>        <attr name="subMarginTop" format="dimension"></attr>    </declare-styleable></resources>
MyTextView.java
    private String mTitleText, mSubTitleText;//内容文字    private int mTitleTextColor, mSubTitleTextColor;//内容文本颜色    private int mTitleTextSize, mSubTitleTextSize;//内容文本大小    private int subMarginTop;//副标题距主标题margin    private Rect mBounds, mSubBounds;//文本区域范围    private Paint mPaint;//画笔    private Paint mSubPaint;//副标题画笔    public MyTextView(Context context) {        super(context);        init(context, null);    }    public MyTextView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context, attrs);    }    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context, attrs);    }    private void init(Context context, AttributeSet attrs) {        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);        //屏幕密度        final float density = getResources().getDisplayMetrics().density;        mTitleText = typedArray.getString(R.styleable.MyTextView_android_text);        mTitleTextColor = typedArray.getColor(R.styleable.MyTextView_android_textColor, Color.BLACK);        mTitleTextSize = typedArray.getDimensionPixelSize(R.styleable.MyTextView_android_textSize, (int) (16 * density));        mSubTitleText = typedArray.getString(R.styleable.MyTextView_mySubText);        mSubTitleTextColor = typedArray.getColor(R.styleable.MyTextView_mySubTextColor, Color.BLACK);        mSubTitleTextSize = typedArray.getDimensionPixelSize(R.styleable.MyTextView_mySubTextSize, (int) (12 * density));        subMarginTop = typedArray.getDimensionPixelSize(R.styleable.MyTextView_subMarginTop, (int) (10 * density));        typedArray.recycle();        mPaint = new Paint();        mPaint.setTextSize(mTitleTextSize);        mBounds = new Rect();        //mBound为主标题范围        mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBounds);        mSubPaint = new Paint();        mSubPaint.setTextSize(mSubTitleTextSize);        mSubPaint.setColor(mSubTitleTextColor);        //mSubBounds为副标题范围        mSubBounds = new Rect();        mSubPaint.getTextBounds(mSubTitleText, 0, mSubTitleText.length(), mSubBounds);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        //最终测量的宽高        int width;        int height;        //EXACTLY模式下直接使用系统测量值        if (widthMode == MeasureSpec.EXACTLY) {            width = widthSize;        } else {            //主标题            float textWidth = mBounds.width();            //副标题            float textSubWidth = mSubBounds.width();            int mWidth = (int) (getPaddingLeft() + Math.max(textWidth, textSubWidth) + getPaddingRight());            width = mWidth;        }        if (heightMode == MeasureSpec.EXACTLY) {            height = heightSize;        } else {            //主标题            float textHeight = mBounds.height();            //副标题            float textSubHeight = mSubBounds.height();            //textHeight + subMarginTop + textSubHeight 内容全部高度            int mHeight = (int) (getPaddingTop() + (textHeight + subMarginTop + textSubHeight) + getPaddingBottom());            height = mHeight;        }        setMeasuredDimension(width, height);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        mPaint.setColor(Color.YELLOW);        //测量完后再布局        canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);        mPaint.setColor(mTitleTextColor);        canvas.drawText(mTitleText, getWidth() / 2 - mBounds.width() / 2, (getHeight() - subMarginTop) / 2 , mPaint);        canvas.drawText(mSubTitleText, getWidth() / 2 - mSubBounds.width() / 2,(getHeight() + subMarginTop) / 2 + mSubBounds.height(), mSubPaint);    }

绘制文本函数:canvas.drawText(“”, x, y, paint);
x:默认是字符的左边在屏幕的位置,如果设置了paint.setTextAlign(Paint.Align.CENTER);那就是字符的中心
y:是指定这个字符baseline在屏幕上的位置

最后

    简单的自定义view就这样实现了。    自定义View还一个原因是需要适配屏幕,在不同设备上能自动缩放满足要求,接下来加上缩放。
1 0
原创粉丝点击