Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement a bilibili Refresh Button in Android

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly explains "how to achieve a bilibili refresh button in Android". The content in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn how to achieve a bilibili refresh button in Android.

1. Analysis

First, let's take a look at the original effect:

The button consists of three parts, namely, rounded rectangle, text and rotation icon. After the button is clicked, the data is loaded, and the rotation icon rotates. After the data loading is completed, the rotation icon resets and stops rotation. Don't say much, start knocking on the code.

2. Draw

Here, there are three parts we want to draw, namely, the rounded rectangle, text, and rotation icon mentioned above. So here are some properties declared for each of these three parts.

It is important to note that there are three constructors in this class, because some of the properties need to be initialized in the constructor (and in preparation for later custom properties), so change the super in the first and second constructors to this.

Public class LQRRefreshButton extends View {/ / rounded rectangle attribute private int borderColor = Color.parseColor ("# fb7299"); private float borderWidth = 0; private float borderRadius = 120; / / text attribute private String text = "Click for another batch"; private int textColor = Color.parseColor ("# fb7299"); private float textSize = 28; / / rotate icon attribute private int iconSrc = R.mipmap.tagged centerprising refresh icons; private float iconSize = 28; private Bitmap iconBitmap Private float space4TextAndIcon = 20; / / Brush private Paint mPaint = new Paint (Paint.ANTI_ALIAS_FLAG); public LQRRefreshButton (Context context) {this (context, null);} public LQRRefreshButton (Context context, @ Nullable AttributeSet attrs) {this (context, attrs, 0);} public LQRRefreshButton (Context context, @ Nullable AttributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr) / / instantiate the icon resource as Bitmap iconBitmap = BitmapFactory.decodeResource (getResources (), R.mipmap.tag_center_refresh_icon);} @ Override protected void onDraw (Canvas canvas) {super.onDraw (canvas); / / 1, draw rounded rectangle / / 2, draw word / / 3, draw refresh icon}}

Next, we focus on the implementation of the onDraw () method:

@ Overrideprotected void onDraw (Canvas canvas) {super.onDraw (canvas); / / 1, rounded rectangle mPaint.setStyle (Paint.Style.STROKE); mPaint.setColor (borderColor); mPaint.setStrokeWidth (borderWidth); canvas.drawRoundRect (new RectF (0,0, getWidth (), getHeight ()), borderRadius, borderRadius, mPaint); / / 2, pictograph mPaint.setTextSize (textSize); mPaint.setColor (textColor); mPaint.setStyle (Paint.Style.FILL); float measureText = mPaint.measureText (text) Float measureAndIcon = measureText + space4TextAndIcon + iconSize; float textStartX = getWidth () / 2-measureAndIcon / 2; float textBaseY = getHeight () / 2 + (Math.abs (mPaint.ascent ())-mPaint.descent ()) / 2; canvas.drawText (text, textStartX, textBaseY, mPaint); / / 3, drawing refresh icon float iconStartX = textStartX + measureText + space4TextAndIcon; canvas.drawBitmap (iconBitmap, iconStartX, getHeight () / 2-iconSize / 2, mPaint);}

Let's take a look at the effect:

I set the width to 200dp and the height to 100dp for the control.

You can see that the effect is pretty good, but there are still a little bit of problems. Let's talk about how these three parts are painted and the minor problems.

1) draw a rounded rectangle

In fact, drawing a rounded rectangle is very simple. Set the style, color and line thickness of the brush, and then call the drawRoundRect () method of canvas.

Because the rounded rectangle we want to draw only needs to draw lines, the style of the brush is set to Paint.Style.STROKE.

In the drawRoundRect () method of canvas, the first parameter is the drawing range, which can be set directly according to the size of the control. The second and third parameters are the fillet radius of the x-axis and y-axis, and the third parameter is the brush (of course, you need a brush to draw something).

