Android界面动画初探之--探索侧边栏折叠效果的实现

本文详细介绍了如何通过自定义ViewGroup实现侧边栏滑动时菜单栏的折叠动画效果。主要内容包括图片的分割、矩阵变换的计算以及阴影效果的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不多说,看看效果先:
这里写图片描述
这个是我实现的Demo:http://pan.baidu.com/s/1c08qBtA
这就是今天要实现的效果;貌似这种效果以前有人实现过;今天我根据自己的探索带领大家来实现这个效果;
我记得在前面讲过自定义ViewGroup的侧边栏实现原理;http://blog.youkuaiyun.com/jike0901xuye/article/details/47804115
在这个里面我们知道了如何很方便的实现平移动画;很方便的处理触摸事件的焦点问题;今天我接着上面的知识,来带领大家搞定类似于这种自定义动画的实现。
首先大家根据效果图想一下:
要实现效果图,我们需要处理的是什么?
没错,你需要处理的是在侧边栏滑动时,需要处理菜单那一栏里面的视图绘制;也就是说我们根据边栏所在位置确定菜单内部的动画效果;当侧边栏完全打开时:我们的菜单栏应该是平铺的;随着边栏向里面滑动;菜单的内部视图应该进行一个折叠;今天我只是做了当菜单在左,主视图在右边的情况;
现在我们先分析一下这个效果:

第一:如何分割菜单栏图片
第二:如何计算每一部分转化需要的矩阵
第三:如何实现阴影效果

其实解决上上述三个问题,我们也就实现了这个效果;首先我们思考一下第一个的解决方案:分割菜单栏图片;其实也就是将菜单栏的背景图片按照层叠的层数进行切割;
我查到了用:

void android.graphics.Canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint);
将bitmap的src区域的内容绘制到画布的dst区域上;

因此切割的核心必须是上面这个方法;折叠效果的每一块都是等比例分割的,因此他们切割的位置代码如下:

             // 初始化切割图片的位置
            mRects = new Rect[foldcound];
            // 计算每一个折叠的宽度
            int foldchildwidth = width / foldcound;
            // 计算好切割图片的每一个区域
            for (int i = 0; i < foldcound; i++) {
                mRects[i] = new Rect(i * foldchildwidth, 0, (i + 1)
                        * foldchildwidth, height);
            }

现在看第二个问题:如何计算每一部分转化需要的矩阵;我又查了一下:发现有这个api:

public boolean setPolyToPoly (float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) 
大意是根据多边形变化前的坐标集合src和变化后的坐标集合dst计算出Matrix矩阵

因此切割变化的核心就是这个方法了;我们每一个都是4个点,当切割的区域在偶数层时:他们只是右边的两个左边点进行变化;当切割的区域在奇数页面时,就只是左边的两个点进行变化;切割形成的三角形的高度可以用勾股定理得出;因此可以产生大概如下的代码:

/** 根据变化计算矩阵转换 */
    //startX指的是绘制的起点,endX指的是当前菜单页面的终点,width和height都是没有折叠时候平铺的宽高
    private void getMatrixsbyscroll(int startX, int endX, int width, int height) {
        // 初始化矩阵变化数组
        float[] spoi = new float[8], dpoi = new float[8];
        // 计算每一个折叠前的宽度
        int foldchildwidth = width / foldcound;
        // 计算每一个折叠后的宽度
        int foldchangewidth = (endX - startX) / foldcound;
        // 根据勾股定理计算出折叠变化的高度
        int deteheight = (int) Math.sqrt(Math.pow(foldchildwidth, 2)
                - Math.pow(foldchangewidth, 2));
        for (int i = 0; i < foldcound; i++) {
            // 图片变化前的坐标
            // 左上角
            spoi[0] = startX + i * foldchildwidth;
            spoi[1] = 0;
            // 左下角
            spoi[2] = spoi[0];
            spoi[3] = height;
            // 右上角,纵坐标和左上角一样
            spoi[4] = spoi[0] + foldchildwidth;
            spoi[5] = spoi[1];
            // 右下角,横坐标和右上角一样
            spoi[6] = spoi[4];
            spoi[7] = height;
            // 图片变化后的坐标,这个要分奇数和偶数
            if (i % 2 == 0) {
                // 偶数情况下
                // 左上角
                dpoi[0] = startX + i * foldchangewidth;
                dpoi[1] = 0;
                // 左下角
                dpoi[2] = dpoi[0];
                dpoi[3] = height;
                // 右上角
                dpoi[4] = dpoi[0] + foldchangewidth;
                dpoi[5] = dpoi[1] + deteheight;
                // 右下角
                dpoi[6] = dpoi[4];
                dpoi[7] = height - deteheight;
            } else {
                // 奇数情况下
                // 左上角
                dpoi[0] = startX + i * foldchangewidth;
                dpoi[1] = deteheight;
                // 左下角
                dpoi[2] = dpoi[0];
                dpoi[3] = height - deteheight;
                // 右上角
                dpoi[4] = dpoi[0] + foldchangewidth;
                dpoi[5] = 0;
                // 右下角
                dpoi[6] = dpoi[4];
                dpoi[7] = height;
            }
            matrixs[i].setPolyToPoly(spoi, 0, dpoi, 0, 4);
        }
    }

