失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android绘制五角星并实现星星闪耀发光效果

Android绘制五角星并实现星星闪耀发光效果

时间:2023-06-05 05:01:58

相关推荐

Android绘制五角星并实现星星闪耀发光效果

效果

先来看下效果:

五角星gif图显示速度较实际慢,代码中可自定义闪烁的时长。

自定义View

自定义ShiningStarView的Kotlin代码:

import android.animation.ValueAnimatorimport android.animation.ValueAnimator.AnimatorUpdateListenerimport android.content.Contextimport android.graphics.*import android.util.AttributeSetimport android.view.Viewimport android.view.animation.Animationimport android.view.animation.LinearInterpolatorclass ShiningStarView @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr), AnimatorUpdateListener {private val mStarRadius: Floatprivate val mStarPaint: Paintprivate var mStarPath: Path? = nullprivate var mAlphaValue = 255init {val a = context.obtainStyledAttributes(attrs, R.styleable.ShiningStarView)val mStarColor = a.getColor(R.styleable.ShiningStarView_starColor, Color.YELLOW)mStarRadius = a.getDimension(R.styleable.ShiningStarView_starRadius, 90f)a.recycle()mStarPaint = Paint(Paint.ANTI_ALIAS_FLAG)mStarPaint.color = mStarColormStarPaint.maskFilter = BlurMaskFilter(mStarRadius / 3, BlurMaskFilter.Blur.SOLID) //外发光效果val circleAlphaValueAnimator = ValueAnimator.ofInt(0, 255)circleAlphaValueAnimator.duration = 1000circleAlphaValueAnimator.repeatCount = Animation.INFINITEcircleAlphaValueAnimator.repeatMode = ValueAnimator.REVERSEcircleAlphaValueAnimator.interpolator = LinearInterpolator()circleAlphaValueAnimator.addUpdateListener(this)circleAlphaValueAnimator.start()}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)canvas.save()mStarPaint.alpha = mAlphaValuecanvas.drawPath(mStarPath!!, mStarPaint)canvas.restore()}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {super.onMeasure(widthMeasureSpec, heightMeasureSpec)var width = MeasureSpec.getSize(widthMeasureSpec)var height = MeasureSpec.getSize(heightMeasureSpec)val widthMode = MeasureSpec.getMode(widthMeasureSpec)val heightMode = MeasureSpec.getMode(widthMeasureSpec)if (widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED) {width = mStarRadius.toInt() * 2}if (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED) {height = mStarRadius.toInt() * 2}mStarPath = calculateStarPath(mStarRadius)setMeasuredDimension(width, height)}private fun calculateStarPath(radius: Float): Path {val starPath = Path()//360度除以5个角, 比如5个角 每个角72度,利用cos 、sin计算位置 1度=π/180 以顶角尖作为坐标轴原点val outRadian = Math.PI / 180.0 * (90.0 - 360.0 / 5 / 2) //右角尖与x轴的弧度val pRadian = (1.0 - 0.5) * outRadian //钝角点与x轴的弧度val pRightRadian = 0.5 * outRadian //钝角点到原点与右角尖的弧度val centerLength = radius * Math.sin(Math.PI / 5) //右角尖到顶角间的中心点到原点的距离val pLength = centerLength / Math.cos(pRightRadian) //钝角点到原点距离val pX = pLength * Math.sin(pRadian)val pY = pLength * Math.cos(pRadian)starPath.moveTo(0f, 0f)for (i in 0..4) {val angle = Math.PI / 180 * 360 / 5 * i //每次旋转坐标轴角度 angle== π/180 * (360 / 5)val sinA = Math.sin(angle)val cosA = Math.cos(angle)val rX2 = (radius * sinA).toFloat()val rY2 = (-radius * cosA + radius).toFloat()val pX2 = (pX * cosA - (pY - radius) * sinA).toFloat()val pY2 = ((pY - radius) * cosA + pX * sinA + radius).toFloat()starPath.lineTo(rX2, rY2)starPath.lineTo(pX2, pY2)}starPath.close()val matrix = Matrix()//坐标系平移matrix.setTranslate(radius, 0f)starPath.transform(matrix)return starPath}override fun onAnimationUpdate(animation: ValueAnimator) {mAlphaValue = animation.animatedValue as Intinvalidate()}}

自定义ShiningStarView的Java代码:

import android.animation.ValueAnimator;import android.content.Context;import android.content.res.TypedArray;import android.graphics.BlurMaskFilter;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Path;import android.util.AttributeSet;import android.view.View;import android.view.animation.Animation;import android.view.animation.LinearInterpolator;import androidx.annotation.Nullable;public class ShiningStarView extends View implements ValueAnimator.AnimatorUpdateListener {private final float mStarRadius;private final Paint mStarPaint;private Path mStarPath;private int mAlphaValue = 255;public ShiningStarView(Context context) {this(context, null);}public ShiningStarView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public ShiningStarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context,attrs,defStyleAttr);final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ShiningStarView);int mStarColor = a.getColor(R.styleable.ShiningStarView_starColor, Color.YELLOW);mStarRadius = a.getDimension(R.styleable.ShiningStarView_starRadius, 90);a.recycle();mStarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mStarPaint.setColor(mStarColor);mStarPaint.setMaskFilter(new BlurMaskFilter(mStarRadius / 3, BlurMaskFilter.Blur.SOLID)); //外发光效果ValueAnimator circleAlphaValueAnimator = ValueAnimator.ofInt(0, 255);circleAlphaValueAnimator.setDuration(1000);circleAlphaValueAnimator.setRepeatCount(Animation.INFINITE);circleAlphaValueAnimator.setRepeatMode(ValueAnimator.REVERSE);circleAlphaValueAnimator.setInterpolator(new LinearInterpolator());circleAlphaValueAnimator.addUpdateListener(this);circleAlphaValueAnimator.start();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.save();mStarPaint.setAlpha(mAlphaValue);canvas.drawPath(mStarPath, mStarPaint);canvas.restore();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(widthMeasureSpec);if(widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED) {width = (int) mStarRadius * 2;}if(heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED) {height = (int) mStarRadius * 2;}mStarPath = calculateStarPath(mStarRadius);setMeasuredDimension(width, height);}private Path calculateStarPath(float radius){Path starPath = new Path();//360度除以5个角, 比如5个角 每个角72度,利用cos 、sin计算位置 1度=π/180 以顶角尖作为坐标轴原点double outRadian = Math.PI / 180.0 * (90.0 - 360.0 / 5 / 2); //右角尖与x轴的弧度double pRadian = (1.0 - 0.5) * outRadian; //钝角点与x轴的弧度double pRightRadian = 0.5 * outRadian; //钝角点到原点与右角尖的弧度double centerLength = radius * Math.sin(Math.PI / 5); //右角尖到顶角间的中心点到原点的距离double pLength = centerLength / Math.cos(pRightRadian); //钝角点到原点距离double pX = pLength * Math.sin(pRadian);double pY = pLength * Math.cos(pRadian);starPath.moveTo(0,0);for (int i = 0;i < 5;i++){double angle = Math.PI / 180 * 360 / 5 * i; //每次旋转坐标轴角度 angle== π/180 * (360 / 5)double sinA = Math.sin(angle);double cosA = Math.cos(angle);float rX2 = (float) (radius * sinA);float rY2 = (float) (-radius * cosA + radius);float pX2 = (float) (pX * cosA - (pY - radius) * sinA);float pY2 = (float) ((pY - radius) * cosA + pX*sinA + radius);starPath.lineTo(rX2,rY2);starPath.lineTo(pX2,pY2);}starPath.close();Matrix matrix = new Matrix();//坐标系平移matrix.setTranslate(radius,0);starPath.transform(matrix);return starPath;}@Overridepublic void onAnimationUpdate(ValueAnimator animation) {mAlphaValue = (int) animation.getAnimatedValue();invalidate();}}

通过BlurMaskFilter实现外发光效果,坐标轴以顶角为原点进行数学计算,得到五角星的Path轨迹。根据弧度(1角度=π/180弧度)来计算边长,根据五角星的对称原理和直角三角形的原理,借助sin和cos等公式计算对应坐标。通过动画进行循环绘制,绘制不同的透明度实现闪闪发光效果。

自定义View的属性定义attrs.xml如下:

<resources><declare-styleable name="ShiningStarView"><attr name="starRadius" format="dimension"/><attr name="starColor" format="color"/></declare-styleable></resources>

其中通过starRadius属性定义五角星的半径(以此作为大小);通过starColor属性为五角星颜色。

在界面中定义如下:

<com.example.customui.ShiningStarViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:starRadius="30dp"app:starColor="@color/yellow"/>

如果觉得《Android绘制五角星并实现星星闪耀发光效果》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。