package UICtrl;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.view.animation.Interpolator;
import android.graphics.Paint;
import android.graphics.PointF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.RelativeLayout; /**
* Created by wangchaomac on 2017/10/18.
*/
public class AroundCircleBall extends RelativeLayout { private BallView mBall; //角度
private float mBallRadius; //小球的颜色
private int mBallColor; private int mCircleRadius; private int mCircleColor; private int mDuration; //笔头描宽
private float mStrokeWidth; private int mInterpolator; private final int ACCELERATE_DECELERATE_INTERPOLATOR = 1; private final int LINEAR_INTERPOLATOR = 2; private final int ACCELERATE = 3; private final int DECELERATE = 4; ObjectAnimator mRotateAnim; PointF mCircleCenterPoint = new PointF(mCircleRadius + mBallRadius, mCircleRadius + mBallRadius);
Paint mPaint = new Paint(); public AroundCircleBall(Context context, AttributeSet attrs){ super(context, attrs);
// TODO Auto-generated constructor stub
init(context); } private void init(Context context){
init();
}
private void init() { mBall = new BallView(getContext());
mBall.setRadius(mBallRadius);
mBall.setBallColor(mBallColor);
//小球的初始位置在圆环的最底部
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); }
@Override
protected 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);
} protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//测量控件宽高
int width = (int) (getPaddingLeft() + mCircleRadius * 2 + mBallRadius * 2 + getPaddingRight());
int height = (int) (getPaddingTop() + mCircleRadius * 2 + mBallRadius * 2 + getPaddingBottom());
setMeasuredDimension(width, height);
} private void initRotateAnim(){
mRotateAnim = ObjectAnimator.ofFloat(mBall, "rotation", 0f, 360f);
//计算小球旋转的中心点(此点的左边是在小球自身的坐标系中)
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);
} 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;
} /**
* 启动旋转动画
*/ public void startRotate(){
if (mRotateAnim != null){
mRotateAnim.start();
}
} /**
* 暂停旋转动画
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void pauseRotate(){
if (mRotateAnim != null && mRotateAnim.isRunning()){
mRotateAnim.pause();
}
} /**
* 取消旋转动画
*/
public void cancelRotate(){
if (mRotateAnim != null){
mRotateAnim.cancel();
}
}
}
package UICtrl;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.View; /**
* Created by wangchaomac on 2017/10/18.
*/
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;
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources><!--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>
<!--设置旋转一周需要的时间(单位为秒)-->
<attr name="rotate_duration" format="integer"></attr>
<!--设置旋转动画的补间器-->
<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></resources>

androidcode的更多相关文章

  1. 编译android 4.4.2

    1.获取Android源码 (1)下载repo 在用户目录下创建一个bin文件夹来存放repo,并把该路径设置到环境变量中 mkdir ~/bin PATH=~/bin:$PATH 下载repo脚本 ...

  2. android 通过eclipse混淆代码 打包 + proguard 总结

    android应用程序的混淆打包 1 . 在工程文件project.properties中加入下proguard.config=proguard.cfg , 如下所示: target=android- ...

  3. Android Studio添加应用作为依赖时报错Error:Dependency MonthText:xlistview:unspecified on project app resolves to an APK archive which is not supported as a compilation dependency. File: 及其解决方案

    Error:Dependency MonthText:xlistview:unspecified on project app resolves to an APK archive which is ...

  4. android 混淆配置

    proguard 原理Java代码编译成二进制class 文件,这个class 文件也可以反编译成源代码 ,除了注释外,原来的code 基本都可以看到.为了防止重要code 被泄露,我们往往需要混淆( ...

  5. vue中使用swiper-slide时,循环轮播失效?

    前言 vue 项目中使用时,组件swiper-slide 如果用v-for循环的话,loop:true 就不能无缝轮播,每次轮播到最后一张就停止了??? 正文 代码如下: <swiper :op ...

  6. android 混淆 与 反编译

    1, 文件 project.properties 修改: target=android-14proguard.config=${sdk.dir}/tools/proguard/proguard-and ...

  7. Android中怎样调用拨打电话?

    Android系统原本就为手机设计,所以,在android系统中的不论什么App中,仅仅要愿意,拨打指定电话很方便. 核心就是使用Intent跳转,指定请求Action为Intent.ACTION_C ...

  8. Android开发学习之反编译APK文件

    反编译的目的在于学习一些优秀的Android应用程序代码. 在进行反编译之前,需要准备好下面的软件工具(这些文件都放在同一文件下): 这些工具的下载地址:http://down.51cto.com/d ...

  9. android发送短信样例

    Android应用开发中我们经常须要发送手机短信.这对于android平台来说,是最简单只是的功能了,无需太多代码,也无需自己定义代码,仅仅须要调用android提供的消息管理类SmsManager就 ...

随机推荐

  1. iOS开发ApplePay的介绍与实现

    1.Apple Pay的介绍 Apple Pay官方 1.1 Apple Pay概念 Apple Pay,简单来说, 就是一种移动支付方式.通过Touch ID/ Passcode,用户可使用存储在i ...

  2. CSAPP阅读笔记-变长栈帧,缓冲区溢出攻击-来自第三章3.10的笔记-P192-P204

    一.几个关于指针的小知识点: 1.  malloc是在堆上动态分配内存,返回的是void *,使用时会配合显式/隐式类型转换,用完后需要用free手动释放. alloca是标准库函数,可以在栈上分配任 ...

  3. LCA(最近公共祖先)

    学习链接:https://baike.baidu.com/item/%E4%BC%B8%E5%B1%95%E6%A0%91/7003945?fr=aladdin 求LCA的方法有很多,在这里就只介绍一 ...

  4. 持续集成Jenkins入门【截图】

  5. 【CSS】CSS Sprites (CSS 精灵) 技术

    CSS Sprites CSS Sprites在国内很多人叫css精灵,是一种网页图片应用处理方式.它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去,这样一来,当访问该页面时,载入的图片就不 ...

  6. wordpress编辑器选择ckeditor、ckfinder

    CKEditor for WordPress 搜索安装 上传功能需要ckfinder 下载 CKFinder for PHP: http://ckfinder.com/download 上传ckfin ...

  7. JVM, JRE,JDK 的区别

    在网上看到一篇讲解jvm,jre,jdk区别的文章,感觉不错,就收藏到自己的博客了. 1.JVM -- java virtual machine JVM就是我们常说的java虚拟机,它是整个java实 ...

  8. Golang教程:包

    什么是包?为什么使用包? 到目前为止我们见到的 Go 程序都只有一个文件,文件中包含了一个main函数和几个其他函数.在实际中这种将所有代码都放在一个文件里的组织方式是不可行的.这样的组织方式使得代码 ...

  9. 不能修改列 "。。",因为它是计算列,或者是 UNION 运算符的结果。

    修改Mapping this.Property(t => t...).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotatio ...

  10. .Net程序员玩转Android系列之二~Android Framework概要(1)

    从windows操作系统说起 人们总是喜欢从将陌生的事物和自己所了解的东西关联起来,以加深对未知事物的了解,这一讲我们从windows操作系统说起,逐步引领带大家走入android的世界.写任何程序都 ...