android+酷炫动画效果,Android酷炫动画效果之3D星体旋转效果

在Android中,如果想要实现3D动画效果一般有两种选择:一是使用Open GL ES,二是使用Camera。Open GL ES使用起来太过复杂,一般是用于比较高级的3D特效或游戏,并且这个也不是开源的,像比较简单的一些3D效果,使用Camera就足够了。

一些熟知的Android 3D动画如对某个View进行旋转或翻转的 Rotate3dAnimation类,还有使用Gallery( Gallery目前已过时,现在都推荐使用 HorizontalScrollView或 RecyclerView替代其实现相应功能) 实现的3D画廊效果等,当然有一些特效要通过伪3D变换来实现,比如CoverFlow效果,它使用标准Android 2D库,还是继承的Gallery类并自定义一些方法,具体实现和使用请参照Android实现CoverFlow效果控件的实例代码。

本文要实现的3D星体旋转效果也是从这个CoverFlow演绎而来,不过CoverFlow只是对图像进行转动,我这里要实现的效果是要对所有的View进行类似旋转木马的转动,并且CoverFlow还存在很多已知bug,所以我这里需要重写一些类,并且将Scroller类用Rotator类替代,使界面看起来具有滚动效果,实际上是在转动一组图像。

首先我们需要自定义控件的一些属性,我们将控件取名Carousel,需要设置子项的最小个数和最大个数、当前选中项以及定义旋转角度等,attrs.xml

The CarouselImageView Class

这个类装载控件子项在3D空间的位置、子项的索引和当前子项的角度,通过实现Comparable接口,帮助我们确定子项绘制的顺序

package com.john.carousel.lib;

import android.content.Context;

import android.util.AttributeSet;

import android.widget.ImageView;

public class CarouselImageView extends ImageView implements Comparable

{

private int index;

private float currentAngle;

private float x;

private float y;

private float z;

private boolean drawn;

public CarouselImageView(Context context)

{

this(context, null, 0);

}

public CarouselImageView(Context context, AttributeSet attrs)

{

this(context, attrs, 0);

}

public CarouselImageView(Context context, AttributeSet attrs, int defStyle)

{

super(context, attrs, defStyle);

}

public void setIndex(int index)

{

this.index = index;

}

public int getIndex()

{

return index;

}

public void setCurrentAngle(float currentAngle)

{

this.currentAngle = currentAngle;

}

public float getCurrentAngle()

{

return currentAngle;

}

public int compareTo(CarouselImageView another)

{

return (int) (another.z - this.z);

}

public void setX(float x)

{

this.x = x;

}

public float getX()

{

return x;

}

public void setY(float y)

{

this.y = y;

}

public float getY()

{

return y;

}

public void setZ(float z)

{

this.z = z;

}

public float getZ()

{

return z;

}

public void setDrawn(boolean drawn)

{

this.drawn = drawn;

}

public boolean isDrawn()

{

return drawn;

}

}

The Carousel Item Class

这个类简化我上面定义的 CarouselImageView一些控件属性

package com.john.carousel.lib;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Matrix;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.widget.FrameLayout;

import android.widget.ImageView;

import android.widget.TextView;

public class CarouselItem extends FrameLayout implements Comparable

{

public ImageView mImage;

public TextView mText, mTextUp;

public Context context;

public int index;

public float currentAngle;

public float itemX;

public float itemY;

public float itemZ;

public float degX;

public float degY;

public float degZ;

public boolean drawn;

// It's needed to find screen coordinates

private Matrix mCIMatrix;

public CarouselItem(Context context)

{

super(context);

this.context = context;

FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

this.setLayoutParams(params);

LayoutInflater inflater = LayoutInflater.from(context);

View itemTemplate = inflater.inflate(R.layout.carousel_item, this, true);

mImage = (ImageView) itemTemplate.findViewById(R.id.item_image);

mText = (TextView) itemTemplate.findViewById(R.id.item_text);

mTextUp = (TextView) itemTemplate.findViewById(R.id.item_text_up);

}

public void setTextColor(int i)

{

this.mText.setTextColor(context.getResources().getColorStateList(i));

this.mTextUp.setTextColor(context.getResources().getColorStateList(i));

}

public String getName()

{

return mText.getText().toString();

}

public void setIndex(int index)

{

this.index = index;

}

public int getIndex()

{

return index;

}

public void setCurrentAngle(float currentAngle)

{

if (index == 0 && currentAngle > 5)

{

Log.d("", "");

}

this.currentAngle = currentAngle;

}

public float getCurrentAngle()

{

return currentAngle;

}

public int compareTo(CarouselItem another)

{

return (int) (another.itemZ - this.itemZ);

}

public void setItemX(float x)

{

this.itemX = x;

}

public float getItemX()

{

return itemX;

}

public void setItemY(float y)

{

this.itemY = y;

}

public float getItemY()

{

return itemY;

}

public void setItemZ(float z)

{

this.itemZ = z;

}

public float getItemZ()

{

return itemZ;

}

public float getDegX()

{

return degX;

}

public void setDegX(float degX)

{

this.degX = degX;

}

public float getDegY()

{

return degY;

}

public void setDegY(float degY)

{

this.degY = degY;

}

public float getDegZ()

{

return degZ;

}

public void setDegZ(float degZ)

{

this.degZ = degZ;

}

public void setDrawn(boolean drawn)

{

this.drawn = drawn;

}

public boolean isDrawn()

{

return drawn;

}

public void setImageBitmap(Bitmap bitmap)

{

mImage.setImageBitmap(bitmap);

}

public void setText(int i)

{

String s = context.getResources().getString(i);

mText.setText(s);

mTextUp.setText(s);

}

public void setText(String txt)

{

mText.setText(txt);

mTextUp.setText(txt);

}

Matrix getCIMatrix()

{

return mCIMatrix;

}

void setCIMatrix(Matrix mMatrix)

{

this.mCIMatrix = mMatrix;

}

public void setImage(int i)

{

mImage.setImageDrawable(context.getResources().getDrawable(i));

}

public void setVisiblity(int id)

{

if (id == 0)

{

mText.setVisibility(View.INVISIBLE);

mTextUp.setVisibility(View.VISIBLE);

}

else

{

mTextUp.setVisibility(View.INVISIBLE);

mText.setVisibility(View.VISIBLE);

}

}

}

