滑动结束 Activity(二)阴影效果和动画的实现

本文在上一篇实现手势滑动销毁Activity的基础上,进一步优化并添加阴影效果和动画。介绍了如何根据滑动距离绘制阴影,以及通过监听滑动事件实现动画效果。文章还提供了自定义ViewGroup的代码示例,展示了如何在Activity中应用这些效果。
摘要由CSDN通过智能技术生成

上一篇文章中讲了如何实现手势滑动来销毁页面,再来回顾一下实现的效果
这里写图片描述
具体实现请看上一篇文章 手势滑动结束 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(
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值