日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

自定义控件-绕着圆形轨迹旋转的小球

發(fā)布時(shí)間:2025/6/17 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自定义控件-绕着圆形轨迹旋转的小球 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://blog.csdn.net/xingxing_yan/article/details/54730068 轉(zhuǎn)載

http://www.cnblogs.com/jiayongji/p/5560806.html

一. 概述

用過華為手機(jī)的人應(yīng)該知道華為手機(jī)系統(tǒng)應(yīng)用中的加載動(dòng)畫是一個(gè)小球繞著圓圈旋轉(zhuǎn),之前有一個(gè)項(xiàng)目用過類似的功能,所以寫了一個(gè)自定義的控件,記錄一下。希望能給需要這個(gè)功能的同志們提供一些思路。先上效果圖:?

二. 思路

我們分析一下,一個(gè)小球繞著圓運(yùn)動(dòng),首先需要一個(gè)小球,那么自定義控件繪制一個(gè)小球。然后需要一個(gè)圓環(huán),最后設(shè)置小球在圓環(huán)上的一個(gè)起始位置,執(zhí)行旋轉(zhuǎn)動(dòng)畫即可。接下來就開始動(dòng)手吧。

三. 實(shí)現(xiàn)

1. 繪制小球

繪制小球很簡(jiǎn)單,自定義一個(gè)控件,重寫onDraw方法,繪制一個(gè)實(shí)心圓就好,這里就不多說了,直接上代碼:?
BallView:

public class BallView extends View { private int mBallColor = Color.BLACK; private float mRadius = 10f; private PointF mCenterPoint; private Paint mPaint; public BallView(Context context) { this(context, null); } public BallView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init(){ mPaint = new Paint(); mPaint.setAntiAlias(true); mCenterPoint = new PointF(mRadius, mRadius); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = (int) (getPaddingLeft() + 2*mRadius + getPaddingRight()); int height = (int) (getPaddingTop() + 2*mRadius + getPaddingBottom()); setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(mBallColor); canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mRadius, mPaint); } public void setBallColor(int mBallColor) { this.mBallColor = mBallColor; } public void setRadius(float radius) { this.mRadius = radius; mCenterPoint.set(radius, radius); } public float getRadius() { return mRadius; } }

1

  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

2. 實(shí)現(xiàn)圓形軌跡

(1) 寫一個(gè)控件AroundCircleBall繼承RelativeLayout,然后在此控件中繪制一個(gè)圓環(huán)

//圓形軌跡的中心的(圓的半徑+小球的半徑) mCircleCenterPoint = new PointF(mCircleRadius + mBallRadius, mCircleRadius + mBallRadius); ... @Overrideprotected void onDraw(Canvas canvas) { //繪制圓 mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(mStrokeWidth); mPaint.setColor(mCircleColor); canvas.drawCircle(mCircleCenterPoint.x, mCircleCenterPoint.y, mCircleRadius, mPaint); super.onDraw(canvas); }

因?yàn)樾∏虻闹行狞c(diǎn)在圓形軌跡上,所以整個(gè)AroundCircleBall的寬度和高度都是圓形軌跡的半徑+小球的半徑

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //測(cè)量控件寬高 int width = (int) (getPaddingLeft() + mCircleRadius * 2 + mBallRadius * 2 + getPaddingRight()); int height = (int) (getPaddingTop() + mCircleRadius * 2 + mBallRadius * 2 + getPaddingBottom()); setMeasuredDimension(width, height); }

?

(2) 添加小球到AroundCircleBall中,計(jì)算初始位置,初始位置在圓的最底部。

