`

关于旋转动画效果

 
阅读更多
好久没有写过blog了,5.1还在继续劳动,:(
刚研究完一个旋转动画的,困扰了我很久的一个问题,现在终于解决了,放在这里给大家分享,避免大家走我一样的弯路,:)
Main.java:
Java代码 
public class Main extends Activity {  
 
    private com.example.view.RoundSpinView mSelfView;  
 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        mSelfView = (com.example.view.RoundSpinView) findViewById(R.id.mSelfView);  
        mSelfView.setmPointX(160);  
        mSelfView.setmPointY(150);  
        mSelfView.setmRadius(80);  
        mSelfView.fixBoxPosition();  
    }  


public class Main extends Activity {

private com.example.view.RoundSpinView mSelfView;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSelfView = (com.example.view.RoundSpinView) findViewById(R.id.mSelfView);
mSelfView.setmPointX(160);
mSelfView.setmPointY(150);
mSelfView.setmRadius(80);
mSelfView.fixBoxPosition();
}
}



自定义View,实现旋转动画:
RoundSpinView.java:
Java代码 
public class RoundSpinView extends View {  
 
    private Paint mPaint = new Paint();  
    private static final int STONE_COUNT = 4;  
    /** 4张图片分布的角度均值 */ 
    private int mDegreeDelta;  
    private float mDown_x, mDown_y;  
 
    private int[] mResourceId = { R.drawable.customer, R.drawable.product,  
            R.drawable.order, R.drawable.info };  
 
    public RoundSpinView(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        mPaint.setColor(Color.RED);  
        mPaint.setStrokeWidth(2);  
        setupStones();  
        computeCoordinates();  
    }  
 
    /** 初始化每个旋转图片的坐标位置及图片资源 */ 
    private void setupStones() {  
        mStones = new BigStone[STONE_COUNT];  
        BigStone stone;  
        int angle = 0;  
        mDegreeDelta = 360 / STONE_COUNT;  
 
        for (int index = 0; index < STONE_COUNT; index++) {  
            stone = new BigStone();  
            stone.angle = angle;  
            stone.bitmap = BitmapFactory.decodeResource(getResources(),  
                    mResourceId[index]);  
            angle += mDegreeDelta;  
            mStones[index] = stone;  
        }  
    }  
 
    /** 计算每个旋转图片坐标 */ 
    private void computeCoordinates() {  
        BigStone stone;  
        for (int index = 0; index < STONE_COUNT; index++) {  
            stone = mStones[index];  
            if (stone.angle >= 360) {  
                stone.angle -= 360;  
            }  
            stone.x = mPointX  
                    + (float) (mRadius * Math.cos(stone.angle * Math.PI / 180));  
            stone.y = mPointY  
                    + (float) (mRadius * Math.sin(stone.angle * Math.PI / 180));  
        }  
    }  
 
    public RoundSpinView(Context context) {  
        super(context);  
    }  
 
    private BigStone[] mStones;  
 
    /** 旋转的中心点 */ 
    private int mPointX = 0, mPointY = 0;  
    /** 旋转半径 */ 
    private int mRadius = 0;  
 
    private int[] mInts = new int[] { 0, 0, 0, 0 };  
    /** 标识那个图片应该位于正中间 */ 
    private int mIn;  
 
    public int getmRadius() {  
        return mRadius;  
    }  
 
    public void setmRadius(int mRadius) {  
        this.mRadius = mRadius;  
    }  
 
    public int getmPointX() {  
        return mPointX;  
    }  
 
    public void setmPointX(int mPointX) {  
        this.mPointX = mPointX;  
    }  
 
    public int getmPointY() {  
        return mPointY;  
    }  
 
    public void setmPointY(int mPointY) {  
        this.mPointY = mPointY;  
    }  
 
    /** Sort the elements in one array. */ 
    public static void sort(int[] data) {  
        int len = data.length;  
        for (int i = 0; i < len - 1; i++) {  
            int temp = 0;  
            boolean isExchanged = false;  
            for (int j = len - 1; j > i; j--) {  
                if (data[j] < data[j - 1]) {  
                    temp = data[j];  
                    data[j] = data[j - 1];  
                    data[j - 1] = temp;  
                    /** 发生了交换,故将交换标志置为真 */ 
                    isExchanged = true;  
                }  
            }  
            /** 本趟排序未发生交换,提前终止算法,提高效率 */ 
            if (!isExchanged) {  
                return;  
            }  
        }  
    }  
 
    public void fixBoxPosition() {  
        for (int i = 0; i < 4; i++) {  
            mInts[i] = Math.abs(mStones[i].angle - 90);  
        }  
        RoundSpinView.sort(mInts);  
        for (int i = 0; i < 4; i++) {  
            if (Math.abs(mStones[i].angle - 90) == mInts[0]) {  
                mIn = i;  
                break;  
            }  
        }  
        int mO = 0;  
        do {  
            mStones[mIn].angle = mO * 90 + 90;  
            mIn++;  
            if (mIn == 4) {  
                mIn = 0;  
            }  
            mO++;  
        } while (mO < 4);  
        computeCoordinates();  
        invalidate();  
    }  
 
    public void catchClickEvent(float mX, float mY) {  
        System.out.println("mDown_x__________" + mDown_x);  
        System.out.println("mDown_y__________" + mDown_y);  
        for (int i = 0; i < mStones.length; i++) {  
            if (mStones[i].angle == 90) {  
                mStones[i].bitmap = BitmapFactory.decodeResource(  
                        getResources(), R.drawable.icon);  
            }  
        }  
        invalidate();  
    }  
 
    @Override 
    public boolean dispatchTouchEvent(MotionEvent event) {  
        switch (event.getAction()) {  
        case MotionEvent.ACTION_DOWN:  
            mDown_x = event.getX();  
            mDown_y = event.getY();  
            // catchClickEvent(mDown_x, mDown_y);  
            break;  
        case MotionEvent.ACTION_MOVE:  
            float mDistance_x = event.getX() - mDown_x;  
            float mDistance_y = event.getY() - mDown_y;  
            computeAngle(mDistance_x, mDistance_y);  
            computeCoordinates();  
            invalidate();  
            break;  
        case MotionEvent.ACTION_UP:  
            fixBoxPosition();  
            break;  
        }  
        return true;  
    }  
 
    public void computeAngle(float mX, float mY) {  
        int angle = (int) (mX * 0.1);  
        if (mX < 0) {  
            for (int index = 0; index < STONE_COUNT; index++) {  
                mStones[index].angle = mStones[index].angle - angle;  
            }  
        } else if (mX > 0) {  
            for (int index = 0; index < STONE_COUNT; index++) {  
                mStones[index].angle = mStones[index].angle - angle;  
            }  
        }  
    }  
 
    /** 计算一次滑动的角度 */ 
    public int computeCurrentAngle(float x, float y) {  
        float distance = (float) Math  
                .sqrt(((x - mPointX) * (x - mPointX) + (y - mPointY)  
                        * (y - mPointY)));  
        int degree = (int) (Math.acos((x - mPointX) / distance) * 180 / Math.PI);  
        return degree;  
    }  
 
    @Override 
    public void onDraw(Canvas canvas) {  
        canvas.drawPoint(mPointX, mPointY, mPaint);  
 
        for (int index = 0; index < STONE_COUNT; index++) {  
            if (!mStones[index].isVisible)  
                continue;  
            drawInCenter(canvas, mStones[index].bitmap, mStones[index].x,  
                    mStones[index].y);  
            // 不想有红线,就注掉下面这句  
            // canvas.drawLine(mPointX, mPointY, mStones[index].x,  
            // mStones[index].y, mPaint);  
        }  
    }  
 
    /** 
     * 把中心点放到中心处 
     *  
     * @param canvas 
     * @param bitmap 
     * @param left 
     * @param top 
     */ 
    void drawInCenter(Canvas canvas, Bitmap bitmap, float left, float top) {  
        canvas.drawPoint(left, top, mPaint);  
        canvas.drawBitmap(bitmap, left - bitmap.getWidth() / 2,  
                top - bitmap.getHeight() / 2, null);  
    }  
 
    class BigStone {  
        Bitmap bitmap;  
        int angle;  
        float x;  
        float y;  
        boolean isVisible = true;  
    }  


public class RoundSpinView extends View {

private Paint mPaint = new Paint();
private static final int STONE_COUNT = 4;
/** 4张图片分布的角度均值 */
private int mDegreeDelta;
private float mDown_x, mDown_y;

private int[] mResourceId = { R.drawable.customer, R.drawable.product,
R.drawable.order, R.drawable.info };

public RoundSpinView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(2);
setupStones();
computeCoordinates();
}

/** 初始化每个旋转图片的坐标位置及图片资源 */
private void setupStones() {
mStones = new BigStone[STONE_COUNT];
BigStone stone;
int angle = 0;
mDegreeDelta = 360 / STONE_COUNT;

for (int index = 0; index < STONE_COUNT; index++) {
stone = new BigStone();
stone.angle = angle;
stone.bitmap = BitmapFactory.decodeResource(getResources(),
mResourceId[index]);
angle += mDegreeDelta;
mStones[index] = stone;
}
}

/** 计算每个旋转图片坐标 */
private void computeCoordinates() {
BigStone stone;
for (int index = 0; index < STONE_COUNT; index++) {
stone = mStones[index];
if (stone.angle >= 360) {
stone.angle -= 360;
}
stone.x = mPointX
+ (float) (mRadius * Math.cos(stone.angle * Math.PI / 180));
stone.y = mPointY
+ (float) (mRadius * Math.sin(stone.angle * Math.PI / 180));
}
}

public RoundSpinView(Context context) {
super(context);
}

private BigStone[] mStones;

/** 旋转的中心点 */
private int mPointX = 0, mPointY = 0;
/** 旋转半径 */
private int mRadius = 0;

private int[] mInts = new int[] { 0, 0, 0, 0 };
/** 标识那个图片应该位于正中间 */
private int mIn;

public int getmRadius() {
return mRadius;
}

public void setmRadius(int mRadius) {
this.mRadius = mRadius;
}

public int getmPointX() {
return mPointX;
}

public void setmPointX(int mPointX) {
this.mPointX = mPointX;
}

public int getmPointY() {
return mPointY;
}

public void setmPointY(int mPointY) {
this.mPointY = mPointY;
}

/** Sort the elements in one array. */
public static void sort(int[] data) {
int len = data.length;
for (int i = 0; i < len - 1; i++) {
int temp = 0;
boolean isExchanged = false;
for (int j = len - 1; j > i; j--) {
if (data[j] < data[j - 1]) {
temp = data[j];
data[j] = data[j - 1];
data[j - 1] = temp;
/** 发生了交换,故将交换标志置为真 */
isExchanged = true;
}
}
/** 本趟排序未发生交换,提前终止算法,提高效率 */
if (!isExchanged) {
return;
}
}
}

public void fixBoxPosition() {
for (int i = 0; i < 4; i++) {
mInts[i] = Math.abs(mStones[i].angle - 90);
}
RoundSpinView.sort(mInts);
for (int i = 0; i < 4; i++) {
if (Math.abs(mStones[i].angle - 90) == mInts[0]) {
mIn = i;
break;
}
}
int mO = 0;
do {
mStones[mIn].angle = mO * 90 + 90;
mIn++;
if (mIn == 4) {
mIn = 0;
}
mO++;
} while (mO < 4);
computeCoordinates();
invalidate();
}

public void catchClickEvent(float mX, float mY) {
System.out.println("mDown_x__________" + mDown_x);
System.out.println("mDown_y__________" + mDown_y);
for (int i = 0; i < mStones.length; i++) {
if (mStones[i].angle == 90) {
mStones[i].bitmap = BitmapFactory.decodeResource(
getResources(), R.drawable.icon);
}
}
invalidate();
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDown_x = event.getX();
mDown_y = event.getY();
// catchClickEvent(mDown_x, mDown_y);
break;
case MotionEvent.ACTION_MOVE:
float mDistance_x = event.getX() - mDown_x;
float mDistance_y = event.getY() - mDown_y;
computeAngle(mDistance_x, mDistance_y);
computeCoordinates();
invalidate();
break;
case MotionEvent.ACTION_UP:
fixBoxPosition();
break;
}
return true;
}

public void computeAngle(float mX, float mY) {
int angle = (int) (mX * 0.1);
if (mX < 0) {
for (int index = 0; index < STONE_COUNT; index++) {
mStones[index].angle = mStones[index].angle - angle;
}
} else if (mX > 0) {
for (int index = 0; index < STONE_COUNT; index++) {
mStones[index].angle = mStones[index].angle - angle;
}
}
}

/** 计算一次滑动的角度 */
public int computeCurrentAngle(float x, float y) {
float distance = (float) Math
.sqrt(((x - mPointX) * (x - mPointX) + (y - mPointY)
* (y - mPointY)));
int degree = (int) (Math.acos((x - mPointX) / distance) * 180 / Math.PI);
return degree;
}

@Override
public void onDraw(Canvas canvas) {
canvas.drawPoint(mPointX, mPointY, mPaint);

for (int index = 0; index < STONE_COUNT; index++) {
if (!mStones[index].isVisible)
continue;
drawInCenter(canvas, mStones[index].bitmap, mStones[index].x,
mStones[index].y);
// 不想有红线,就注掉下面这句
// canvas.drawLine(mPointX, mPointY, mStones[index].x,
// mStones[index].y, mPaint);
}
}

/**
* 把中心点放到中心处
*
* @param canvas
* @param bitmap
* @param left
* @param top
*/
void drawInCenter(Canvas canvas, Bitmap bitmap, float left, float top) {
canvas.drawPoint(left, top, mPaint);
canvas.drawBitmap(bitmap, left - bitmap.getWidth() / 2,
top - bitmap.getHeight() / 2, null);
}

class BigStone {
Bitmap bitmap;
int angle;
float x;
float y;
boolean isVisible = true;
}
}

代码有点长,各位可以建个工程运行看下效果.

main.xml:
Java代码 
<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" android:layout_height="fill_parent" 
    android:background="@drawable/bg">  
    <TextView android:layout_width="fill_parent" 
        android:layout_height="wrap_content" android:text="The animation is solved." />  
    <com.example.view.RoundSpinView  
        android:layout_width="320dp" android:layout_height="300dp" android:id="@+id/mSelfView" 
        android:layout_alignParentBottom="true" />  
</RelativeLayout> 
分享到:
评论

相关推荐

    图片悬停标题旋转动画效果.rar

    图片悬停标题旋转动画效果.rar 图片悬停标题旋转动画效果.rar 图片悬停标题旋转动画效果.rar 图片悬停标题旋转动画效果.rar 图片悬停标题旋转动画效果.rar 图片悬停标题旋转动画效果.rar 图片悬停标题旋转动画效果....

    鸿蒙 ArkTS 双色旋转动画效果(源码版)

    鸿蒙 ArkTS 双色旋转动画效果是一种在 HarmonyOS 操作系统中实现的视觉效果,主要应用于用户界面的交互设计,提升用户体验。ArkTS 是 HarmonyOS 的一种编程语言,它是基于 TypeScript 扩展的,提供了丰富的类型安全...

    两球旋转动画效果

    "两球旋转动画效果"是一种常见的动画设计,常用于加载等待界面,为用户提供视觉反馈,减轻等待焦虑感。这种动画具有高度自定义性,可以根据设计师的需求进行个性化设置。 在Android中,有两种主要的动画类型:属性...

    旋转动画效果

    flash旋转动画效果,可清晰播放,字体可以进行旋转。

    3D Tabhost 旋转 动画 效果

    在Android开发中,3D Tabhost旋转动画效果是一种高级用户界面设计,旨在提供更吸引人的交互体验。Tabhost是Android SDK中的一个组件,用于在多个Tab之间切换,通常用于展示应用的不同功能区域。通过实现3D旋转动画,...

    Activity3D旋转动画效果

    在Android开发中,Activity的切换动画是提升用户体验的重要一环,而"Activity3D旋转动画效果"正是这种体验的一种高级展现。本示例通过模仿陌陌科技的产品动画,为开发者提供了一个实现3D旋转效果的Demo,使得应用的...

    FLASH+XML 旋转动画效果代码

    "FLASH+XML 旋转动画效果代码"是利用Adobe Flash(现为Animate CC)与XML结合来创建动态旋转效果的技术。以下是关于这个主题的详细解释: 1. **Flash与XML**: - **Flash**:曾经是Web开发中的主力工具,用于创建...

    非常漂亮赫兹旋转动画效果

    "非常漂亮赫兹旋转动画效果"是一个专为Android设计的独特动画效果,它结合了多种动画技术,包括悬浮View、缩放、移动以及旋转,来创造出类似“赫兹”(可能是品牌或者某种特定风格)的旋转动画。这个效果通常用于吸引...

    iOS 图片旋转动画

    在iOS开发中,图片旋转动画是一种常见的视觉效果,常用于音乐播放器、加载指示器或者各种过渡动画。本文将深入探讨如何实现一个类似音乐播放器的图片旋转动画,并在动画停止时保持图片当前的旋转角度。 首先,我们...

    旋转动画的Demo

    同时,运行Demo应用,观察并分析动画效果,这样可以加深对旋转动画的理解。 总之,这个"旋转动画的Demo"为你提供了一个实践和研究Android旋转动画的平台,无论是属性动画还是视图动画,都能帮助你掌握如何在Android...

    listview特效-3D旋转动画效果

    为了提升用户体验,开发者往往会为ListView添加各种特效,其中3D旋转动画效果就是一个常见的增强视觉吸引力的手段。本篇文章将详细探讨如何在ListView中实现3D旋转动画效果,以及相关的技术要点。 首先,要实现3D...

    超级酷的3d鼠标拖动图片360°旋转动画效果

    "超级酷的3d鼠标拖动图片360°旋转动画效果"是一种创新的技术,它利用了jQuery库来创建一种动态的、引人入胜的视觉体验,让用户能够通过鼠标拖动操作查看图片的全方位视图。这种技术广泛应用于电子商务平台,让客户...

    实现安卓音乐播放器中的旋转动画效果

    本教程将深入探讨如何在安卓音乐播放器中实现旋转动画效果,包括图片的圆形截取以及从相册和相机获取图片的流程。 首先,让我们关注“旋转动画效果”。在安卓中,我们可以使用`ObjectAnimator`、`ValueAnimator`...

    js楼盘模型360度旋转动画效果

    【360度旋转动画效果】在Web开发中是一种引人注目的视觉表现形式,尤其在房地产、产品展示等领域广泛应用。本项目通过结合JavaScript(JS)与CSS3技术,实现了一个楼盘模型的3D旋转动画,使用户可以全方位地查看模型...

    jQuery旋转动画按钮

    在本教程中,我们将探讨“jQuery旋转动画按钮”的实现,这可以为网页添加交互性和视觉吸引力。 标题“jQuery旋转动画按钮”暗示我们将关注如何使用jQuery来创建一个具有旋转效果的按钮。这种效果通常是通过CSS3的...

    android自定义ImageView实现旋转动画

    本文将深入探讨如何通过自定义ImageView来实现旋转动画,让图片在XYZ轴上动态展示,为用户带来更加生动的视觉效果。 首先,我们需要创建一个新的类,继承自Android的内置ImageView类。这个新类将作为我们自定义的...

    旋转动画效果制作的Loading素材.rar

    本话题主要关注的是如何制作一个旋转动画效果,具体为一个矢量旋转箭头的Loading素材,适用于Flash加载模块。以下是关于这个主题的详细知识点: 1. **Flash动画基础**:Flash是一款广泛应用于创建互动内容、动画和...

    html5 canvas酷炫水晶光圈旋转动画特效.zip

    在这个项目中,jQuery被用作基础框架,帮助我们更轻松地控制页面元素和触发动画效果。 jQuery特效通常涉及对DOM元素的操作,如改变样式、位置或大小,以创建动态视觉效果。在这个水晶光圈旋转动画中,jQuery可能被...

    纯CSS3模拟摩天轮旋转动画效果

    效果描述: 这是用纯CSS3实现的一个旋转动画效果,模拟游乐场里的摩天轮旋转动画效果 效果逼真好用 使用方法: 1、引入css样式 2、将index.html中的代码部分拷贝过去即可

    HTML5CSS3实现大风车旋转动画效果源码下载

    在这个“HTML5CSS3实现大风车旋转动画效果源码下载”项目中,我们可以深入学习如何利用这两者来创建动态、交互式的网页元素。以下是相关的知识点详解: 1. HTML5新特性: - `&lt;canvas&gt;`元素:HTML5引入了画布元素,...

Global site tag (gtag.js) - Google Analytics