1. 程式人生 > >Android 自定義View

Android 自定義View

wid declare created odi lex getwidth 實現 tdi led

  最近在看鴻洋大神的博客,在看到自定義部分View部分時,想到之前案子中經常會要用到"圖片 + 文字"這類控件,如下圖所示:

技術分享

之前的做法是在布局文件中,將一個Image & TextView組件放在LinearLayout/RelativeLayout中。今天就嘗試了通過自定義View的方式來實現"圖片 + 文字"組件。

  首先在/res/value/目錄下新建attrs.xml文件,在該文件中為CustomTextView定義以下幾個attr。分別為

  1.文字內容-titleText 2.文字顏色-titleTextColor 3.文字大小-titleTextSize

  4.圖像內容-image 5.圖像寬度-imageWidth 6.圖像高度-imageHeight 7.圖像顯示模式-imageScaleType

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--define some attrs for custom view-->

    <attr name="titleText" format="string"/>
    <attr name="titleTextColor" format="color"/>
    <attr name="titleTextSize" format="dimension"/>
    <attr name="image"
format="reference"/> <attr name="imageWidth" format="dimension"/> <attr name="imageHeight" format="dimension"/> <attr name="imageScaleType"> <enum name="fillXY" value="0" /> <enum name="center" value="1" /> </attr> <declare-styleable
name="CustomTextView"> <attr name="titleText" /> <attr name="titleTextColor" /> <attr name="titleTextSize" /> <attr name="image" /> <attr name="imageScaleType" /> <attr name="imageWidth"/> <attr name="imageHeight"/> </declare-styleable> </resources>

  下面就是CustomTextView.java內容:

package com.example.steve.customizedview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

/**
 * Created by steve on 17-6-2.
 */

public class CustomTextView extends View {
    /**
     * 文本
     */
    private String mTitleText;
    /**
     * 文本的顏色
     */
    private int mTitleTextColor;
    /**
     * 文本的大小
     */
    private int mTitleTextSize;

    /**
     * 圖片
     */
    private Bitmap mImage;
    private int mImageWidth;
    private int mImageHeight;
    /**
     * 圖片顯示模式
     */
    private int mImageScaleType;
    /**
     * 繪制時控制文本繪制的範圍
     */
    private Rect mBound;
    private Paint mPaint;
    /**
     * Canvas大小
     */
    private int mWidth;
    private int mHeight;

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

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

    public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView, defStyleAttr, 0);
        int count = a.getIndexCount();
        for (int i = 0; i < count; i++)
        {
            int attr = a.getIndex(i);
            switch (attr)
            {
                case R.styleable.CustomTextView_titleText:
                    mTitleText = a.getString(attr);
                    break;
                case R.styleable.CustomTextView_titleTextColor:
                    mTitleTextColor = a.getColor(attr, Color.BLACK);
                    break;
                case R.styleable.CustomTextView_titleTextSize:
                    mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.CustomTextView_image:
                    mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));
                    break;
                case R.styleable.CustomTextView_imageScaleType:
                    mImageScaleType = a.getInt(attr, 0);
                    break;
                case R.styleable.CustomTextView_imageWidth:
                    mImageWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, 24, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.CustomTextView_imageHeight:
                    mImageHeight = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, 32, getResources().getDisplayMetrics()));
                    break;
            }

        }
        a.recycle();

// 如果設置圖片的寬和高的話,需要對原始圖片進行縮放處理
if (mImageWidth > 0 && mImageHeight > 0) { mImage = zoomImg(mImage, mImageWidth, mImageHeight); } mPaint = new Paint(); mPaint.setTextSize(mTitleTextSize); mBound = new Rect(); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); } public Bitmap zoomImg(Bitmap bm, int newWidth ,int newHeight){ // 獲得圖片的寬高 int width = bm.getWidth(); int height = bm.getHeight(); // 計算縮放比例 float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // 取得想要縮放的matrix參數 Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); // 得到新的圖片 Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true); return newbm; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //設置寬度 int specMode = MeasureSpec.getMode(widthMeasureSpec); int specWidth = MeasureSpec.getSize(widthMeasureSpec); if (specMode == MeasureSpec.EXACTLY) { mWidth = specWidth; } else { int desireByImg = getPaddingLeft() + getPaddingRight() + mImage.getWidth(); int desireByTitle = getPaddingLeft() + getPaddingRight() + mBound.width(); if (specMode == MeasureSpec.AT_MOST) { int desireWidth = Math.max(desireByImg, desireByTitle);//取兩者之間的最大值 mWidth = Math.min(desireWidth, specWidth); } } //設置高度 specMode = MeasureSpec.getMode(heightMeasureSpec); int specHight = MeasureSpec.getSize(heightMeasureSpec); if (specMode == MeasureSpec.EXACTLY) { mHeight = specHight; } else { int desireHight = getPaddingTop() + getPaddingBottom() + mImage.getHeight() + mBound.height(); if (specMode == MeasureSpec.AT_MOST) { mHeight = Math.min(desireHight, specHight); } } setMeasuredDimension(mWidth, mHeight); } @Override protected void onDraw(Canvas canvas) { Rect rect = new Rect(); rect.left = getPaddingLeft(); rect.right = mWidth - getPaddingRight(); rect.top = getPaddingTop(); rect.bottom = mHeight - getPaddingBottom(); mPaint.setColor(mTitleTextColor); mPaint.setStyle(Paint.Style.FILL); mPaint.setTypeface(Typeface.DEFAULT_BOLD);//設置字體樣式 canvas.drawText(mTitleText, mWidth / 2 - mBound.width() * 1.0f / 2, mHeight - getPaddingBottom(), mPaint); rect.bottom = - mBound.height();//重新計算rect的高度,即減去字體占用的空間 if (mImageScaleType == 1) { canvas.drawBitmap(mImage, null, rect, mPaint); } else { //計算居中的矩形範圍 rect.left = mWidth / 2 - mImage.getWidth() / 2; rect.right = mWidth / 2 + mImage.getWidth() / 2; rect.top = (mHeight - mBound.height()) / 2 - mImage.getHeight() / 2; rect.bottom = (mHeight - mBound.height()) / 2 + mImage.getHeight() / 2; canvas.drawBitmap(mImage, null, rect, mPaint); } } }

  布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.steve.customizedview.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/custom_view_height"
        android:background="#F0F0F0">
        <com.example.steve.customizedview.CustomTextView
            android:layout_width="80dp"
            android:layout_height="match_parent"
            android:layout_centerInParent="true"
            android:paddingBottom="5dp"
            custom:titleText="@string/delete_text"
            custom:titleTextColor="#5C5C5C"
            custom:titleTextSize="12sp"
            custom:image="@drawable/delete_n"
            custom:imageWidth="28dp"
            custom:imageHeight="28dp"/>
        />
    </RelativeLayout>
</RelativeLayout>

  該文章內容基本上都是參考http://blog.csdn.net/lmj623565791/article/details/24252901/,有興趣的可以直接看鴻洋大神的blog。

Android 自定義View