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 use Android to implement a cool custom View

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces how to use Android to achieve cool custom View related knowledge, the content is detailed and easy to understand, the operation is simple and fast, with a certain reference value, I believe that after reading this article on how to use Android to achieve cool custom View will have a harvest, let's take a look at it.

I. background

1.1. Control effect

The effect of the custom control to be implemented is roughly as follows. More custom View API is used in the implementation process. If you think it is representative, share it and take it as a learning summary.

Project code has been uploaded to github

Github.com/DaLeiGe/And...

1.2, from the functional analysis of this control, roughly has the following characteristics

The randomly moving particles move from the circumference to the center of the circle, and there is an angle difference of positive or negative 30 °with the tangent direction. The transparency, radius and velocity of the particles are random, and the motion disappears over a certain distance or time.

The background circle has a gradient from the inside to the outside

The torus has a clockwise rotate animation with a gradual color change in timing mode.

The color of the whole background circle varies with the fan angle.

Pointer color change

The digital change is to switch animation up and down.

1.3. Structural analysis

This control can be divided into two parts, and the combined control is composed of background circle and digital control. The reason why the digital control is separated separately is to facilitate the animation of the digital jump up and down. After all, it is not convenient to realize the animation by controlling the position of the drawText, and it is better to realize the animation directly through the property animation of View.

Second, the realization of background circle

2.1. Realize the motion of particles

AnimPoint.java is used to represent moving particles, which has attributes such as x-ray coordinates, radius, angle, velocity, transparency and so on. Through these attributes, a static particle can be drawn.

Public class AnimPoint implements Cloneable {/ * Particle Origin x coordinates * / private float mX; / * Particle Origin y coordinates * / private float mY; / * Particle Radius * / private float radius; / * Angle of initial position of particles * / private double anger / * * Speed of moving a frame * / private float velocity; / * Total number of frames moved * / private int num = 0; / * * Transparency 0cm 255 * / private int alpha = 153; / * * Random offset Angle * / private double randomAnger = 0;}

The initial position of the particle is located in the circle of random angle, and a particle has random radius, transparency, speed and so on. Through the init () method, the initialization of the particle is as follows.