第二个问题解决如上:那我们进行第三个问题:如何实现阴影?

public LinearGradient (float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile) 
以x0,y0为起点,x1,y1为终点,color0为开始颜色,color1为终止颜色的一个渐变区域绘制

上面这个方法可以实现我们需要的阴影效果;当然,阴影的透明度需要根据折叠的程度来决定;

在本例中,折叠程度和阴影程度取决于边栏滑动的程度!

下面我就上重点代码了:大家注意看代码注释就可以看出实现的原理;重点搜索dispatchDraw方法进行查看:

package com.xy.framework.widget;

import com.xy.framework.Utils.Utils;
import com.xy.framework.widget.SideView.SideViewinterface;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.Style;
import android.graphics.Shader.TileMode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.Scroller;

/**
 * @author 徐晔
 * @note 实现侧边栏的View
 */
public class Sidebarview extends RelativeLayout {

    /**
     * @author 徐晔
     * @note 侧边栏需要实现需要的配置文件
     */
    public static interface SidebarConfig {
        /** 边栏所占用的百分比 */
        public int setSidebarpercent();
        /** 左边还是右边 */
        public int setSidebarPosition();
    }

    /** 元素 */
    private class SideElements {
        /** 上下文 */
        private Context mContext;
        /** 屏幕宽度 */
        private int screenwidth;
        /** 菜单页面所在的页面 */
        private RelativeLayout mMenuLayout;
        /** 侧栏所在的页面 */
        private RelativeLayout mSideLayout;
        /** 配置文件 */
        private SidebarConfig mConfig;
        /** 触摸时需要的临时文件 */
        private int menuspace;
        private int mMotionX, mdeteX;

        public void setmMotionX(int mMotionX) {
            this.mMotionX = mMotionX;
        }

    }

    /** 元素 */
    private SideElements mElements;
    /** 平移动画实现类 */
    private Scroller mScroller;

    /** 折叠效果所需要的变量 */
    // 需要实现几个折叠页面,建议都是2的倍数
    private final int foldcound = 4;

    // 两个折叠的图片分别需要的矩阵
    private Matrix[] matrixs;
    // 将View切割成两部分的坐标
    private Rect[] mRects;
    private Rect deRect;
    // 切割前的图片
    private Bitmap viewbitmap;
    // 画阴影
    private LinearGradient shadowGrad;
    private Paint mshadowpaint;


    public void setElements(int setnumber) {
        mElements.setmMotionX(setnumber);
    }

    public RelativeLayout getmMenuLayout() {
        return mElements.mMenuLayout;
    }

    public Sidebarview(Context context, SidebarConfig sidebarConfig) {
        super(context);
        mElements = new SideElements();
        initView(context, sidebarConfig);
    }

    public Sidebarview(Context context, AttributeSet attrs,
            SidebarConfig sidebarConfig) {
        super(context, attrs);
        mElements = new SideElements();
        initView(context, sidebarConfig);
    }

    public Sidebarview(Context context, AttributeSet attrs, int defStyle,
            SidebarConfig sidebarConfig) {
        super(context, attrs, defStyle);
        mElements = new SideElements();
        initView(context, sidebarConfig);
    }

