最近项目中需要实现这样的动画切换效果,因此自己尝试了几天,觉得最终实现的效果还是很满意的,废话不多说!现在就把心得跟大家分享一下。下面先来看看最初想象的草图
经过上图的了解,相信大神们应该可以很清楚是什么样的效果了吧!对的,就是两个activity(View)之间的切换问题,但这里不是普通切换,要有3D动画并且是翻转切换!也就是一个水平的翻转过程!(因为这是最开始的思路,但本文中并不是实现两个活动之间的切换,而是在一个活动里进行两个布局的切换)
在这里就不做过多解释了,因为在代码里已经注释比较详细了。
一、实现3D动画效果核心类:
/**
* 实现3D旋转动画核心类
* @author qiulong
*
*/
public class Rotate3d extends Animation {
private final float mFromDegrees;// 开始角度
private final float mToDegrees;// 结束角度
// 中心点
private final float mCenterX;
private final float mCenterY;
//深度
private final float mDepthZ;
//是否需要扭曲
private final boolean mReverse;
//摄像头
private Camera mCamera;
public Rotate3d(float fromDegrees, float toDegrees, float centerX,
float centerY, float depthZ, boolean reverse) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mCenterX = centerX;
mCenterY = centerY;
mDepthZ = depthZ;
mReverse = reverse;
}
@Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
// 生成中间角度
float degrees = fromDegrees
+ ((mToDegrees - fromDegrees) * interpolatedTime);
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
final Matrix matrix = t.getMatrix();//取得当前矩阵
camera.save();
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
camera.rotateY(degrees);//翻转
camera.getMatrix(matrix);// 取得变换后的矩阵
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
二、xml布局文件(视需求而定,可更改)
/**
* 实现3D旋转动画核心类
* @author qiulong
*
*/
public class Rotate3d extends Animation {
private final float mFromDegrees;// 开始角度
private final float mToDegrees;// 结束角度
// 中心点
private final float mCenterX;
private final float mCenterY;
//深度
private final float mDepthZ;
//是否需要扭曲
private final boolean mReverse;
//摄像头
private Camera mCamera;
public Rotate3d(float fromDegrees, float toDegrees, float centerX,
float centerY, float depthZ, boolean reverse) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mCenterX = centerX;
mCenterY = centerY;
mDepthZ = depthZ;
mReverse = reverse;
}
@Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
// 生成中间角度
float degrees = fromDegrees
+ ((mToDegrees - fromDegrees) * interpolatedTime);
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
final Matrix matrix = t.getMatrix();//取得当前矩阵
camera.save();
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
camera.rotateY(degrees);//翻转
camera.getMatrix(matrix);// 取得变换后的矩阵
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000000"
android:orientation="vertical" >
<!-- 标题部分 -->
<RelativeLayout
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:background="#01aef0"
android:orientation="horizontal" >
<Button
android:id="@+id/btn_return"
android:layout_width="50dip"
android:layout_height="50dip"
android:layout_alignParentLeft="true"
android:background="@null" />
<Button
android:id="@+id/btn_music"
android:layout_width="50dip"
android:layout_height="50dip"
android:layout_alignParentRight="true"
android:background="@drawable/music" />
<TextView
android:id="@+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@android:color/transparent"
android:text="@string/main_home"
android:textColor="#ffffff"
android:textSize="22sp" />
</RelativeLayout>
<!-- 翻转布局的容器部分 -->
<FrameLayout
android:id="@+id/container_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<!-- 布局2(音乐)部分 -->
<LinearLayout
android:id="@+id/lin2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#ccccff">
<ListView
android:id="@+id/music_listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
<!-- 布局1(首页)部分 -->
<LinearLayout
android:id="@+id/lin1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ccffff"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/main_home"
android:textColor="#000000"
android:textSize="36sp" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
三、MainActivity.java文件:
/**
* 翻转动画切换Layout
* @author qiulong
*
*/
public class MainActivity extends Activity implements OnClickListener {
/** 初始视图索引 (0为首页,1为音乐) */
private int index = 1;
/** 标题文字 */
private TextView text_title;
/** 标题右边按钮 */
private Button btn_music;
/** 首页视图 */
private LinearLayout homeView;
/** 音乐视图 */
private LinearLayout musicView;
/** 视图容器 */
private FrameLayout containerView;
/** 音乐视图List列表 */
private ListView musicList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
text_title = (TextView) findViewById(R.id.text_title);
btn_music = (Button) findViewById(R.id.btn_music);
containerView = (FrameLayout) this.findViewById(R.id.container_view);
homeView = (LinearLayout) findViewById(R.id.lin1);
musicView = (LinearLayout) findViewById(R.id.lin2);
musicList = (ListView) findViewById(R.id.music_listview);
btn_music.setOnClickListener(this);
}
/**测试数据 */
private List<String> getData() {
List<String> data = new ArrayList<String>();
data.add("音乐歌名1");
data.add("音乐歌名2");
data.add("音乐歌名3");
data.add("音乐歌名4");
data.add("音乐歌名5");
data.add("音乐歌名6");
data.add("音乐歌名7");
data.add("音乐歌名8");
data.add("音乐歌名9");
data.add("音乐歌名10");
return data;
}
@Override
public void onClick(View v) {
if (index == 1) {
//首页页面以0~90度翻转,并加载数据
applyRotation(1, 0, 90);
index = 0;
musicList.setAdapter(new ArrayAdapter<String>(
MainActivity.this,
android.R.layout.simple_expandable_list_item_1,
getData()));
} else {
//音乐页面以0~-90度翻转
applyRotation(0, 0, -90);
index = 1;
}
}
/**
* 执行翻转第一个视图动画
* @param tag view索引
* @param start 起始角度
* @param end 结束角度
*/
private void applyRotation(int tag, float start, float end) {
// 得到中心点(以中心翻转)
final float centerX = containerView.getWidth() / 2.0f;
final float centerY = containerView.getHeight() / 2.0f;
// 根据参数创建一个新的三维动画,并且监听触发下一个动画
final Rotate3d rotation = new Rotate3d(start, end, centerX, centerY,310.0f, true);
rotation.setDuration(300);//设置动画持续时间
rotation.setInterpolator(new AccelerateInterpolator());//设置动画变化速度
rotation.setAnimationListener(new DisplayNextView(tag));//显示下一个视图
containerView.startAnimation(rotation);
}
/**
* 显示下一个视图
* @author qiulong
*
*/
private final class DisplayNextView implements Animation.AnimationListener {
private final int tag;
private DisplayNextView(int tag) {
this.tag = tag;
}
public void onAnimationStart(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
containerView.post(new SwapViews(tag));
}
public void onAnimationRepeat(Animation animation) {
}
}
/**
* 执行翻转第二个视图动画子线程
* @author qiulong
*
*/
private final class SwapViews implements Runnable {
private final int tag;
public SwapViews(int position) {
tag = position;
}
public void run() {
if (tag == 0) {
text_title.setText("首页");
//首页页面以90~0度翻转
showView(tag,homeView, musicView, 90, 0);
} else if (tag == 1) {
text_title.setText("音乐");
//音乐页面以-90~0度翻转
showView(tag,musicView, homeView, -90, 0);
}
}
}
/**
* 显示第二个视图动画
* @param showView 要显示的视图
* @param hiddenView 要隐藏的视图
* @param start_jd 开始角度
* @param end_jd 目标角度
*/
private void showView(int tag, LinearLayout showView, LinearLayout hiddenView, int start_jd, int end_jd) {
//同样以中心点进行翻转
float centerX = showView.getWidth() / 2.0f;
float centerY = showView.getHeight() / 2.0f;
if (centerX == 0 || centerY == 0) {
//调用该方法getMeasuredWidth(),必须先执行measure()方法,否则会出异常。
showView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
//获取该view在父容器里面占的大小
centerX = showView.getMeasuredWidth() / 2.0f;
centerY = showView.getMeasuredHeight() / 2.0f;
}
hiddenView.setVisibility(View.GONE);
showView.setVisibility(View.VISIBLE);
Rotate3d rotation = new Rotate3d(start_jd, end_jd, centerX, centerY, 310.0f, false);
rotation.setDuration(300);//设置动画持续时间
rotation.setInterpolator(new DecelerateInterpolator());//设置动画变化速度
containerView.startAnimation(rotation);
}
}
四、OK!把上面代码直接Copy到工程里即可运行(图片、颜色值以及文字内容需要自行修改)
/**
* 翻转动画切换Layout
* @author qiulong
*
*/
public class MainActivity extends Activity implements OnClickListener {
/** 初始视图索引 (0为首页,1为音乐) */
private int index = 1;
/** 标题文字 */
private TextView text_title;
/** 标题右边按钮 */
private Button btn_music;
/** 首页视图 */
private LinearLayout homeView;
/** 音乐视图 */
private LinearLayout musicView;
/** 视图容器 */
private FrameLayout containerView;
/** 音乐视图List列表 */
private ListView musicList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
text_title = (TextView) findViewById(R.id.text_title);
btn_music = (Button) findViewById(R.id.btn_music);
containerView = (FrameLayout) this.findViewById(R.id.container_view);
homeView = (LinearLayout) findViewById(R.id.lin1);
musicView = (LinearLayout) findViewById(R.id.lin2);
musicList = (ListView) findViewById(R.id.music_listview);
btn_music.setOnClickListener(this);
}
/**测试数据 */
private List<String> getData() {
List<String> data = new ArrayList<String>();
data.add("音乐歌名1");
data.add("音乐歌名2");
data.add("音乐歌名3");
data.add("音乐歌名4");
data.add("音乐歌名5");
data.add("音乐歌名6");
data.add("音乐歌名7");
data.add("音乐歌名8");
data.add("音乐歌名9");
data.add("音乐歌名10");
return data;
}
@Override
public void onClick(View v) {
if (index == 1) {
//首页页面以0~90度翻转,并加载数据
applyRotation(1, 0, 90);
index = 0;
musicList.setAdapter(new ArrayAdapter<String>(
MainActivity.this,
android.R.layout.simple_expandable_list_item_1,
getData()));
} else {
//音乐页面以0~-90度翻转
applyRotation(0, 0, -90);
index = 1;
}
}
/**
* 执行翻转第一个视图动画
* @param tag view索引
* @param start 起始角度
* @param end 结束角度
*/
private void applyRotation(int tag, float start, float end) {
// 得到中心点(以中心翻转)
final float centerX = containerView.getWidth() / 2.0f;
final float centerY = containerView.getHeight() / 2.0f;
// 根据参数创建一个新的三维动画,并且监听触发下一个动画
final Rotate3d rotation = new Rotate3d(start, end, centerX, centerY,310.0f, true);
rotation.setDuration(300);//设置动画持续时间
rotation.setInterpolator(new AccelerateInterpolator());//设置动画变化速度
rotation.setAnimationListener(new DisplayNextView(tag));//显示下一个视图
containerView.startAnimation(rotation);
}
/**
* 显示下一个视图
* @author qiulong
*
*/
private final class DisplayNextView implements Animation.AnimationListener {
private final int tag;
private DisplayNextView(int tag) {
this.tag = tag;
}
public void onAnimationStart(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
containerView.post(new SwapViews(tag));
}
public void onAnimationRepeat(Animation animation) {
}
}
/**
* 执行翻转第二个视图动画子线程
* @author qiulong
*
*/
private final class SwapViews implements Runnable {
private final int tag;
public SwapViews(int position) {
tag = position;
}
public void run() {
if (tag == 0) {
text_title.setText("首页");
//首页页面以90~0度翻转
showView(tag,homeView, musicView, 90, 0);
} else if (tag == 1) {
text_title.setText("音乐");
//音乐页面以-90~0度翻转
showView(tag,musicView, homeView, -90, 0);
}
}
}
/**
* 显示第二个视图动画
* @param showView 要显示的视图
* @param hiddenView 要隐藏的视图
* @param start_jd 开始角度
* @param end_jd 目标角度
*/
private void showView(int tag, LinearLayout showView, LinearLayout hiddenView, int start_jd, int end_jd) {
//同样以中心点进行翻转
float centerX = showView.getWidth() / 2.0f;
float centerY = showView.getHeight() / 2.0f;
if (centerX == 0 || centerY == 0) {
//调用该方法getMeasuredWidth(),必须先执行measure()方法,否则会出异常。
showView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
//获取该view在父容器里面占的大小
centerX = showView.getMeasuredWidth() / 2.0f;
centerY = showView.getMeasuredHeight() / 2.0f;
}
hiddenView.setVisibility(View.GONE);
showView.setVisibility(View.VISIBLE);
Rotate3d rotation = new Rotate3d(start_jd, end_jd, centerX, centerY, 310.0f, false);
rotation.setDuration(300);//设置动画持续时间
rotation.setInterpolator(new DecelerateInterpolator());//设置动画变化速度
containerView.startAnimation(rotation);
}
}
五、下面就是效果图:
六、demo下载地址:demo下载地址 download.csdn.net/detail/baidu_23478311/8499253 转载请注明出处!
文章转载自http://www.voidcn.com/blog/baidu_23478311/article/p-3995212.html