But have you noticed that when the thickness of the line is 0 (borderWidth=0), how can there be a rectangular line? This is because the style of the brush is Paint.Style.STROKE, and when the line thickness is 0, you should also draw the line of 1px, because for the brush, the smallest line thickness is 1px. Therefore, the above code needs to be changed as follows:

/ 1. If (borderWidth > 0) {mPaint.setStyle (Paint.Style.STROKE); mPaint.setColor (borderColor); mPaint.setStrokeWidth (borderWidth); canvas.drawRoundRect (new RectF (0,0, getWidth (), getHeight ()), borderRadius, borderRadius, mPaint);}

2) draw words

The general step of drawing words is to set the text size, text color, brush style, and draw the starting point. Among them, the last two are the most important.

Brush style has an impact on the characters drawn. When the brush style is Paint.Style.STROKE, the words are hollowed out (you can try it if you don't believe it). What we need is solid words, so we need to modify the brush style to Paint.Style.FILL.

In Android, the drawing of text is different from other drawings. for example, the starting point of rounded rectangle and rotation icon is the upper left corner, while the text is drawn according to the lower-left word of the text, that is, by the Baseline, so you need to get the coordinates of the starting point of the baseline.

As in the picture above, what we need to get now is the point in the lower left corner of the text. How can we find this?

First of all, x, generally need to make the text center display (it also has something to do with the text alignment, here the default left alignment as an example), so the formula is generally: X = control width / 2-text length / 2. But our control is a little different, it also needs to take into account the position of the rotation icon, so x should ask: X = control width / 2-(text length + gap + rotation icon width) / 2.

/ / get the text length float measureText = mPaint.measureText (text); / / get the text length + gap + rotation icon width float measureAndIcon = measureText + space4TextAndIcon + iconSize;// to get the text drawing starting point float textStartX = getWidth () / 2-measureAndIcon / 2

And y, as shown in the figure:

If you directly use half of the height of the control as the text drawing baseline, then the text drawn must be on the upper side, because the height of Ascent is much higher than the height of Descent, when we calculate Baseline, we need to subtract the height of Descent in Ascent to get the height difference between the two, and then let the control center y coordinates plus (drop) half of the height difference. Therefore:

Float textBaseY = getHeight () / 2 + (Math.abs (mPaint.ascent ())-mPaint.descent ()) / 2

3) draw refresh icon

Finally, it is to draw the refresh icon, which starts from the upper left corner and can be drawn through the drawBitmap () method of canvas.

However, it should be noted that iconSize is a size I set by myself, not the actual size of the icon, so there will be an error in the rotation center obtained when I do the rotation animation later, which will cause the icon to rotate instead of according to the center. So, here you need to resize the icon:

Public class LQRRefreshButton extends View {... Public LQRRefreshButton (Context context, @ Nullable AttributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr); / / icon iconBitmap = BitmapFactory.decodeResource (getResources (), iconSrc); iconBitmap = zoomImg (iconBitmap, iconSize, iconSize);} public Bitmap zoomImg (Bitmap bm, float newWidth, float newHeight) {/ / get the width and height of the image int width = bm.getWidth (); int height = bm.getHeight () / / calculate the zoom ratio float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; / / get the desired matrix parameters Matrix matrix = new Matrix (); matrix.postScale (scaleWidth, scaleHeight); / / get a new image Bitmap newbm = Bitmap.createBitmap (bm, 0,0, width, height, matrix, true); return newbm;}.}

3. Animation

Now it's time to implement the rotation function of the rotation icon. The principle is that when canvas draws the icon, it is easy to rotate the canvas and rotate the canvas to draw the icon, which only takes four steps:

Canvas.save (); canvas.rotate (degress, centerX, centerY); canvas.drawBitmap (iconBitmap, iconStartX, getHeight () / 2-iconSize / 2, mPaint); canvas.restore ()

