`

环形动画

 
阅读更多

今天貌似生病了……直接来代码

 

自定义View代码

package com.lizw.circular.wave;


import com.lizw.circular.R;
import com.lizw.circular.R.attr;
import com.lizw.circular.R.drawable;
import com.lizw.circular.R.styleable;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;


/**
 * 
 * @author Troy Lee
 *
 */
public class CircularView extends View {

	//背景圆所在的区域
    private final RectF mCircleBounds = new RectF();

//    //thumb所在举行
//    private final RectF mSquareRect = new RectF();
    //底层大圆的画笔
    private Paint mBackgroundColorPaint = null;
    //底层大圆边宽
    private int mCircleStrokeWidth = 10;
    private int mGravity = Gravity.CENTER;
    //Horizontal的内边界技术依赖于mGravity
    private int mHorizontalInset = 0;
    //Vertical的内边界技术依赖于mGravity
    private int mVerticalInset = 0;
    //所有属性设置完成为true,此时在Layout View时候将不会发生错误
    private boolean mIsInitializing = true;
    //thumb是否可见
    private boolean mIsThumbEnabled = true;
    //thumb沿着底层圆转的进度
    private float mProgress = 0.0f;
    //thumb沿着底层圆转前的路径颜色
    private int mProgressBackgroundColor;
    //thumb沿着底层圆转后留下的路径颜色
    private int mProgressColor;
    //thumb沿着底层圆转所用的画笔
    private Paint mProgressColorPaint;
    //底层大圆的半径
    private float mRadius;
    //thumb的画笔
    private Paint mThumbColorPaint = null;
    //thumb的坐标 x
    private float mThumbPosX;
    //thumb的坐 y
    private float mThumbPosY;
    //thumb的半径
    private int mThumbRadius = 20;
    //我们用自己坐标系统的变化偏移量X
    private float mTranslationOffsetX;
    //我们用自己坐标系统的变化偏移量Y
    private float mTranslationOffsetY;

    /**
     * Instantiates a new holo circular progress bar.
     *
     * @param context the context
     */
    public CircularView(final Context context) {
        this(context, null);
    }

    /**
     * Instantiates a new holo circular progress bar.
     *
     * @param context the context
     * @param attrs   the attrs
     */
    public CircularView(final Context context, final AttributeSet attrs) {
        this(context, attrs, R.attr.circularProgressBarStyle);
    }

    /**
     * Instantiates a new holo circular progress bar.
     *
     * @param context  the context
     * @param attrs    the attrs
     * @param defStyle the def style
     */
    public CircularView(final Context context, final AttributeSet attrs,
            final int defStyle) {
        super(context, attrs, defStyle);

        // load the styled attributes and set their properties
        final TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircularView,defStyle, 0);
        if (attributes != null) {
            try {
                setProgressColor(attributes.getColor(R.styleable.CircularView_progress_color, Color.CYAN));
                setProgressBackgroundColor(attributes.getColor(R.styleable.CircularView_progress_background_color,Color.GREEN));
                setProgress(attributes.getFloat(R.styleable.CircularView_progress, 0.0f));
                setWheelSize((int) attributes.getDimension(R.styleable.CircularView_stroke_width, 10));
                setThumbEnabled(attributes.getBoolean(R.styleable.CircularView_thumb_visible, true));

                mGravity = attributes.getInt(R.styleable.CircularView_android_gravity,Gravity.CENTER);
            } finally {
                // make sure recycle is always called.
                attributes.recycle();
            }
        }

        mThumbRadius = mCircleStrokeWidth * 2;
        mBackgroundColorPaint = new Paint();
        mThumbColorPaint = new Paint();
        updateBackgroundColor();
        updateProgressColor();
        // the view has now all properties and can be drawn
        mIsInitializing = false;

    }
    private Bitmap ballBitmap;

    @Override
    protected void onDraw(final Canvas canvas) {

        // All of our positions are using our internal coordinate system.
        // Instead of translating
        // them we let Canvas do the work for us.
        canvas.translate(mTranslationOffsetX, mTranslationOffsetY);

        final float progressRotation = getCurrentRotation();

//        // draw the background
        canvas.drawArc(mCircleBounds, 270, 360, false,mBackgroundColorPaint);

        if (isThumbEnabled()) {
        	// 根据进度画thumb图标转的路径
        	canvas.drawArc(mCircleBounds, 270, progressRotation, false,mProgressColorPaint);
        	//save()作用:在save()方法之前的全都保存,在save()方法之后,restore()方法之前的都清空。
        	canvas.save();
            // 将thumb图标初始位置放到0度
            canvas.rotate(progressRotation - 90);
//            // 将小方形图标正向旋转45度
//            canvas.rotate(45, mThumbPosX, mThumbPosY);
//            mSquareRect.left = mThumbPosX - mThumbRadius / 3;
//            mSquareRect.right = mThumbPosX + mThumbRadius / 3;
//            mSquareRect.top = mThumbPosY - mThumbRadius / 3;
//            mSquareRect.bottom = mThumbPosY + mThumbRadius / 3;
//            canvas.drawRect(mSquareRect, mThumbColorPaint);
            //设置thumb图标为小球
            ballBitmap = BitmapFactory.decodeStream(getResources().openRawResource(R.drawable.ic_detectiontrack));
            canvas.drawBitmap(ballBitmap, mThumbPosX-ballBitmap.getWidth()/2f, mThumbPosY - ballBitmap.getHeight()/2f, mThumbColorPaint);
            canvas.restore();
        }
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        final int height = getDefaultSize(getSuggestedMinimumHeight() + getPaddingTop() + getPaddingBottom() ,heightMeasureSpec);
        final int width = getDefaultSize(getSuggestedMinimumWidth() + getPaddingLeft() + getPaddingRight(), widthMeasureSpec);

        //所要画出圆形的目标直径
        final int diameter;
        if (heightMeasureSpec == MeasureSpec.UNSPECIFIED) {
            // ScrollView
            diameter = width;
            computeInsets(0, 0);
        } else if (widthMeasureSpec == MeasureSpec.UNSPECIFIED) {
            // HorizontalScrollView
            diameter = height;
            computeInsets(0, 0);
        } else {
            // Default
            diameter = Math.min(width, height);
            computeInsets(width - diameter, height - diameter);
        }

        setMeasuredDimension(diameter, diameter);

        
        final float halfDiameter = diameter * 0.5f;

        // 所画圆形的边宽
        final float drawedWith;
        if (isThumbEnabled()) {
            drawedWith = mThumbRadius * (5f / 6f);
        } else {
            drawedWith = mCircleStrokeWidth / 2f;
        }

        // 所要画圆形的半径;-10.5f 是为了更好的融入到RectF中,起到padding的作用
        mRadius = halfDiameter - drawedWith - 10.5f;

        mCircleBounds.set(-mRadius, -mRadius, mRadius, mRadius);
        

        mThumbPosX = (float) (mRadius * Math.cos(0));
        mThumbPosY = (float) (mRadius * Math.sin(0));

        mTranslationOffsetX = halfDiameter + mHorizontalInset;
        mTranslationOffsetY = halfDiameter + mVerticalInset;

    }


    public int getCircleStrokeWidth() {
        return mCircleStrokeWidth;
    }


    /**
     * gives the current progress of the ProgressBar. Value between 0..1 if you set the progress to
     * >1 you'll get progress % 1 as return value
     *
     * @return the progress
     */
    public float getProgress() {
        return mProgress;
    }

    /**
     * Gets the progress color.
     *
     * @return the progress color
     */
    public int getProgressColor() {
        return mProgressColor;
    }

    /**
     * @return true if the marker is visible
     */
    public boolean isThumbEnabled() {
        return mIsThumbEnabled;
    }

	/**
	 * Sets the progress.
	 * 
	 * @param progress
	 *            the new progress
	 */
	public void setProgress(final float progress) {

		if (progress >= 1.0f) {
			mProgress = 1.0f;
		} else {
			mProgress = progress % 1.0f;
		}

//		Log.e("", "progress is : " + progress + " ,mProgress is : " + mProgress);

		if (!mIsInitializing) {
			invalidate();
		}
	}

    /**
     * Sets the progress background color.
     *
     * @param color the new progress background color
     */
    public void setProgressBackgroundColor(final int color) {
        mProgressBackgroundColor = color;
        updateBackgroundColor();
    }

    /**
     * Sets the progress color.
     *
     * @param color the new progress color
     */
    public void setProgressColor(final int color) {
        mProgressColor = color;
        updateProgressColor();
    }

    /**
     * shows or hides the thumb of the progress bar
     *
     * @param enabled true to show the thumb
     */
    public void setThumbEnabled(final boolean enabled) {
        mIsThumbEnabled = enabled;
    }

    /**
     * Sets the wheel size.
     *
     * @param dimension the new wheel size
     */
    public void setWheelSize(final int dimension) {
        mCircleStrokeWidth = dimension;

        // update the paints
        updateBackgroundColor();
        updateProgressColor();
    }

    /**
     * Compute insets.
     *
     * <pre>
     *  ______________________
     * |_________dx/2_________|
     * |......| /'''''\|......|
     * |-dx/2-|| View ||-dx/2-|
     * |______| \_____/|______|
     * |________ dx/2_________|
     * </pre>
     *
     * @param dx the dx the horizontal unfilled space
     * @param dy the dy the horizontal unfilled space
     */
    @SuppressLint("NewApi")
    private void computeInsets(final int dx, final int dy) {
        int absoluteGravity = mGravity;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            absoluteGravity = Gravity.getAbsoluteGravity(mGravity, getLayoutDirection());
        }

        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
            case Gravity.LEFT:
                mHorizontalInset = 0;
                break;
            case Gravity.RIGHT:
                mHorizontalInset = dx;
                break;
            case Gravity.CENTER_HORIZONTAL:
            default:
                mHorizontalInset = dx / 2;
                break;
        }
        switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
            case Gravity.TOP:
                mVerticalInset = 0;
                break;
            case Gravity.BOTTOM:
                mVerticalInset = dy;
                break;
            case Gravity.CENTER_VERTICAL:
            default:
                mVerticalInset = dy / 2;
                break;
        }
    }

    /**
     * Gets the current rotation.
     *
     * @return the current rotation
     */
    private float getCurrentRotation() {
        return 360f * mProgress;
    }


    /**
     * updates the paint of the background
     */
    private void updateBackgroundColor() {
        mBackgroundColorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBackgroundColorPaint.setColor(mProgressBackgroundColor);
        mBackgroundColorPaint.setStyle(Paint.Style.STROKE);
        mBackgroundColorPaint.setStrokeWidth(mCircleStrokeWidth);

        invalidate();
    }


    /**
     * updates the paint of the progress and the thumb to give them a new visual style
     */
    private void updateProgressColor() {
        mProgressColorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mProgressColorPaint.setColor(mProgressColor);
        mProgressColorPaint.setStyle(Paint.Style.STROKE);
        mProgressColorPaint.setStrokeWidth(mCircleStrokeWidth);

        mThumbColorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mThumbColorPaint.setColor(mProgressColor);
        mThumbColorPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mThumbColorPaint.setStrokeWidth(mCircleStrokeWidth);

        invalidate();
    }


}

 

 Activity代码

package com.lizw.circular;


import com.lizw.circular.wave.CircularView;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;


/**
 * Troy Lee
 */
public class CircularActivity extends Activity {

    private static final String TAG = CircularActivity.class.getSimpleName();


    /**
     * The Switch button.
     */

    private CircularView circularView;
    private ObjectAnimator objAnimator;


    /*
     * (non-Javadoc)
     *
     * @see android.app.Activity#onCreate(android.os.Bundle)
     */
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        circularView = (CircularView) findViewById(R.id.circularView);
    }
    
    
    public void startAnimate(View view) {
    	animate(circularView,new AnimatorListener() {

    		 @Override
             public void onAnimationCancel(final Animator animation) {
             	circularView.setProgress(0.0f);
             }

             @Override
             public void onAnimationEnd(final Animator animation) {
             	circularView.setProgress(1.0f);
             }

             @Override
             public void onAnimationRepeat(final Animator animation) {
             }

             @Override
             public void onAnimationStart(final Animator animation) {
             	circularView.setProgress(0.0f);
             }
        });
    	
    	
//    	new Handler().postDelayed(new Runnable() {
//			
//			@Override
//			public void run() {
//				// TODO Auto-generated method stub
//				if(objAnimator != null){
//					objAnimator.cancel();
//					
//					circularView.setProgress(0.0f);
//				}
//			}
//		}, 3000);
    	
    }
    
    
    /**
     * Animate.
     *
     * @param progressBar the progress bar
     * @param listener    the listener
     */
    private void animate(final CircularView circularView,final AnimatorListener listener) {
        final float progress = 1.00f;
        int duration = 5000;
        circularView.setProgress(0.0f);
        animate(circularView, listener, progress, duration);
    }

    private void animate(final CircularView circularView, final AnimatorListener listener,final float progress, final int duration) {

    	objAnimator = ObjectAnimator.ofFloat(circularView, "progress", progress);
        objAnimator.setDuration(duration);

        objAnimator.addListener(new AnimatorListener() {

            @Override
            public void onAnimationCancel(final Animator animation) {
            	circularView.setProgress(0.0f);
            }

            @Override
            public void onAnimationEnd(final Animator animation) {
            	circularView.setProgress(1.0f);
            }

            @Override
            public void onAnimationRepeat(final Animator animation) {
            }

            @Override
            public void onAnimationStart(final Animator animation) {
            	circularView.setProgress(0.0f);
            }
        });
        if (listener != null) {
        	objAnimator.addListener(listener);
        }
       
        objAnimator.addUpdateListener(new AnimatorUpdateListener() {

        	float count = 0.0f;
            @Override
            public void onAnimationUpdate(final ValueAnimator animation) {
            	count=0.01f;
            	circularView.setProgress(count);
            }
        });
//        circularView.setMarkerProgress(progress);
        objAnimator.start();
        
        
    }

}

 attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="CircularView">
        <attr name="stroke_width" format="dimension" />
        <attr name="progress" format="float" />
        <attr name="progress_color" format="color" />
        <attr name="progress_background_color" format="color" />
        <attr name="thumb_visible" format="boolean" />
        <attr name="android:gravity" />
        
    
    </declare-styleable>

    <attr name="circularStyle" format="reference" />

</resources>

 styles.xml

<resources xmlns:android="http://schemas.android.com/apk/res/android">
    
    <style name="Circular">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">match_parent</item>
        <item name="stroke_width">5dp</item>
        <item name="progress" format="float">0</item>
        <item name="progress_color">#46A4EC</item>
        <item name="progress_background_color">#adff2f</item>
        <item name="thumb_visible">true</item>
    </style>
    
    <style name="CircularLight">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">match_parent</item>
        <item name="stroke_width">5dp</item>
        <item name="progress" format="float">0</item>
        <item name="progress_color">#46A4EC</item>
        <item name="progress_background_color">#adff2f</item>
        <item name="thumb_visible">true</item>
    </style>
</resources>

 themes.xml

<resources>
    <!-- Application theme. -->
    <style name="AppTheme" parent="android:Theme.Holo">
        <item name="circularStyle">@style/Circular</item>
    </style>
    
    <style name="AppThemeLight" parent="android:Theme.Holo.Light">
        <item name="circularStyle">@style/CircularLight</item>
    </style>
</resources>

 activity_home.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/com.lizw.circular"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:orientation="vertical" >

    <com.lizw.circular.wave.CircularView
        android:id="@+id/circularView"
        android:layout_marginTop="20dp"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        app:progress="0" />
    
    <Button 
        android:layout_marginTop="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="startAnimate"
        android:text="试试动画"/>

</LinearLayout>

 运行效果



 

 

  • 大小: 324.3 KB
  • 大小: 78.5 KB
  • 大小: 4.4 KB
分享到:
评论

相关推荐

    环形动画进度数字时钟.rar

    环形动画进度数字时钟是一种视觉效果独特的时间显示方式,它将传统的数字时钟与动态的环形进度条相结合,创造出既美观又直观的时钟界面。这种设计常见于现代的用户界面(UI)和应用设计中,尤其适用于增强用户交互...

    环形动画菜单特效代码

    环形动画菜单特效是一种利用CSS3技术实现的创新交互设计,它为网站的导航菜单带来了独特的视觉体验。这种菜单在静止状态下呈现环形布局,当用户点击中心按钮时,子菜单会按照特定的动画效果从中心向外展开,提供丰富...

    C#的环形动画进度控件

    C#,环形,动画,进度控件,C#的环形动画进度控件 C#,环形,动画,进度控件,C#的环形动画进度控件 C#,环形,动画,进度控件,C#的环形动画进度控件 C#,环形,动画,进度控件,C#的环形动画进度控件 C#,环形,动画,进度控件,C#的...

    CSS3二级环形动画菜单.zip

    本案例"CSS3二级环形动画菜单.zip"正是利用这些特性来创建一个独特且吸引人的交互式菜单。 首先,我们要理解"二级环形动画菜单"的概念。这通常指的是一个主菜单项周围分布着子菜单项,当用户悬停在主菜单项上时,子...

    HTML5/CSS3超酷环形动画菜单

    今天我们要分享一款非常有创意的HTML5/CSS3动画菜单,菜单是环形的,当鼠标点击中心按钮时,子菜单即会环绕展开,并伴随很酷的菜单展开动画。记得之前还分享过一款HTML5/CSS3实现iOS Path菜单,也是环形的菜单,动画...

    H5 CSS3环形动画

    "H5 CSS3环形动画"这个主题,就是关于如何利用这两种技术来创建引人注目的环形动画效果。这篇博客文章可能是探讨如何通过CSS3的动画属性和HTML5的结构元素,来实现这种视觉上的创新。 首先,我们来了解一下HTML5。...

    一款环形动画导航菜单jquery插件

    环形动画导航菜单jQuery插件是一款用于网页交互设计的工具,它通过JavaScript库jQuery实现,为网站的导航菜单带来独特的视觉效果。这款插件利用HTML、CSS和JavaScript技术,将传统线性的导航菜单转变为环形布局,...

    环形动画效果导航菜单

    环形动画效果导航菜单是一种独特且引人注目的网页交互设计,它利用jQuery和CSS技术为用户提供了非线性的导航体验。这种设计通常用于展示多个主要功能或分类,以一个中心点为轴心,菜单项以环形排列,通过动态的过渡...

    html5 canvas 3D方块环形动画特效

    在“html5 canvas 3D方块环形动画特效”这个项目中,我们主要探讨的是如何利用Canvas API创建一个立体的3D方块环形动画,其中每个方块的六个面颜色各异,并且可以通过鼠标交互来实现全方位的旋转控制。 首先,要...

    仿招行信用卡已出账单环形动画效果

    "仿招行信用卡已出账单环形动画效果"是一种创新的UI设计,它能够以动态且直观的方式展示用户的信用卡账单状态。这种动画效果通常应用于移动应用或者网页中,让用户能够一目了然地了解自己的消费情况。 环形动画的...

    css简单实现环形动画效果,无需js

    在CSS世界中,创建动态和引人入胜的视觉效果是一项常见的挑战,而环形动画则是其中一种吸引眼球的设计元素。本教程将详细介绍如何仅使用CSS来实现这种效果,无需JavaScript的介入,使得动画在移动端和PC端都有良好的...

    垂直循环滚动,环形动画进度条

    在iOS开发中,实现“垂直循环滚动,环形动画进度条”的功能,通常涉及到自定义UI组件和动画处理。这个功能结合了两个重要的视觉元素:一个垂直方向的跑马灯效果,以及一个环形动画进度条。下面我们将深入探讨这两个...

    CSS3超酷环形动画菜单.zip

    "CSS3超酷环形动画菜单"就是一个很好的例子,它利用了CSS3的高级特性,如选择器、转换(transform)、过渡(transition)和动画(animation),来实现一个独特且引人注目的菜单导航。 首先,CSS3的选择器使得我们...

    Canvas 3D方块环形动画特效.zip

    在这个“Canvas 3D方块环形动画特效”中,用户可以看到环形排列的3D方块在网页上进行流畅的旋转,这种动态效果极大地提升了网页的视觉冲击力和互动性。 文件名"jiaoben6902"可能是源代码或资源文件的名称,通常在...

    flash环形动画

    "Flash环形动画"是一个特定的领域,它涉及到使用Adobe Flash软件来创建动态的环状图形,这种图形常用于表示进度条加载效果。下面将详细阐述Flash环形动画的制作过程、相关技术以及其在实际应用中的价值。 首先,...

    经典载入环形动画进度控件的C#源码

    本项目名为"经典载入环形动画进度控件的C#源码",主要关注的是在C#环境下,使用Visual Studio 2005开发的一款动画进度指示器。 进度控件是用户界面中的常见元素,用于向用户展示操作的进度或等待状态。在这个项目中...

    CSS3超酷环形动画菜单其子菜单可环绕展开.zip

    在“CSS3超酷环形动画菜单其子菜单可环绕展开”这个主题中,我们主要关注的是如何利用CSS3来创建一种创新且引人注目的交互式菜单设计。 首先,环形布局在UI设计中并不常见,但它可以为网站带来独特的视觉效果。要...

Global site tag (gtag.js) - Google Analytics