目的
自定义View显示一张图片,下面包含图片的文本介绍
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <resources> <attr name="titleText" format="string" /> <attr name="titleTextColor" format="color" /> <attr name="titleTextSize" format="dimension" /> <attr name="image" format="reference"/> <attr name="imageScaleType"> <enum name="fillXY" value="0" /> <enum name="center" value="1" /> </attr>
<declare-styleable name="MyView"> <attr name="titleText" /> <attr name="titleTextColor" /> <attr name="titleTextSize" /> <attr name="image"/> <attr name="imageScaleType"/> </declare-styleable> </resources>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| class MyView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { private var mImage: Bitmap? = null private var mImageScale: Int = 0 private var mTitle: String = "" private var mTextColor: Int = Color.BLACK private var mTextSize: Int = 0 private var mWidth=0 private var mHeight=0 private val rect = Rect() private val mPaint = Paint() private val mTextBound = Rect()
init { val a = context.theme.obtainStyledAttributes( attrs, R.styleable.MyView, defStyleAttr, 0 )
for (i in 0 until a.indexCount) { when (val attr = a.getIndex(i)) { R.styleable.MyView_image -> { val resId = a.getResourceId(attr, 0) if (resId != 0) { mImage = BitmapFactory.decodeResource(resources, resId) } } R.styleable.MyView_imageScaleType -> { mImageScale = a.getInt(attr, 0) } R.styleable.MyView_titleText -> { mTitle = a.getString(attr) ?: "" } R.styleable.MyView_titleTextColor -> { mTextColor = a.getColor(attr, Color.BLACK) } R.styleable.MyView_titleTextSize -> { mTextSize = a.getDimensionPixelSize( attr, TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16f, resources.displayMetrics ).toInt() ) } } }
a.recycle()
mPaint.textSize = mTextSize.toFloat() mPaint.getTextBounds(mTitle, 0, mTitle.length, mTextBound) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { var specMode = MeasureSpec.getMode(widthMeasureSpec) var specSize = MeasureSpec.getSize(widthMeasureSpec)
mWidth = when (specMode) { MeasureSpec.EXACTLY -> { Log.e("xxx", "EXACTLY") specSize } MeasureSpec.AT_MOST -> { val desireByImg = paddingLeft + paddingRight + (mImage?.width ?: 0) val desireByTitle = paddingLeft + paddingRight + mTextBound.width() val desire = maxOf(desireByImg, desireByTitle) Log.e("xxx", "AT_MOST") minOf(desire, specSize) } else -> { val desireByImg = paddingLeft + paddingRight + (mImage?.width ?: 0) val desireByTitle = paddingLeft + paddingRight + mTextBound.width() maxOf(desireByImg, desireByTitle) } }
specMode = MeasureSpec.getMode(heightMeasureSpec) specSize = MeasureSpec.getSize(heightMeasureSpec)
mHeight = when (specMode) { MeasureSpec.EXACTLY -> specSize MeasureSpec.AT_MOST -> { val desire = paddingTop + paddingBottom + (mImage?.height ?: 0) + mTextBound.height() minOf(desire, specSize) } else -> { paddingTop + paddingBottom + (mImage?.height ?: 0) + mTextBound.height() } }
setMeasuredDimension(mWidth, mHeight) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| override fun onDraw(canvas: Canvas) { mPaint.strokeWidth = 4f mPaint.style = Paint.Style.STROKE mPaint.color = Color.CYAN canvas.drawRect(0f, 0f, measuredWidth.toFloat(), measuredHeight.toFloat(), mPaint)
rect.left = paddingLeft rect.right = mWidth - paddingRight rect.top = paddingTop rect.bottom = mHeight - paddingBottom
mPaint.color = mTextColor mPaint.style = Paint.Style.FILL
val displayText = if (mTextBound.width() > mWidth) { val textPaint = TextPaint(mPaint) TextUtils.ellipsize( mTitle, textPaint, (mWidth - paddingLeft - paddingRight).toFloat(), TextUtils.TruncateAt.END ).toString() } else { mTitle }
val textX = if (displayText == mTitle) { mWidth / 2f - mTextBound.width() / 2f } else { paddingLeft.toFloat() } val textY = (mHeight - paddingBottom).toFloat() canvas.drawText(displayText, textX, textY, mPaint)
rect.bottom -= mTextBound.height()
mImage?.let { bitmap -> if (mImageScale == 0) { canvas.drawBitmap(bitmap, null, rect, mPaint) } else { rect.left = mWidth / 2 - bitmap.width / 2 rect.right = mWidth / 2 + bitmap.width / 2 rect.top = (mHeight - mTextBound.height()) / 2 - bitmap.height / 2 rect.bottom = (mHeight - mTextBound.height()) / 2 + bitmap.height / 2 canvas.drawBitmap(bitmap, null, rect, mPaint) } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:example="http://schemas.android.com/apk/res-auto" android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" tools:ignore="ResAuto"> <com.example.viewtest.MyView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:padding="10dp" example:image="@drawable/custom_img" example:imageScaleType="center" example:titleText="hello andorid ! " example:titleTextColor="#ff0000" example:titleTextSize="30sp" />
<com.example.viewtest.MyView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:padding="10dp" example:image="@drawable/vol_01" example:imageScaleType="center" example:titleText="helloworld" example:titleTextColor="#00ff00" example:titleTextSize="20sp" />
<com.example.viewtest.MyView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:padding="10dp" example:image="@drawable/vol_02" example:imageScaleType="fillXY" example:titleText="妹子~" example:titleTextColor="#ff0000" example:titleTextSize="12sp" /> </LinearLayout>
|