Android rounded corner Tag Control

Source: Internet
Author: User
Tags transparent color

Android rounded corner Tag Control

Generally, the rounded corner label control is implemented by setting the shape in xml. However, if we want to create a more powerful and general rounded corner control, you don't need to care about the rounded corner, just set the background. How should we implement it? In this case, you need to set the background to an image first, then process the image as a rounded corner, and then set it as a background. The basic idea is as follows:

Bitmap bitmap = (BitmapDrawable) getBackground ()). getBitmap (); BitmapShader bitmapShader = new BitmapShader (bitmap, Shader. tileMode. CLAMP, Shader. tileMode. CLAMP); Matrix matrix = new Matrix (); bitmapShader. setLocalMatrix (matrix); // set float scale = Math. max (getWidth () * 1.0f/bmp. getWidth (), getHeight () * 1.0f/bmp. getHeight (); mBitmapPaint. setShader (bitmapShader); Canvas canvas = new Canvas (bitmap); if (mRadius> 0) {canvas. drawRoundRect (mDrawableRect, mRadius, mRadius, mBitmapPaint);} else {canvas. drawRect (mDrawableRect, mBitmapPaint);} setBackground (new BitmapDrawable (bitmap ));
The above code retrieves the background image and draws the rounded corner with the Shadow (if the background color is color, a ColorDrawable to Bitmap conversion is required ). In this way, the TextView of a rounded corner background can be enforced. You can also use Xfermode. There are a lot of articles on the Internet.

Now the question is, what if my background is ShapDrawable (xml: shape) or the set StateListDrawable (selector? This is useless. ShapeDrawable can also be customized, but StateListDrawable provides few interfaces that can be customized.

In addition, if we need to set drawableLeft or drawableRight, it will also hide the background and the rounded corner will be gone. You can also set rounded corners for the compound drawable. The radius of the rounded corner cannot be the same as the radius of the main space. Otherwise, the width and height of the rounded corner will be different. This solution is too complicated. Give up!

Is there any simple solution? We can use Xfermode to make an article on the basemap of the canvas.

Here we will talk about the implementation of the Android (it is estimated that other operating systems are similar) control.

Everything we see on the display is actually a piece of memory, which is placed in a memory buffer called framebuffer. This Buffer, in pixels, uses color rules to arrange various things on the screen we can see. Android uses a system called Surface to manage this FrameBuffer. The so-called controls actually follow certain rules to tell the Surface system how to draw my region. This will give us a detailed picture of what we want to see. There are too many details, so I will talk about it later. Let's continue to talk about how to implement the rounded corner control.

All the controls in Android provide us with an onDraw () method. The parameter is Canvas, and Canvas is the meaning of Canvas. What we draw on this cloth, it is the appearance of the space. This method will be called in View. draw () to tell the system how to draw this control. For example, the onDraw in TextView is basically a bit of writing, set the color, font operation, ImageView is to use Drawable to draw the canvas operation.

Android provides a variety of methods to facilitate operations on this Canvas. If we want to achieve rounded corners, do we have some hands and feet on this Canvas? We can use Xfermode to draw an elliptical Bitmap on the source image. Then we can only keep this part of their intersection and remove the non-Intersecting part. Isn't the rounded corner control finished? For Xfermode, there is a classic illustration of deep animation usage:

What we want to do is as follows:


The code for generating a masking image is as follows:

private Bitmap generateMaskBitmap() {    Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);    Canvas bitmapCanvas = new Canvas(bitmap);    RectF r = new RectF(0, 0, getWidth(), getHeight());    Rect rect = new Rect(0, 0, getWidth(), getHeight());    Paint bitmapPaint = new Paint();    bitmapPaint.setAlpha(0);    bitmapPaint.setColor(Color.TRANSPARENT);    bitmapCanvas.drawRect(rect, bitmapPaint);    bitmapPaint.reset();    bitmapPaint.setStyle(Paint.Style.FILL);    bitmapPaint.setAntiAlias(true);    bitmapPaint.setColor(Color.WHITE);    bitmapCanvas.drawRoundRect(r, mRadius, mRadius, bitmapPaint);    return bitmap;}
The onDraw code is as follows:

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    if (mRadius > 0) {        Bitmap bitmap = generateMaskBitmap();        Paint bitmapPaint = new Paint();        bitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));        canvas.drawBitmap(bitmap, 0f, 0f, bitmapPaint);        bitmap.recycle();    }}

But this is not OK. This control is used as follows:

<Com. example. widget. tagTextView android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: background = "# ff0000" android: text = "" app: border_radius = "5dp"/>


Why? The rounded corner is available, but the surrounding area is black. I feel that the code is OK, and then I went to the Internet to search for it. XferMode has some limitations when enabling hardware acceleration (http://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported). It is estimated that this problem is also one of the limitations. Therefore, after the hardware acceleration is disabled in This widget and re-built, it is found that there is still no change. I am a little dizzy, so it's not other colors, but black, and my maskBitmap is also set to white. It can only be interpreted as one: My Background does not set the alpha value, and there is no transparency. As a result, the deleted color changes to the uncolored state. Let me set a background color with transparency:

<Com. example. widget. tagTextView android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: background = "# feff0000" android: text = "" app: border_radius = "5dp"/>



Yes. In this way, no matter what the control has done in the future, it must be rounded around it.

Although this method implements mandatory rounded corners, It is very limited. If the Canvas of the View itself does not have a transparent channel, the rounded corner will become black. I tried to draw a transparent Color on the control, but it still didn't work. The specific reason is unknown. I have not had time to go into it. If you know why, share the reason. Suggestion: We recommend that you create a Factory to generate some defined Tag controls. This is more in line with Android specifications. It can also well manage various Tag controls.
Code link: http://download.csdn.net/detail/yutao52shi/8972539

Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.