Android 自定義View
阿新 • • 發佈:2017-06-03
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-styleablename="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