Public void init (Random random, float viewRadius) {anger = Math.toRadians (random.nextInt); velocity = random.nextFloat () * 2F; radius = random.nextInt (6) + 5; mX = (float) (viewRadius * Math.cos (anger)); mY = (float) (viewRadius * Math.sin (anger)) / / Random offset angle-30 °~ 30 °randomAnger = Math.toRadians (30-random.nextInt (60); alpha = 153 + random.nextInt (102);}

If you want to make the particles move, you can use update to update these coordinate attributes of the particles. For example, if the coordinates of the particles are now in (5), change the coordinates of the particles to (6) through update (), and then keep calling update () in combination with attribute animation, you can constantly change the coordinates of XMague y and realize the particle motion. Then when the particles move more than a certain distance, or call update for more than a certain number of times. Then call init () again to start the next life cycle motion of the particle from the circumference.

Public void updatePoint (Random random, float viewRadius) {/ / pixel size per frame offset float distance = 1F; double moveAnger = anger + randomAnger; mX = (float) (mX-distance * Math.cos (moveAnger) * velocity); mY = (float) (mY-distance * Math.sin (moveAnger) * velocity); / / the simulation radius gradually decreases radius = radius-0.02F * velocity Num++; / / if the maximum value is reached, give the moving particle a trajectory attribute int maxDistance = 180; int maxNum = 400; if (velocity * num > maxDistance | | num > maxNum) {num = 0; init (random, viewRadius);}}

The approximate implementation in View is as follows

/ * initialize animation * / private void initAnim () {/ / draw moving particles AnimPoint mAnimPoint = new AnimPoint (); for (int I = 0; I

< pointCount; i++) { //通过clone创建对象,避免重复创建 AnimPoint cloneAnimPoint = mAnimPoint.clone(); //先给每个粒子初始化各类属性 cloneAnimPoint.init(mRandom, mRadius - mOutCircleStrokeWidth / 2F); mPointList.add(cloneAnimPoint); } //画运动粒子 mPointsAnimator = ValueAnimator.ofFloat(0F, 1F); mPointsAnimator.setDuration(Integer.MAX_VALUE); mPointsAnimator.setRepeatMode(ValueAnimator.RESTART); mPointsAnimator.setRepeatCount(ValueAnimator.INFINITE); mPointsAnimator.addUpdateListener(animation ->

{for (AnimPoint point: mPointList) {/ / calculate the next coordinate of the particle point.updatePoint (mRandom, mRadius);} invalidate ();}); mPointsAnimator.start ();} @ Override protected void onDraw (final Canvas canvas) {super.onDraw (canvas) through attribute animation Canvas.save (); canvas.translate (mCenterX, mCenterY); / / draw moving particles for (AnimPoint animPoint: mPointList) {mPointPaint.setAlpha (animPoint.getAlpha ()); canvas.drawCircle (animPoint.getmX (), animPoint.getmY (), animPoint.getRadius (), mPointPaint);} 2.2, realize gradient circle

Use RadialGradient to realize the gradual change of circle from the inside to the outside

The approximate implementation is as follows

Float [] mRadialGradientStops = {0F, 0.69F, 0.86F, 0.94F, 0.98F, 1F}; mRadialGradientColors [0] = transparentColor;mRadialGradientColors [1] = transparentColor;mRadialGradientColors [2] = parameter.getInsideColor (); mRadialGradientColors [3] = parameter.getOutsizeColor (); mRadialGradientColors [4] = transparentColor;mRadialGradientColors [5] = transparentColor MRadialGradient = new RadialGradient (0,0, mCenterX, mRadialGradientColors, mRadialGradientStops, Shader.TileMode.CLAMP); mSweptPaint.setShader (mRadialGradient);. / / onDraw () draw canvas.drawCircle (0,0, mCenterX, mSweptPaint)

Originally intended to achieve this effect through DrawArc, but DrawArc can not achieve the center of the area

So how to achieve such an irregular shape? you can use canvas.clipPath () to cut the irregular shape, so as long as you get the fan-shaped Path, you can achieve it through the dot + arc and then close the path.

/ * * draw sector path * * @ param r radius * @ param startAngle start angle * @ param sweepAngle sweep angle * / private void getSectorClip (float r, float startAngle, float sweepAngle) {mArcPath.reset (); mArcPath.addArc (- r,-r, startAngle, sweepAngle); mArcPath.lineTo (0,0); mArcPath.close () } / / then in onDraw (), crop the canvas canvas.clipPath (mArcPath); 2.4.implement pointer discoloration

The pointer is irregularly shaped and can not be realized by drawing geometry, so drawBitmap is chosen to realize it.

As for how to change the color of the bitmap pointer image, the original scheme is to use AvoidXfermode to change the color within the specified pixel channel range, but AvoidXfermode has been removed in API 24, so this scheme is not effective

Finally, the layer blending mode is used to realize the pointer image discoloration.

The bitmap color can be realized through PorterDuff.Mode.MULTIPLY mode. The source image is the pointer color to be modified, and the target image is white pointer. The discoloration is realized by obtaining the overlapping part of the two images.

The approximate implementation is as follows

/ * initialize Bitmap * / private void initBitmap () {float f = 130F / 656F; mBitmapDST = BitmapFactory.decodeResource (getResources (), R.drawable.indicator); float mBitmapDstHeight = width * f; float mBitmapDstWidth = mBitmapDstHeight * mBitmapDST.getWidth () / mBitmapDST.getHeight (); / / layer blending mode mXfermode = new PorterDuffXfermode (PorterDuff.Mode.MULTIPLY) of the initialization pointer MPointerRectF = new RectF (0,0, mBitmapDstWidth, mBitmapDstHeight); mBitmapSRT = Bitmap.createBitmap ((int) mBitmapDstWidth, (int) mBitmapDstHeight, Bitmap.Config.ARGB_8888); mBitmapSRT.eraseColor (mIndicatorColor);} @ Override protected void onDraw (final Canvas canvas) {super.onDraw (canvas); / / draw pointer canvas.translate (mCenterX, mCenterY); canvas.rotate (mCurrentAngle / 10F) Canvas.translate (- mPointerRectF.width () / 2,-mCenterY); mPointerLayoutId = canvas.saveLayer (mPointerRectF, mBmpPaint); mBitmapSRT.eraseColor (mIndicatorColor); canvas.drawBitmap (mBitmapDST, null, mPointerRectF, mBmpPaint); mBmpPaint.setXfermode (mXfermode); canvas.drawBitmap (mBitmapSRT, null, mPointerRectF, mBmpPaint); mBmpPaint.setXfermode (null); canvas.restoreToCount (mPointerLayoutId)

The circular control is divided into 3600 °, and each angle corresponds to a specific color value of the control, so how to calculate the specific color value of a specific angle?

Referring to the android.animation.ArgbEvaluator implementation of discoloration animation in attribute animation, the color value of a specific point in the two colors is calculated as follows

Public Object evaluate (float fraction, Object startValue, Object endValue) {int startInt = (Integer) startValue; float startA = ((startInt > > 24) & 0xff) / 255.0f; float startR = (startInt > > 16) & 0xff) / 255.0f; float startG = (startInt > > 8) & 0xff) / 255.0f; float startB = (startInt & 0xff) / 255.0f; int endInt = (Integer) endValue Float endA = ((endInt > > 24) & 0xff) / 255.0f; float endR = (endInt > > 16) & 0xff) / 255.0f; float endG = ((endInt > > 8) & 0xff) / 255.0f; float endB = (endInt & 0xff) / 255.0f; / / convert from sRGB to linear startR = (float) Math.pow (startR, 2.2); startG = (float) Math.pow (startG, 2.2) StartB = (float) Math.pow (startB, 2.2); endR = (float) Math.pow (endR, 2.2); endG = (float) Math.pow (endG, 2.2); endB = (float) Math.pow (endB, 2.2); / / compute the interpolated color in linear space float a = startA + fraction * (endA-startA); float r = startR + fraction * (endR-startR); float g = startG + fraction * (endG-startG) Float b = startB + fraction * (endB-startB); / convert back to sRGB in the [0.255] range a = a * 255.0f; r = (float) Math.pow (r, 1.0 / 2.2) * 255.0f; g = (float) Math.pow (g, 1.0 / 2.2) * 255.0f; b = (float) Math.pow (b, 1.0 / 2.2) * 255.0f Return Math.round (a)

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