    /** 初始化组件 */
    private void initView(Context context, SidebarConfig sidebarConfig) {

        mScroller = new Scroller(context);
        // 设置
        mElements.mContext = context;
        mElements.screenwidth = Utils.getScreenSize(context)[0];
        mElements.mConfig = sidebarConfig;

        this.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        // 添加菜单页面
        mElements.mMenuLayout = new RelativeLayout(context) {
             //重点方法,不知道为什么我重写这个方法的最好去百度一下
            @Override
            protected void dispatchDraw(Canvas canvas) {
                // 获取原始坐标
                int endX = mElements.mSideLayout.getScrollX();
                // 当没有折叠时
                if (-endX == mElements.menuspace) {
                    super.dispatchDraw(canvas);
                    return;
                }
                int width = getChildAt(0).getMeasuredWidth();
                int height = getChildAt(0).getMeasuredHeight();

                // 获取到侧边栏的视图
                if (getChildAt(0) != null && viewbitmap == null) {
                    viewbitmap = Bitmap.createBitmap(width, height,
                            Bitmap.Config.ARGB_8888);
                    Canvas canvas2 = new Canvas(viewbitmap);
                    getChildAt(0).draw(canvas2);
                }

                endX = Math.abs(endX);
                //准备绘制所需要的数据
                perpareFolddata(width, height);
                //计算折叠效果需要的数据
                getMatrixsbyscroll(0, endX, width, height);
                Rect src;
                for (int i = 0; i < foldcound; i++) {
                    src = mRects[i];
                    canvas.save();
                    //将效果连接起来
                    canvas.concat(matrixs[i]);
                    if (deRect == null) {
                        deRect = new Rect();
                    }
                    // 设置需要绘制到的地方
                    deRect.set(src.left, src.top, src.left + src.width(),
                            src.height());
                    // 分别绘制每一块扇形区域
                    canvas.drawBitmap(viewbitmap, src, deRect, null);
                    // 计算阴影的透明度
                    int shadowalpha = 255 * (width - (endX - 0)) / width;
                    if (mshadowpaint == null) {
                        mshadowpaint = new Paint();
                        mshadowpaint.setStyle(Style.FILL);
                    }
                    // 设置阴影的透明度,折叠程度越深,透明度越低,也就是说看起来越暗
                    mshadowpaint.setAlpha(shadowalpha);
                    if (i % 2 == 0) {
                        shadowGrad = new LinearGradient(i * width / foldcound,
                                0, (i + 1) * width / foldcound, 0,
                                Color.TRANSPARENT, Color.BLACK, TileMode.CLAMP);
                    } else {
                        shadowGrad = new LinearGradient(i * width / foldcound,
                                0, (i + 1) * width / foldcound, 0, Color.BLACK,
                                Color.TRANSPARENT, TileMode.CLAMP);

                    }
                    mshadowpaint.setShader(shadowGrad);
                    // 绘制阴影
                    canvas.drawRect(i * width / foldcound, 0, (i + 1) * width
                            / foldcound, height, mshadowpaint);
                    canvas.restore();
                }
            }
        };
        mElements.mMenuLayout.setId(0);
        mElements.mMenuLayout.setTag("sidemenu");
        LayoutParams mMenuParams = new LayoutParams(mElements.screenwidth
                * ((100 - mElements.mConfig.setSidebarpercent())) / 100,
                LayoutParams.MATCH_PARENT);
        mElements.mMenuLayout.setLayoutParams(mMenuParams);
        addView(mElements.mMenuLayout);
        // 添加侧边栏页面
        mElements.mSideLayout = new RelativeLayout(context) {

            /** 平移动画 */
            @Override
            public void computeScroll() {
                mElements.mMenuLayout.postInvalidate();
                if (mScroller.computeScrollOffset()) {
                    mElements.mSideLayout.scrollTo(mScroller.getCurrX(), 0);
                    mElements.mSideLayout.postInvalidate();
                }

                if (mElements.mConfig.setSidebarPosition() % 2 == 0) {
                    if (mElements.mSideLayout.getScrollX() == mElements.menuspace) {
                        mElements.mMenuLayout.invalidate();
                        return;
                    }
                    if (mElements.mSideLayout.getScrollX() == 0) {
                        return;
                    }
                    mElements.mMenuLayout.scrollTo(
                            (-mElements.menuspace + mElements.mSideLayout
                                    .getScrollX()) >> 1, 0);
                }
                if (mElements.mConfig.setSidebarPosition() % 2 == 1) {
                    if (mElements.mSideLayout.getScrollX() == 0) {
                        return;
                    }
                    if (mElements.mSideLayout.getScrollX() == mElements.menuspace) {
                        mElements.mMenuLayout.invalidate();
                        return;
                    }
                }
                super.computeScroll();
            }
        };
        mElements.mSideLayout.setId(1);
        mElements.mSideLayout.setTag("sideside");
        LayoutParams mSideParams = new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT);
        mElements.mSideLayout.setLayoutParams(mSideParams);
        addView(mElements.mSideLayout);
        mElements.menuspace = mElements.screenwidth
                * (100 - mElements.mConfig.setSidebarpercent()) / 100;
    }

    /** 给主页添加页面 */
    public void addViewtoMenu(View view) {
        mElements.mMenuLayout.addView(view, new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    }

    /** 给菜单栏添加页面 */
    public void addViewtoSide(View view, SideViewinterface sideViewinterface) {
        SideView mSideView = new SideView(mElements.mContext, sideViewinterface);
        mSideView.addView(view);
        mElements.mSideLayout.addView(mSideView, new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        if (mElements.mConfig.setSidebarPosition() % 2 == 0) {
            mSideView.setOnTouchListener(new mSidebarTouchListenerLeft());
        }
        if (mElements.mConfig.setSidebarPosition() % 2 == 1) {
            mSideView.setOnTouchListener(new mSidebarTouchListenerRight());
        }
    }

    /** 右边滑动时的触摸事件 */
    private class mSidebarTouchListenerRight implements OnTouchListener {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int touchX = (int) event.getX();
            switch (event.getAction()) {
            // 按下
            case MotionEvent.ACTION_DOWN:
                mElements.mMotionX = touchX;
                return true;
                // 移动
            case MotionEvent.ACTION_MOVE:
                mElements.mdeteX = touchX - mElements.mMotionX;
                if (mElements.mSideLayout.getScrollX() - mElements.mdeteX
                        + mElements.menuspace >= 0
                        && mElements.mSideLayout.getScrollX()
                                - mElements.mdeteX <= 0) {
                    mElements.mSideLayout.scrollBy(-mElements.mdeteX, 0);
                }
                return true;
                // 抬起
            case MotionEvent.ACTION_UP:
                if (Math.abs(mElements.mdeteX) < 24) {
                    if (mElements.mSideLayout.getScrollX() == mElements.menuspace) {
                        close();
                    }
                }
                if (mElements.mSideLayout.getScrollX() > -mElements.menuspace >> 1) {
                    startAnimation(mElements.mSideLayout.getScrollX(), 0, 0, 0, 300);
                } else {
                    startAnimation(mElements.mSideLayout.getScrollX(), 0, -mElements.menuspace, 0, 300);
                }
                mElements.mdeteX = 0;
                mElements.mMotionX = 0;
                return true;
            }
            return false;
        }

    }

    /** 左边触摸时实现的事件 */
    private class mSidebarTouchListenerLeft implements OnTouchListener {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int touchX = (int) event.getX();
            switch (event.getAction()) {
            // 按下
            case MotionEvent.ACTION_DOWN:
                mElements.mMotionX = touchX;
                return true;
                // 滑动
            case MotionEvent.ACTION_MOVE:
                if (mElements.mMotionX == 0) {
                    mElements.mMotionX = touchX;
                }
                mElements.mdeteX = touchX - mElements.mMotionX;
                if (mElements.mSideLayout.getScrollX() - mElements.menuspace
                        - mElements.mdeteX <= 0
                        && mElements.mSideLayout.getScrollX()
                                - mElements.mdeteX >= 0) {
                    mElements.mSideLayout.scrollBy(-mElements.mdeteX, 0);
                }
                return true;
                // 抬起
            case MotionEvent.ACTION_UP:
                if (Math.abs(mElements.mdeteX) < 24) {
                    if (mElements.mSideLayout.getScrollX() == mElements.menuspace) {
                        close();
                    }
                }
                if (mElements.mSideLayout.getScrollX() >= mElements.menuspace >> 1) {
                    startAnimation(mElements.mSideLayout.getScrollX(), 0, mElements.menuspace, 0, 300);
                } else {
                    startAnimation(mElements.mSideLayout.getScrollX(), 0, 0, 0, 300);
                }
                mElements.mdeteX = 0;
                mElements.mMotionX = 0;
                return true;
            }
            return false;
        }
    }

    /** 侧边栏动画 */

    private void startAnimation(int startX, int startY, int endX, int endY,
            int time) {
        if (!mScroller.computeScrollOffset()) {
            mScroller.setFinalX(endX);
            mScroller.setFinalY(endY);
            mScroller.startScroll(startX, startY, endX - startX, endY - startY,
                    time);
            mElements.mSideLayout.invalidate();
        }
    }

    /**
     * 判断其是否打开
     * 
     * @return
     */
    public boolean isopen() {
        if (mElements.mSideLayout.getScrollX() == 0) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 打开侧边栏
     */
    public void open() {
        if (!mScroller.computeScrollOffset()) {
            if (mElements.mConfig.setSidebarPosition() % 2 == 0) {
                mScroller.setFinalX(mElements.menuspace);
                mScroller.setFinalY(0);
                mScroller.startScroll(mElements.mSideLayout.getScrollX(), 0,
                        mElements.menuspace, 0, 600);
            } else {
                mScroller.setFinalX(-mElements.menuspace);
                mScroller.setFinalY(0);
                mScroller.startScroll(
                        mElements.mSideLayout.getScrollX(),
                        0,
                        mScroller.getFinalX()
                                - mElements.mSideLayout.getScrollX(), 0, 600);
            }
            mElements.mSideLayout.invalidate();
        }
    }

    /**
     * 关闭侧边栏
     */
    public void close() {
        if (!mScroller.computeScrollOffset()) {
            if (mElements.mConfig.setSidebarPosition() % 2 == 0) {
                mScroller.setFinalX(0);
                mScroller.setFinalY(0);
                mScroller.startScroll(
                        mElements.mSideLayout.getScrollX(),
                        0,
                        mScroller.getFinalX()
                                - mElements.mSideLayout.getScrollX(), 0, 600);
            } else {
                mScroller.setFinalX(0);
                mScroller.setFinalY(0);
                mScroller.startScroll(
                        mElements.mSideLayout.getScrollX(),
                        0,
                        mScroller.getFinalX()
                                - mElements.mSideLayout.getScrollX(), 0, 600);
            }

            mElements.mSideLayout.invalidate();
        }

    }

    /** 初始化折叠的数据 */
    private void perpareFolddata(int width, int height) {
        // 初始化各个形状变化的矩阵
        if (matrixs == null) {
            matrixs = new Matrix[foldcound];
            for (int i = 0; i < foldcound; i++) {
                matrixs[i] = new Matrix();
            }
        }
        if (mRects == null) {
            // 初始化切割图片的位置
            mRects = new Rect[foldcound];
            // 计算每一个折叠的宽度
            int foldchildwidth = width / foldcound;
            // 计算好切割图片的每一个区域
            for (int i = 0; i < foldcound; i++) {
                mRects[i] = new Rect(i * foldchildwidth, 0, (i + 1)
                        * foldchildwidth, height);
            }
        }

    }

    /** 根据变化计算矩阵转换 */
    private void getMatrixsbyscroll(int startX, int endX, int width, int height) {
        // 初始化矩阵变化数组
        float[] spoi = new float[8], dpoi = new float[8];
        // 计算每一个折叠前的宽度
        int foldchildwidth = width / foldcound;
        // 计算每一个折叠后的宽度
        int foldchangewidth = (endX - startX) / foldcound;
        // 根据勾股定理计算出折叠变化的高度
        int deteheight = (int) Math.sqrt(Math.pow(foldchildwidth, 2)
                - Math.pow(foldchangewidth, 2));
        for (int i = 0; i < foldcound; i++) {
            // 图片变化前的坐标
            // 左上角
            spoi[0] = startX + i * foldchildwidth;
            spoi[1] = 0;
            // 左下角
            spoi[2] = spoi[0];
            spoi[3] = height;
            // 右上角,纵坐标和左上角一样
            spoi[4] = spoi[0] + foldchildwidth;
            spoi[5] = spoi[1];
            // 右下角,横坐标和右上角一样
            spoi[6] = spoi[4];
            spoi[7] = height;
            // 图片变化后的坐标,这个要分奇数和偶数
            if (i % 2 == 0) {
                // 偶数情况下
                // 左上角
                dpoi[0] = startX + i * foldchangewidth;
                dpoi[1] = 0;
                // 左下角
                dpoi[2] = dpoi[0];
                dpoi[3] = height;
                // 右上角
                dpoi[4] = dpoi[0] + foldchangewidth;
                dpoi[5] = dpoi[1] + deteheight;
                // 右下角
                dpoi[6] = dpoi[4];
                dpoi[7] = height - deteheight;
            } else {
                // 奇数情况下
                // 左上角
                dpoi[0] = startX + i * foldchangewidth;
                dpoi[1] = deteheight;
                // 左下角
                dpoi[2] = dpoi[0];
                dpoi[3] = height - deteheight;
                // 右上角
                dpoi[4] = dpoi[0] + foldchangewidth;
                dpoi[5] = 0;
                // 右下角
                dpoi[6] = dpoi[4];
                dpoi[7] = height;
            }
            matrixs[i].setPolyToPoly(spoi, 0, dpoi, 0, 4);

        }
    }

    /** 控制组件的位置 */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            int measuredWidth = childView.getMeasuredWidth();
            int measuredHeight = childView.getMeasuredHeight();
            if (mElements.mConfig.setSidebarPosition() % 2 == 0) {
                if (childView.getId() == 0) {
                    childView.layout(
                            mElements.screenwidth
                                    * (mElements.mConfig.setSidebarpercent())
                                    / 100, 0, mElements.screenwidth
                                    * (mElements.mConfig.setSidebarpercent())
                                    / 100 + measuredWidth, measuredHeight);
                } else {
                    childView.layout(0, 0, measuredWidth, measuredHeight);
                }
            }
            if (mElements.mConfig.setSidebarPosition() % 2 == 1) {
                childView.layout(0, 0, measuredWidth, measuredHeight);
            }
        }
    }

    /** 度量组件的大小 */
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(widthSize, heightSize);
    }
}

