1. 程式人生 > >Android自定義View初體驗,實現圓形TextView的三種方式

Android自定義View初體驗,實現圓形TextView的三種方式

自定義view對我來說一直是比較恐懼的,但是萬事開頭難,今天總結一下自己實現圓形TextView的三種方式。

首先來說一下自定義view的三種方式:

一,自繪控制元件:

自繪控制元件就是說介面展示的內容就是我們在ondraw()方法中繪製出來的,繼承View.

二,組合控制元件:

顧名思義,由多個控制元件組合在一起的控制元件,這裡面組合的控制元件並不需要我們自己去繪製,用android原生的即可。最常見的就是標題欄,將圖示,文字組合到一個佈局中,自定義組合控制元件時繼承Framelayout,通過 LayoutInflater.from(context).inflate(R.layout.title, this); 來引用佈局即可。

三,繼承控制元件:

顧名思義,繼承android原生的已有控制元件,在此基礎上進行繪製,那麼我們就可以在原有的功能上增加新的功能。

自定義view的步驟:

1:自定義屬性,在values中建立attrs檔案

2:在構造方法中獲取自定義屬性,

public View (Context context)是在java程式碼建立檢視的時候被呼叫,如果是從xml填充的檢視,就不會呼叫這個
public View (Context context, AttributeSet attrs)這個是在xml建立但是沒有指定style的時候被呼叫
public View (Context context, AttributeSet attrs, int defStyle)這個是在xml建立,引用預設style的時候被呼叫

3:重寫onMesure(),測量控制元件高度;

4:重寫onDraw(),繪製控制元件;

Demo

圓形TextView的實現:

方式一(自繪控制元件):

1.1自定義屬性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomTextView">
        <attr name="mTextSize" format="dimension"/>
        <attr name="mTextColor"
format="color"/>
<attr name="mBackgroudColor" format="color"/> <attr name="mRound" format="dimension"/> <attr name="mText" format="string"/> </declare-styleable> </resources>

1.2獲取屬性

public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray array = null;
        try {
            array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTextView, 0, 0);
            mTextSize = array.getDimension(R.styleable.CustomTextView_mTextSize, 14);
            mTextColor = array.getColor(R.styleable.CustomTextView_mTextColor, Color.BLACK);
            mBackgroudColor = array.getColor(R.styleable.CustomTextView_mBackgroudColor, Color.YELLOW);
            mRound = array.getColor(R.styleable.CustomTextView_mRound, 5);
            mText = array.getString(R.styleable.CustomTextView_mText);
        } finally {
            array.recycle();
        }
        init();

    }

1.3重寫onMesure();

    @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 = 48;
        int height = 48;
        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = Math.min(width, widthSize);
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = Math.min(height, heightSize);
        }
        setMeasuredDimension(width, height);
    }

1.4重寫onDraw();

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setColor(mBackgroudColor);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, paint);
        paint.setColor(mTextColor);
        canvas.drawText(mText, getWidth() / 2 - rect.width() / 2, getHeight() / 2 + rect.height() / 2, paint);
    }

添加布局

 <com.example.com.customview.CustomTextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:mText="你好"
        android:layout_margin="8dp"
        app:mTextColor="@color/colorPrimary"
        app:mTextSize="16sp"
        app:mBackgroudColor="#F00"/>

方式二(繼承控制元件):

package com.example.com.customview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.TextView;

/**
 * Created by Administrator on 2016/9/5.
 */
public class CustomView extends TextView{

    private Rect rect;
    private Paint paint;
    public CustomView(Context context) {
        super(context);
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        rect=new Rect();
        paint=new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);//抗鋸齒
        paint.setDither(true);//防抖動
    }

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

    @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 = 48;
        int height = 48;
        if(widthMode==MeasureSpec.EXACTLY||heightMode==MeasureSpec.EXACTLY){
            width=widthSize;
            height=heightSize;
            width=Math.max(width,height);
        }

        setMeasuredDimension(width,width);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawCircle(getWidth()/2,getHeight()/2,Math.max(getWidth(), getHeight())/2,paint);
        super.onDraw(canvas);
    }
}

在drawCircle放在 super.onDraw(canvas);前面,因為如果父類先畫text的話,畫圓的時候會被遮蓋,所以先畫圓,在呼叫父類的ondraw();

方式三(shape):

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    android:useLevel="false">

    <solid android:color="#F00"/>
    <size android:height="48dp" android:width="48dp"/>

</shape>

在佈局中新增背景

   <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:text="shape"
        android:gravity="center"
        android:layout_margin="8dp"
        android:background="@drawable/bg_circle"/>

看看三種方式的實現效果:

這裡寫圖片描述

就這些了,講的不是很詳細,因為一些概念基礎我也不是很理解,只能先實現看看咯!