The next thing to do is to calculate the rotation center, rotation angle, and do not stop to call onDraw () to compile the icon, you can use ValueAnimator or ObjectAnimator to achieve this function, here choose ObjectAnimator. The implementation is as follows:

Public class LQRRefreshButton extends View {... Private float degress = 0; private ObjectAnimator mAnimator; public LQRRefreshButton (Context context, @ Nullable AttributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr); / / rotation animation mAnimator = ObjectAnimator.ofObject (this, "degress", new FloatEvaluator (), 360,0); mAnimator.setDuration (2000); mAnimator.setRepeatMode (ObjectAnimator.RESTART); mAnimator.setInterpolator (new LinearInterpolator ()); mAnimator.setRepeatCount (ObjectAnimator.INFINITE) } @ Override protected void onDraw (Canvas canvas) {super.onDraw (canvas); / / 3, draw refresh icon float iconStartX = textStartX + measureText + space4TextAndIcon; canvas.save (); float centerX = iconStartX + iconSize / 2; int centerY = getHeight () / 2; canvas.rotate (degress, centerX, centerY); canvas.drawBitmap (iconBitmap, iconStartX, getHeight () / 2-iconSize / 2, mPaint); canvas.restore () } public void start () {mAnimator.start ();} public void stop () {mAnimator.cancel (); setDegress (0);} public float getDegress () {return degress;} public void setDegress (float degress) {this.degress = degress; invalidate ();}}

You can modify any property value with ObjectAnimator, so you need to declare a rotation angle variable (degress) in the control, write the getter and setter methods, and call invalidate () in the setter method, so that when the angle value changes, you can have the control call back onDraw () to rotate the icon. The use of ObjectAnimator is not complicated, so I won't go into details here. Let's take a look at the animation:

4. Custom attributes

A custom control cannot write property values in the control, so we need custom properties to get these property values from the outside world.

1) property file writing

Write the following code in attrs.xml:

2) get the attribute value

Get these property values in the third constructor of the control:

Public class LQRRefreshButton extends View {public LQRRefreshButton (Context context, @ Nullable AttributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr); / / get custom attribute values TypedArray ta = context.obtainStyledAttributes (attrs, R.styleable.LQRRefreshButton); borderColor = ta.getColor (R.styleable.LQRRefreshButton_refresh_btn_borderColor, Color.parseColor ("# fb7299")); borderWidth = ta.getDimension (R.styleable.LQRRefreshButton_refresh_btn_borderWidth, dipToPx (0)) BorderRadius = ta.getDimension (R.styleable.LQRRefreshButton_refresh_btn_borderRadius, dipToPx (60)); text = ta.getString (R.styleable.LQRRefreshButton_refresh_btn_text); if (text = = null) text = ""; textColor = ta.getColor (R.styleable.LQRRefreshButton_refresh_btn_textColor, Color.parseColor ("# fb7299")); textSize = ta.getDimension (R.styleable.LQRRefreshButton_refresh_btn_textSize, spToPx (14)) IconSrc = ta.getResourceId (R.styleable.LQRRefreshButton_refresh_btn_iconSrc, R.mipmap.tag_center_refresh_icon); iconSize = ta.getDimension (R.styleable.LQRRefreshButton_refresh_btn_iconSize, dipToPx (14)); space4TextAndIcon = ta.getDimension (R.styleable.LQRRefreshButton_refresh_btn_space4TextAndIcon, dipToPx (10)); ta.recycle ();...}}

There is one thing to note here:

Ta.getDimension (property id, default)

one

two

The value that can be obtained from the outside world through the TypedArray object is automatically converted to px according to different units (such as dp, sp), but the default unit is px, so in order to comply with the Android specification, do not directly use px, so you need to do a manual conversion. Finally, you need to call the recycle () method to recycle the TypedArray.

3) apply it in layout file

Thank you for your reading, the above is the content of "how to achieve a bilibili refresh button in Android". After the study of this article, I believe you have a deeper understanding of how to achieve a bilibili refresh button in Android, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report