相关代码1:

package com.xy.framework.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;

/**
 * @author 徐晔
 */
public class SideView extends RelativeLayout{

    /**
     * @author 徐晔
     * @note 传递触摸事件的接口
     */
    public static interface SideViewinterface {
        /**传递onInterceptTouchEvent*/
        public boolean onSideInterceptTouchEvent(MotionEvent ev);
    }

    private SideViewinterface mSideViewinterface;
    public SideView(Context context, AttributeSet attrs, int defStyle,SideViewinterface mSideViewinterface ) {
        super(context, attrs, defStyle);
        this.mSideViewinterface=mSideViewinterface;
    }

    public SideView(Context context, AttributeSet attrs,SideViewinterface mSideViewinterface ) {
        super(context, attrs);
        this.mSideViewinterface=mSideViewinterface;
    }

    public SideView(Context context,SideViewinterface mSideViewinterface ) {
        super(context);
        this.mSideViewinterface=mSideViewinterface;
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        return mSideViewinterface.onSideInterceptTouchEvent(ev);
    }

    /** 测量位置 */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            int measuredWidth = childView.getMeasuredWidth();
            int measuredHeight = childView.getMeasuredHeight();
            childView.layout(0, 0, measuredWidth, measuredHeight);
        }
    }

    /** 度量大小 */
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);


        setMeasuredDimension(widthSize, heightSize);
    }

}

