上一篇文章中讲了如何实现手势滑动来销毁页面,再来回顾一下实现的效果
具体实现请看上一篇文章 手势滑动结束 Activity(一)基本功能的实现,不过这只是实现了最基本的功能,还有很多地方需要优化和完善的,这篇文章主要是在原来实现的基础上做优化和特效;
先来看效果:
1、效果图1:侧滑显示阴影
2、效果图2:改变滑动动画效果
先来看看效果图1的实现方式:
根据效果图,我们应该能想到他的实现原理,就是在手势不断的滑动的同时绘制已经滑走部分的颜色,并且不断改变透明度。
所以我们需要重写 ViewGroup 中的 drawShadow(Canvas canvas) 方法,在里面绘制我们要显示的遮罩层,
/**
* 绘制背景颜色,随着距离的改变而改变
* @param canvas
*/
private void drawBackground(Canvas canvas) {
mShadowPaint.setAlpha((int) ((1 - mRatio) * 180));
canvas.drawRect(-mPix, 0, 0, getHeight(), mShadowPaint);
}
这里有三个变量我们还不知道的,mRatio、mPix、mShadowPaint;
1、mShadowPaint:是绘制阴影的画笔,这个我们可以直接在初始化的时候 new 出来,并设置画笔的颜色为黑色,画出来的图就是黑色的。
mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mShadowPaint.setColor(0xff000000);
2、mRatio:滑动的梯度值,但开始滑动的时候这个值为0,而滑动到最大值的时候,也就是 Activity 页面小时不见了时,这个值为1,所以这个值的范围0.0f~1.0f。所以通过一下代码来改变画笔的透明度,使得在滑动的过程中,阴影层会逐渐变化
mShadowPaint.setAlpha((int) ((1 - mRatio) * 180));
3、mPix:这个变量是滑动距离原始位置的距离。通俗点讲就是已经滑动了多远的距离,可以通过这个值来确定绘制阴影部分的面积
canvas.drawRect(-mPix, 0, 0, getHeight(), mShadowPaint);
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mShouldDraw){
drawBackground(canvas);
}
}
以上代码只是绘制了滑动部分的阴影,如果仔细看了效果图1的朋友会发现在被滑走页面的边缘也存在一条渐变的阴影,这又怎么绘制呢?
首先,定义一个 Drawable 资源文件left_shadow.xml
<?xml version="1.0" encoding="utf-8"?>
<!--形状为矩形-->
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<!--颜色渐变范围-->
<gradient android:startColor="#00000000" android:endColor="#33000000" />
</shape>
接着绘制 Drawable,在绘制 Drawable 之前先要设置其大小
/**
* 绘制shadow阴影
* @param canvas
*/
private void drawShadow(Canvas canvas){
/*保存画布当前的状态,这个用法在我前面将自定义View 的时候将的很详细*/
canvas.save() ;
/*设置 drawable 的大小范围*/
mLeftShadow.setBounds(0, 0, mShadowWidth, getHeight());
/*让画布平移一定距离*/
canvas.translate(-mShadowWidth,0);
/*绘制Drawable*/
mLeftShadow.draw(canvas);
/*恢复画布的状态*/
canvas.restore();
}
所以dispatchDraw(Canvas canvas)的方法实现为
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mShouldDraw){
/*绘制偏移的背影颜色*/
drawBackground(canvas);
/*绘制边缘的阴影*/
drawShadow(canvas) ;
}
}
到这里就完成了效果图1的功能实现。
滑动动画的实现:
在实现可滑动的自定义 ViewGroup 的时候,我把滑动的距离做了一个接口回调出来,类似 ViewPage控件的 PageChange 监听事件,这里也对页面滑动做了滑动监听,虽然只有一页,但是有了这个监听事件,对做很多操作都十分方便,比如我们前面讲到的 mRatio、mPix 都可以直接通过监听滑动事件来获取,接口定义如下:
public interface OnPageChangeListener {
/*滑动页面滑动状态,当前页和页面的偏移梯度,页面的偏移位置*/
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
/*当前页面*/
public void onPageSelected(int position);
}
接口调用通过重写scrollTo(int x, int y)方法来获取滑动监听的参数
@Override
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
/*设置回调事件的值*/
pageScrolled(x);
}
private void pageScrolled(int xpos) {
final int widthWithMargin = getWidth();
/*获取当前页面*/
int position = Math.abs(xpos) / widthWithMargin;
/*获取当前滑动的距离*/
final int offsetPixels = Math.abs(xpos) % widthWithMargin;
/*通过滑动的距离来获取梯度值*/
final float offset = (float) offsetPixels / widthWithMargin;
/*这里需要做特殊处理,因为只有一个页面*/
position = mIsBeingDragged ? 0 : position;
onPageScrolled(position, offset, offsetPixels);
}
protected void onPageScrolled(int position, float offset, int offsetPixels) {
if (mListener != null) {
mListener.onPageScrolled(position, offset, offsetPixels);
}
mInternalPageChangeListener.onPageScrolled(position, offset, offsetPixels);
}
动画效果的实现我这里做了处理,放在了 SlidingLayout类中实现
/**
* Created by moon.zhong on 2015/3/13.
*/
public class SlidingLayout extends FrameLayout {
/*可根据手势滑动的View*/
private SlidingView mSlidingView ;
/*需要绑定的Activity*/
private Activity mActivity ;
/*滑动View 的滑动监听*/
private SlidingView.OnPageChangeListener mPageChangeListener ;
/*这个是当Activity 滑动到可以结束的时候用到的常量*/
private final int POSITION_FINISH = 1 ;
/*页面的View*/
private View mContextView ;
/*用于定制自己的动画效果的接口*/
private OnAnimListener mAnimListener ;
public SlidingLayout(Context context) {
this(context, null);
}
public SlidingLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
/*初始化可滑动的View*/
mSlidingView = new SlidingView(context) ;
/*吧可滑动的View 添加到当前Layout 中*/
addView(mSlidingView);
/*设置滑动监听*/
mPageChangeListener = new SlidingOnPageChangeListener() ;
mSlidingView.setOnPageChangeListener(mPageChangeListener);
mActivity = (Activity) context;
/*绑定Activity 到可滑动的View 上面*/
bindActivity(mActivity) ;
}
/**
* 侧滑View 和Activity 绑定
* @param activity
*/
private void bindActivity(Activity activity){
/*获取Activity 的最顶级ViewGroup*/
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
/*获取Activity 显示内容区域的ViewGroup,包行ActionBar*/
ViewGroup child = (ViewGroup) decorView.getChildAt(0);
decorView.removeView(child);
setContentView(child) ;
decorView.addView(