private void init() {...mBall = new BallView(getContext());mBall.setRadius(mBallRadius);mBall.setBallColor(mBallColor);//小球的初始位置在圓環(huán)的最底部 LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); params.leftMargin = (int) (mCircleRadius); params.topMargin = (int) (mCircleRadius * 2); mBall.setLayoutParams(params); addView(mBall); ... }

?

到此,我們圓環(huán)和小球的初始化都做完了,就下來就是讓小球繞著圓形軌跡旋轉(zhuǎn)。?
(3) 旋轉(zhuǎn)動(dòng)畫:?
小球需要繞著圓環(huán)旋轉(zhuǎn),我們首先需要計(jì)算旋轉(zhuǎn)的中心。View中提供兩個(gè)方法setPivotX()和 setPivotY() 方法來設(shè)置要旋轉(zhuǎn)View的中心點(diǎn)。這里注意一下,pivotX和pivotY的坐標(biāo)點(diǎn)是相對(duì)View自身坐標(biāo)系的,如果使用屏幕坐標(biāo)系可能會(huì)出現(xiàn)位置錯(cuò)亂。?

private void initRotateAnim(){mRotateAnim = ObjectAnimator.ofFloat(mBall, "rotation", 0f, 360f); //計(jì)算小球旋轉(zhuǎn)的中心點(diǎn)(此點(diǎn)的左邊是在小球自身的坐標(biāo)系中) float pivotX = mBall.getRadius(); float pivotY = mBall.getRadius() - mCircleRadius; mBall.setPivotX(pivotX); mBall.setPivotY(pivotY); mRotateAnim.setDuration(mDuration); mRotateAnim.setInterpolator(getInterpolator()); mRotateAnim.setRepeatCount(-1); mRotateAnim.setStartDelay(500); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

提供四種設(shè)置動(dòng)畫的補(bǔ)間器:先加速在減速,勻速,加速,減速

private Interpolator getInterpolator(){Interpolator interpolator = null;switch (mInterpolator){case ACCELERATE_DECELERATE_INTERPOLATOR: //先加上后減速 interpolator = new AccelerateDecelerateInterpolator(); break; case LINEAR_INTERPOLATOR: //勻速 interpolator = new LinearInterpolator(); break; case ACCELERATE: //加速 interpolator = new AccelerateInterpolator(); break; case DECELERATE: //減速 interpolator = new DecelerateInterpolator(); break; } return interpolator; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

最后就是對(duì)動(dòng)畫的操作,提供啟動(dòng),暫停,取消三個(gè)方法:

/*** 啟動(dòng)旋轉(zhuǎn)動(dòng)畫*/public void startRotate(){if (mRotateAnim != null){ mRotateAnim.start(); } } /** * 暫停旋轉(zhuǎn)動(dòng)畫 */ @RequiresApi(api = Build.VERSION_CODES.KITKAT) public void pauseRotate(){ if (mRotateAnim != null && mRotateAnim.isRunning()){ mRotateAnim.pause(); } } /** * 取消旋轉(zhuǎn)動(dòng)畫 */ public void cancelRotate(){ if (mRotateAnim != null){ mRotateAnim.cancel(); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

到此,整個(gè)自定義控件AroundCircleBall就寫完了,接下來就用吧。?
(4) 使用?
布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/activity_main"android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.yyx.simple.MainActivity"> <com.yyx.mylibrary.widget.AroundCircleBall android:id="@+id/main_acb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:layout_centerInParent="true" app:ball_color="@android:color/holo_green_light" app:ball_radius="5dp" app:circle_color="@android:color/holo_blue_light" app:circle_width="1dp" app:circle_radius="40dp" app:rotate_duration="5" app:rotate_interpolator="accelerate_decelerate"/> </RelativeLayout>

?

在代碼中啟動(dòng)動(dòng)畫:

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mAcb = (AroundCircleBall) findViewById(R.id.main_acb);mAcb.startRotate();}

?

真?zhèn)€過程并沒有很難的地方,唯一需要注意的就是旋轉(zhuǎn)中心點(diǎn)是要被旋轉(zhuǎn)的View自身坐標(biāo)系中的點(diǎn),不是屏幕坐標(biāo)系的。?
(5) 可以看到上邊的布局文件中有一些屬性是自定義的,方便我們?cè)诓季治募性O(shè)置一些參數(shù),自定義屬性如下:

<!--AroundCircleBall自定義屬性--><declare-styleable name="AroundCircleBall"> <!--繪制圓形軌跡的線寬--> <attr name="circle_width" format="dimension"></attr> <!--繪制圓形軌跡的顏色--> <attr name="circle_color" format="color"></attr> <!--圓形軌跡的半徑--> <attr name="circle_radius" format="dimension"></attr> <!--小球的顏色--> <attr name="ball_color" format="color"></attr> <!--小球的半徑--> <attr name="ball_radius" format="dimension"></attr> <!--設(shè)置旋轉(zhuǎn)一周需要的時(shí)間(單位為秒)--> <attr name="rotate_duration" format="integer"></attr> <!--設(shè)置旋轉(zhuǎn)動(dòng)畫的補(bǔ)間器--> <attr name="rotate_interpolator" format="enum"> <enum name="accelerate_decelerate" value="1"/> <enum name="linear" value="2"/> <enum name="accelerate" value="3"/> <enum name="decelerate" value="4"/> </attr> </declare-styleable>


http://blog.csdn.net/u010800708/article/details/49780085 另外一個(gè)例子

轉(zhuǎn)載于:https://www.cnblogs.com/wcLT/p/7689486.html

總結(jié)

以上是生活随笔為你收集整理的自定义控件-绕着圆形轨迹旋转的小球的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。