Activity中的代码:

package com.xy.framework;

import com.example.xyframework.R;
import com.xy.framework.widget.SideView.SideViewinterface;
import com.xy.framework.widget.Sidebarview;
import com.xy.framework.widget.Sidebarview.SidebarConfig;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.RelativeLayout;

public class SidebarActivity extends Activity {

    private Sidebarview view;
    private RelativeLayout menu, side;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        menu = (RelativeLayout) getLayoutInflater()
                .inflate(R.layout.menu, null);
        side = (RelativeLayout) getLayoutInflater()
                .inflate(R.layout.side, null);
        view = new Sidebarview(this, new SidebarConfig() {
            @Override
            public int setSidebarpercent() {
                return 50;
            }

            @Override
            public int setSidebarPosition() {
                return 1;
            }
        });
        view.addViewtoMenu(menu);
        view.addViewtoSide(side, new SideViewinterface() {
            @Override
            public boolean onSideInterceptTouchEvent(MotionEvent ev) {
                // TODO 自动生成的方法存根
                return false;
            ```


        });
        setContentView(view);
    }
}

其实实现的原理并不难;只要你仔细分析,类似于这种效果,你首先要将它分解开来看;然后分别找到实现相应效果的办法,最终将他组合在一起,那么就可以了;照着这篇介绍的原理,我相信大家可以自己研究一下类似于翻页效果的例子等等;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值