首先让我们来看一下需要实现的效果 昨天发现华为加载控件的动画还挺好看的于是就想着自己模仿这做出来。 我们可以看到其实就是绘制这样一个图案然后利用动画以最中心轴旋转就实现了加载 CustomLoadingView.java activity_main.xml MainActivity.java 由此就搞定了这个简单的自定义View 项目链接 欢迎Star ![请输入图片描述][5]
闲话不多说,看完了效果图接下来就开做!1.实现原理
总共十个圆(这里命名为加载圆)
加载圆1,2,3,4,5大小和颜色一致。
加载圆6,7,8开始大小和颜色依次增加。
加载圆8,10大小和颜色一致。
加载圆9颜色大小最大颜色最深。
这里颜色我们可以通过改变透明度来实现
下面我们通过代码绘制来实现。2.项目结构
3.自定义属性
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CustomLoadingView"> <!--控件颜色--> <attr name="custom_color" format="color" /> <!--转一圈花费时长--> <attr name="custom_duration" format="integer" /> <attr name="custom_size" format="dimension"/> </declare-styleable> </resources>
4.自定义View
public class CustomLoadingView extends View { private static final int mCount = 10; //加载圆总数 private static final int mRotateValue = 360 / mCount; //每个加载圆圆心间隔角度差 private float[] mAllRadius = new float[mCount]; //记录所有小圆半径 private int[] mAllColors = new int[mCount]; //记录所有小圆颜色 private float mMaxRadius; //小圆最大半径 private int mAnimateValue = 0; private Paint mPaint; //画笔 private int mSize; private int mColor; private long mDuration; private ValueAnimator mAnimator = null; public CustomLoadingView(Context context) { super(context); } public CustomLoadingView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); initAttrs(context, attrs); initPaint();//初始化画笔 initValue(); } public CustomLoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } private void initAttrs(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomLoadingView); mSize = (int) typedArray.getDimension(R.styleable.CustomLoadingView_custom_size, mSize); mColor = typedArray.getColor(R.styleable.CustomLoadingView_custom_color, mColor); mDuration = typedArray.getInt(R.styleable.CustomLoadingView_custom_duration, 1000); typedArray.recycle();//回收 Log.e("message", String.valueOf(mSize)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(mSize, mSize); } /** * 初始化所有加载圆半径、颜色 颜色绘制可改变透明度 */ private void initValue() { float mMinRadius = mSize / 20; Log.e("minCircleRadius", String.valueOf(mMinRadius)); for (int i = 0; i < mCount; i++) {//循环从0开始 所以降位 switch (i) { /** * 圆1 2 3 4 5 大小透明度一致 * 圆6 7 大小透明度增加 * 圆9大小透明度最大 * 圆10 8 大小一致透明度一致 倒数第二 */ case 9: mAllRadius[i] = mMinRadius * 2f; mAllColors[i] = (int) (255); break; case 8: case 10: mAllRadius[i] = mMinRadius * 1.75f; mAllColors[i] = (int) (255 * 0.9f); break; case 7: mAllRadius[i] = mMinRadius * 1.5f; mAllColors[i] = (int) (255 * 0.8f); break; case 6: mAllRadius[i] = mMinRadius * 1.25f; mAllColors[i] = (int) (255 * 0.7f); break; default: mAllRadius[i] = mMinRadius; mAllColors[i] = (int) (255 * 0.5f); break; } } mMaxRadius = mMinRadius * 2; } @Override protected void onDraw(Canvas canvas) { if (mSize > 0) { //mRotateValue * mAnimateValue角度,绘制所有小圆 canvas.rotate(mRotateValue * mAnimateValue, mSize / 2, mSize / 2);//以中心点旋转 直到整体旋转360度 for (int i = 0; i < mCount; i++) { //设置加载圆透明度 mPaint.setAlpha(mAllColors[i]); //每隔mRotateValue角度,绘制一个加载圆 canvas.drawCircle(mSize / 2, mMaxRadius, mAllRadius[i], mPaint);//绘制加载圆 canvas.rotate(mRotateValue, mSize / 2, mSize / 2);//旋转加载圆圆心间隔角度差 } } } /** * 开始动画 */ public void start() { if (mAnimator == null) {//关闭后还能运行 mAnimator = ValueAnimator.ofInt(0, mCount - 1); mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mAnimateValue = (int) animation.getAnimatedValue(); postInvalidate();//重绘刷新整个View } }); mAnimator.setDuration(mDuration); mAnimator.setRepeatMode(ValueAnimator.RESTART); mAnimator.setRepeatCount(ValueAnimator.INFINITE); mAnimator.start(); } else if (!mAnimator.isStarted()) { mAnimator.start(); } } /** * 关闭动画 */ public void stop() { if (mAnimator != null) { mAnimator.removeAllUpdateListeners(); mAnimator.cancel(); mAnimator = null;//设置关闭状态 } } /** * 初始化画笔 */ private void initPaint() { mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(mColor); } }
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.custom.customloadingview.CustomLoadingView android:id="@+id/customLoadingView" android:layout_width="wrap_content" android:layout_height="wrap_content" app:custom_color="@color/white" app:custom_size="100dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.385" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="正在加载..." android:textSize="15dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.501" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/customLoadingView" app:layout_constraintVertical_bias="0.032" /> <Button android:id="@+id/btn_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:width="100dp" android:text="结束" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/btn_start" app:layout_constraintTop_toBottomOf="@+id/customLoadingView" /> <Button android:id="@+id/btn_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="72dp" android:width="100dp" android:text="开始" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/customLoadingView" app:layout_constraintVertical_bias="0.501" /> </androidx.constraintlayout.widget.ConstraintLayout>
public class MainActivity extends AppCompatActivity { private Button btn_start; private Button btn_stop; private CustomLoadingView customLoadingView; @Override protected void onCreate(Bundle savedInstanceState) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//版本判断 Window window = getWindow(); // Translucent status bar window.setFlags( WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//设置statusbar应用所占的屏幕扩大到全屏,但是最顶上会有背景透明的状态栏,它的文字可能会盖着你的应用的标题栏 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_start = findViewById(R.id.btn_start); btn_stop = findViewById(R.id.btn_stop); customLoadingView=findViewById(R.id.customLoadingView); btn_start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { customLoadingView.start(); } }); btn_stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { customLoadingView.stop(); } }); } }
附上项目链接
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算