自定義控制元件之仿雅虎新聞載入
阿新 • • 發佈:2019-01-02
分析:
1.先畫固定不動的圓,圍成一個大圓,均勻分佈在外圓上
2.開始旋轉屬性動畫,獲取旋轉的角度3.開始內聚動畫,就是位移動畫,向大圓圓心移動
4.水波紋效果,就是strokeWidth型別的圓向外移動,半徑不斷變大
public class SplashLoadingView extends View { private SplashState mSplashState; private float mRotationRadius; // 是否初始化引數 private boolean mIsInitParams = false; // 繪製圓的畫筆 private Paint mPaint = new Paint(); // 繪製背景的畫筆 private Paint mPaintBackground = new Paint(); // 當前大圓旋轉的角度(弧度) private float mCurrentRotationAngle = 0F; private final long ROTATION_ANIMATION_TIME = 2000; // 第二部分動畫執行的總時間 (包括三個動畫的時間) private final long SPLASH_ANIMATION_TIME = 1200; private float mCircleRadius; private int mCenterX; private int mCenterY; private int[] mCircleColors; // 整體的顏色背景 private int mSplashColor = Color.WHITE; private float mCurrentRotationRadius; // 空心圓初始半徑 private float mHoleRadius = 0F; //螢幕對角線的一半 private float mScreenDis; public SplashLoadingView(Context context) { this(context, null); } public SplashLoadingView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public SplashLoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (!mIsInitParams) { initPatams(); } if (mSplashState == null) { mSplashState = new RotationState(); } mSplashState.draw(canvas); } private void initPatams() { int width = getMeasuredWidth(); //大圓的半徑 mRotationRadius = width / 4; mCircleRadius = mRotationRadius / 8; //螢幕中心位置 mCenterX = width / 2; mCenterY = getMeasuredHeight() / 2; mScreenDis = (float) Math.sqrt(mCenterX * mCenterX + mCenterY * mCenterY); //小圓顏色列表 mCircleColors = getContext().getResources().getIntArray(R.array.splash_circle_colors); //初始化畫筆 mPaint.setDither(true); mPaint.setAntiAlias(true); mPaintBackground.setDither(true); mPaintBackground.setAntiAlias(true); mPaintBackground.setColor(mSplashColor); } public void disappear() { if (mSplashState instanceof RotationState) { RotationState splashState = (RotationState) mSplashState; splashState.cancelAnimator(); mSplashState = new MergeState(); } } private abstract class SplashState { public abstract void draw(Canvas canvas); } /** * 繪製小圓旋轉動畫 */ private class RotationState extends SplashState { private ValueAnimator mValueAnimator; public RotationState() { //旋轉屬性動畫 mValueAnimator = ValueAnimator.ofFloat(0, (float) (Math.PI * 2)); mValueAnimator.setDuration(ROTATION_ANIMATION_TIME); mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mCurrentRotationAngle = (float) animation.getAnimatedValue(); invalidate(); } }); mValueAnimator.setRepeatCount(-1); mValueAnimator.setInterpolator(new LinearInterpolator()); mValueAnimator.start(); } @Override public void draw(Canvas canvas) { //畫整個背景 canvas.drawColor(mSplashColor); //繪製六個圓 float preAngle = (float) (2 * Math.PI / mCircleColors.length); for (int i = 0; i < mCircleColors.length; i++) { mPaint.setColor(mCircleColors[i]); //初始角度+旋轉角度 double angle = i * preAngle + mCurrentRotationAngle; float cx = (float) (mCenterX + mRotationRadius * Math.cos(angle)); float cy = (float) (mCenterY + mRotationRadius * Math.sin(angle)); canvas.drawCircle(cx, cy, mCircleRadius, mPaint); } } public void cancelAnimator() { mValueAnimator.cancel(); mValueAnimator = null; } } /** * 小圓的聚合動畫 */ private class MergeState extends SplashState { private ValueAnimator mValueAnimator; public MergeState() { mValueAnimator = ValueAnimator.ofFloat(mRotationRadius, 0); mValueAnimator.setDuration(SPLASH_ANIMATION_TIME / 2); mValueAnimator.setInterpolator(new AnticipateInterpolator(6f)); mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mCurrentRotationRadius = (float) animation.getAnimatedValue(); invalidate(); } }); mValueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mSplashState = new ExpandingState(); } }); mValueAnimator.start(); } @Override public void draw(Canvas canvas) { //畫整個背景 canvas.drawColor(mSplashColor); //繪製六個圓 float preAngle = (float) (2 * Math.PI / mCircleColors.length); for (int i = 0; i < mCircleColors.length; i++) { mPaint.setColor(mCircleColors[i]); //初始角度+旋轉角度 double angle = i * preAngle + mCurrentRotationAngle; float cx = (float) (mCenterX + mCurrentRotationRadius * Math.cos(angle)); float cy = (float) (mCenterY + mCurrentRotationRadius * Math.sin(angle)); canvas.drawCircle(cx, cy, mCircleRadius, mPaint); } } } /** * 圓的擴散動畫 */ private class ExpandingState extends SplashState { private ValueAnimator mValueAnimator; public ExpandingState() { mValueAnimator = ObjectAnimator.ofFloat(0, mScreenDis); mValueAnimator.setDuration(ROTATION_ANIMATION_TIME / 2); mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mHoleRadius = (float) animation.getAnimatedValue(); invalidate(); } }); mValueAnimator.start(); } @Override public void draw(Canvas canvas) { float strokeWidth = mScreenDis - mHoleRadius; mPaint.setStrokeWidth(strokeWidth); mPaint.setColor(mSplashColor); mPaint.setStyle(Paint.Style.STROKE); float radius =strokeWidth/2+mHoleRadius; canvas.drawCircle(mCenterX,mCenterY,radius,mPaint); } } }
activity_main佈局如下
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <include layout="@layout/fragment_page_first"/> <com.example.ex_chenmengjia001.myview.view.SplashLoadingView android:id="@+id/thirdScreenView" android:layout_width="match_parent" android:layout_height="match_parent" tools:layout_editor_absoluteY="8dp" tools:layout_editor_absoluteX="8dp" /> </RelativeLayout>
fragment_page_first佈局如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/fragment_page_first"/>
<com.example.ex_chenmengjia001.myview.view.SplashLoadingView
android:id="@+id/thirdScreenView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteY="8dp"
tools:layout_editor_absoluteX="8dp" />
</RelativeLayout>
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
final SplashLoadingView splashView = (SplashLoadingView) findViewById(R.id.thirdScreenView);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
splashView.disappear();
}
},2000);
}
}