Reprinted please indicate the source: http://blog.csdn.net/lmj623565791/article/details/24300125
To continue the custom View journey, we have already introduced a basic example of a custom View, Android custom View (1 ), if you are not familiar with the custom View, you can check it out. Today, we will give you an example with a little complexity.
A custom View displays an image. The following content describes the text of the image, which is similar to the photo description. However, it is not important to learn how to use the custom View.
Do you still remember the four steps described in the previous article:
1. Custom View attributes
2. Obtain custom attributes in the View constructor.
[3. Rewrite onMesure]
4. Override onDraw
Start with the question:
1. In res/values/attr. xml
<?xml version="1.0" encoding="utf-8"?><resources> <attr name="titleText" format="string" /> <attr name="titleTextSize" format="dimension" /> <attr name="titleTextColor" format="color" /> <attr name="image" format="reference" /> <attr name="imageScaleType"> <enum name="fillXY" value="0" /> <enum name="center" value="1" /> </attr> <declare-styleable name="CustomImageView"> <attr name="titleText" /> <attr name="titleTextSize" /> <attr name="titleTextColor" /> <attr name="image" /> <attr name="imageScaleType" /> </declare-styleable></resources>
2. Get our custom attributes in the constructor:
/*** Initialize a specific custom type ** @ param context * @ param attrs * @ param defStyle */public CustomImageView (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); TypedArray a = context. getTheme (). obtainStyledAttributes (attrs, R. styleable. customImageView, defStyle, 0); int n =. getIndexCount (); for (int I = 0; I <n; I ++) {int attr =. getIndex (I); switch (attr) {case R. styleable. customImageView_image: mImage = BitmapFactory. decodeResource (getResources (),. getResourceId (attr, 0); break; case R. styleable. customImageView_imageScaleType: mImageScale =. getInt (attr, 0); break; case R. styleable. customImageView_titleText: mTitle =. getString (attr); break; case R. styleable. customImageView_titleTextColor: mTextColor =. getColor (attr, Color. BLACK); break; case R. styleable. customImageView_titleTextSize: mTextSize =. getDimensionPixelSize (attr, (int) TypedValue. applyDimension (TypedValue. COMPLEX_UNIT_SP, 16, getResources (). getDisplayMetrics (); break;}. recycle (); rect = new Rect (); mPaint = new Paint (); mTextBound = new Rect (); mPaint. setTextSize (mTextSize); // calculates the mPaint range required to describe the font. getTextBounds (mTitle, 0, mTitle. length (), mTextBound );}
3. Override onMeasure
@ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {// super. onMeasure (widthMeasureSpec, heightMeasureSpec);/*** set the width */int specMode = MeasureSpec. getMode (widthMeasureSpec); int specSize = MeasureSpec. getSize (widthMeasureSpec); if (specMode = MeasureSpec. EXACTLY) // match_parent, accurate {Log. e ("xxx", "EXACTLY"); mWidth = specSize;} else {// width int desireByImg = getPaddingLeft () + getPaddingRight () + mImage. getWidth (); // The width int desireByTitle = getPaddingLeft () + getPaddingRight () + mTextBound determined by the font. width (); if (specMode = MeasureSpec. AT_MOST) // wrap_content {int desire = Math. max (desireByImg, desireByTitle); mWidth = Math. min (desire, specSize); Log. e ("xxx", "AT_MOST") ;}/ ***** set height */specMode = MeasureSpec. getMode (heightMeasureSpec); specSize = MeasureSpec. getSize (heightMeasureSpec); if (specMode = MeasureSpec. EXACTLY) // match_parent, accurate {mHeight = specSize;} else {int desire = getPaddingTop () + getPaddingBottom () + mImage. getHeight () + mTextBound. height (); if (specMode = MeasureSpec. AT_MOST) // wrap_content {mHeight = Math. min (desire, specSize) ;}} setMeasuredDimension (mWidth, mHeight );}
4. Override onDraw
@ Overrideprotected void onDraw (Canvas canvas) {// super. onDraw (canvas);/*** border */mPaint. setStrokeWidth (4); mPaint. setStyle (Paint. style. STROKE); mPaint. setColor (Color. CYAN); canvas. drawRect (0, 0, getMeasuredWidth (), getMeasuredHeight (), mPaint); rect. left = getPaddingLeft (); rect. right = mWidth-getPaddingRight (); rect. top = getPaddingTop (); rect. bottom = mHeight-getPaddingBottom (); mPaint. setColor (mTextColor); mPaint. setStyle (Style. FILL);/*** the current width is smaller than the font width, and the font is changed to xxx... */if (mTextBound. width ()> mWidth) {TextPaint paint = new TextPaint (mPaint); String msg = TextUtils. ellipsize (mTitle, paint, (float) mWidth-getPaddingLeft ()-getPaddingRight (), TextUtils. truncateAt. END ). toString (); canvas. drawText (msg, getPaddingLeft (), mHeight-getPaddingBottom (), mPaint);} else {// normal, center the font in the canvas. drawText (mTitle, mWidth/2-mTextBound. width () * 1.0f/2, mHeight-getPaddingBottom (), mPaint);} // cancel the use of quick rect. bottom-= mTextBound. height (); if (mImageScale = IMAGE_SCALE_FITXY) {canvas. drawBitmap (mImage, null, rect, mPaint);} else {// calculates the rect of the rectangular range centered. left = mWidth/2-mImage. getWidth ()/2; rect. right = mWidth/2 + mImage. getWidth ()/2; rect. top = (mHeight-mTextBound. height ()/2-mImage. getHeight ()/2; rect. bottom = (mHeight-mTextBound. height ()/2 + mImage. getHeight ()/2; canvas. drawBitmap (mImage, null, rect, mPaint );}}
Code, combined with comments and the use of the first View, should be understandable, do not understand the message. Next we will introduce our custom View:
<LinearLayout xmlns: android = "http://schemas.android.com/apk/res/android" xmlns: tools = "http://schemas.android.com/tools" xmlns: zhy = "http://schemas.android.com/apk/res/com.zhy.customview02" android: layout_width = "match_parent" android: layout_height = "match_parent" android: orientation = "vertical"> <com. zhy. customview02.view. customImageView android: layout_width = "wrap_content" android: layout_height = "wrap _ Content "android: layout_margin =" 10dp "android: padding =" 10dp "zhy: image =" @ drawable/ic_launcher "zhy: imageScaleType =" center "zhy: titleText = "hello andorid! "Zhy: titleTextColor =" # ff0000 "zhy: titleTextSize =" 30sp "/> <com. zhy. customview02.view. customImageView android: layout_width = "100dp" android: layout_height = "wrap_content" android: layout_margin = "10dp" android: padding = "10dp" zhy: image = "@ drawable/ic_launcher" zhy: imageScaleType = "center" zhy: titleText = "helloworldwelcome" zhy: titleTextColor = "#00ff00" zhy: titleTextSize = "20sp"/> <com. zhy. customview02.view. CustomImageView android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_margin = "10dp" android: padding = "10dp" zhy: image = "@ drawable/lmj" zhy: imageScaleType = "center" zhy: titleText = "~ "Zhy: titleTextColor =" # ff0000 "zhy: titleTextSize =" 12sp "/> </LinearLayout>
I specifically asked the display to show 3 errors:
1. The font width is greater than the image width, and the View width is set to wrap_content.
2. Set the View width to an exact value. The font length is greater than this width.
3. The image width is greater than the font and the View width is set to wrap_content.
Check the display effect:
How about it? The effect shown in the three cases is good.
Okay, so here you are. You can leave a comment ~
Download source code