The Rotator Class

如果你去查看Scroller类方法,你会发现它定义了两种操作模式:滑动模式和抛动作,用来计算当前相对于给出的起始位置的偏移量,我们需要移除一些不需要的成员变量,添加我们自己的成员,并且修改相应的计算方法

package com.john.carousel.lib;

import android.content.Context;

import android.view.animation.AnimationUtils;

/**

* This class encapsulates rotation. The duration of the rotation can be passed

* in the constructor and specifies the maximum time that the rotation animation

* should take. Past this time, the rotation is automatically moved to its final

* stage and computeRotationOffset() will always return false to indicate that

* scrolling is over.

*/

public class Rotator

{

private float mStartAngle;

private float mCurrAngle;

private long mStartTime;

private long mDuration;

private float mDeltaAngle;

private boolean mFinished;

private int direction;

private float mCurrDeg;

public Rotator(Context context)

{

mFinished = true;

}

public final boolean isFinished()

{

return mFinished;

}

/**

* Force the finished field to a particular value.

*

* @param finished

* The new finished value.

*/

public final void forceFinished(boolean finished)

{

mFinished = finished;

}

/**

* Returns how long the scroll event will take, in milliseconds.

*

* @return The duration of the scroll in milliseconds.

*/

public final long getDuration()

{

return mDuration;

}

/**

* Returns the current X offset in the scroll.

*

* @return The new X offset as an absolute distance from the origin.

*/

public final float getCurrAngle()

{

return mCurrAngle;

}

public final float getStartAngle()

{

return mStartAngle;

}

/**

* Returns the time elapsed since the beginning of the scrolling.

*

* @return The elapsed time in milliseconds.

*/

public int timePassed()

{

return (int) (AnimationUtils.currentAnimationTimeMillis() - mStartTime);

}

public int getdirection()

{

return this.direction;

}

public float getCurrDeg()

{

return this.mCurrDeg;

}

/**

* Extend the scroll animation.

*/

public void extendDuration(int extend)

{

int passed = timePassed();

mDuration = passed + extend;

mFinished = false;

}

/**

* Stops the animation. Contrary to {@link #forceFinished(boolean)},

* aborting the animating cause the scroller to move to the final x and y

* position

*

* @see #forceFinished(boolean)

*/

public void abortAnimation()

{

mFinished = true;

}

/**

* Call this when you want to know the new location. If it returns true, the

* animation is not yet finished. loc will be altered to provide the new

* location.

*/

public boolean computeAngleOffset()

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
旋转木马布局效果     gradle    compile 'com.dalong:carrousellayout:1.0.0'or Maven    <dependency>       <groupId>com.dalong</groupId>       <artifactId>carrousellayout</artifactId>       <version>1.0.0</version>       <type>pom</type>     </dependency>xml:     <com.dalong.carrousellayout.CarrouselLayout            android:id="@ id/carrousel"            app:rotateDirection="anticlockwise"            app:r="200dp"            app:rotationTime="3000"            android:gravity="center"            android:layout_marginBottom="180dp"            android:layout_width="match_parent"            android:layout_height="match_parent">           <ImageView               android:src="@mipmap/image1"               android:layout_width="wrap_content"               android:layout_height="wrap_content" />           <ImageView               android:src="@mipmap/image2"               android:layout_width="wrap_content"               android:layout_height="wrap_content" />               ...        </com.dalong.carrousellayout.CarrouselLayout>java:    CarrouselLayout carrousel= (CarrouselLayout) findViewById(R.id.carrousel);     carrousel.setR(width/3)//设置R的大小              .setAutoRotation(false)//是否自动切换              .setAutoRotationTime(1500);//自动切换的时间  单位毫秒

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值