一、效果分析
布局:
- DrawerLayout+Fragment
重点:
- 侧边栏的数据结构(名称+资源文件)
- 侧边栏的动画效果(点击ActionBar中的home按钮,显示侧边栏时的旋转效果)
二、自定义DrawerLayout侧边栏
DrawLayout需要注意两点:
- DrawerLayout最好是跟布局
- DrawerLayout中的子布局先后顺序要注意,抽屉布局要放在最后,因为DrawerLayout布局和RelativeLayout布局类似,后写的布局会覆盖前面的布局。
三、侧边栏结构设计
Interface:
public interface Resourceble {
public int getImageRes(); //图片资源文件,引用时放在项目的drawable文件夹下
public String getName(); //每个资源文件对应的名称
}
数据模型类:
public class SlideMenuItem implements Resourceble {
private String name;
private int imageRes;
public SlideMenuItem(String name, int imageRes) {
this.name = name;
this.imageRes = imageRes;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getImageRes() {
return imageRes;
}
public void setImageRes(int imageRes) {
this.imageRes = imageRes;
}
}
四、侧边栏动画设计
侧边栏的每一个Item都是SlideMenuItem实例。每个SlideMenuItem的动画效果是沿着Y轴旋转90度(显示是逆时针90°,隐藏是顺时针90°),为了动画的平滑效果,用到了加速插值器。
- 自定义Animation
FlipAnimation类,extends Animation。重写了initialize(),applyTransformation()方法。动画的平移,旋转,透明度变化都在applyTransformation中实现。注意代码中注释的角度计算,是重点。每个Item都是围绕Y轴做了旋转操作,度数都是90度。关键在于:
1 如何做到显示和隐藏的角度计算?
2 如何平滑显示和隐藏?
3 每一个Item的动画效果延迟是如何实现的?
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
//interpolatedTime范围固定0-1。
//显示:mToDegrees为90, mFromDegrees为0,变化范围是-90度--->0度
//隐藏:mToDegrees为0, mFromDegrees为90,变化范围是0度--->-90度
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();
camera.rotateY(degrees);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
显示抽屉菜单,代码可见,平滑动画的出现是因为使用了加速插值器rotation.setInterpolator(new AccelerateInterpolator());
private void animateView(int position) {
final View view = viewList.get(position);
view.setVisibility(View.VISIBLE);
FlipAnimation rotation =
new FlipAnimation(90, 0, 0.0f, view.getHeight() / 2.0f);
rotation.setDuration(ANIMATION_DURATION); //175ms
rotation.setFillAfter(true);
rotation.setInterpolator(new AccelerateInterpolator());
rotation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
view.clearAnimation();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
view.startAnimation(rotation);
}
每一个Item动画交替出现是用了Handler延迟调用,最后的Fragment的图片切换效果是用了一个开源的库RevealFrameLayout
for (int i = 0; i < size; i++) {
略...
new Handler().postDelayed(new Runnable() {
public void run() {
if (position < viewList.size()) {
animateView((int) position);
}
if (position == viewList.size() - 1) { //最后一个Item
screenShotable.takeScreenShot(); //调用接口的方式来改变Fragment中的图片(这个其实也是点击之后才发生的效果)
setViewsClickable(true);
}
}
}, (long) delay);
}