自定义控件-侧拉菜单

    手机版qq有一个挺不错的效果是侧拉菜单,在主界面向右滑动就会在左侧出现关于自己qq的一些信息;
    实现侧滑效果目前知道有三种:
	一是SlidingDrawer,谷歌在Android4.2之后已经不建议使用
	二是DrawerLayout,谷歌提供的挺好用的控件,只需在布局文件中加载即可
	三是第三方提供的开源控件,更加的灵活;下面就来简单介绍一下原理
  一、需求
    1.定义两个布局,菜单和主内容,然后整合在一个自定义的控件中
    2.分别测量出菜单和主内容的宽和高
    3.主内容全屏显示在屏幕上,那么左侧的菜单就会看不到,达到了隐藏菜单的效果
    4.处理屏幕的onTouchEvent()事件,实现左右滑动控制菜单的隐藏与显示
  二、具体实现
    1.定义布局文件菜单和主内容,然后整合在自定义的SlideMenu控件中
    2.在SlideMenu中通过onMeasure测量布局文件的宽和高
	
 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //测量菜单的宽和高,宽为240dip,高为父窗体高度
        //0代表菜单
        View menuView = getChildAt(0);
        menuView.measure(menuView.getLayoutParams().width, heightMeasureSpec);

        //测量内容正文的宽和高,与父窗体一致
        //1代表正文内容
        View contentView = getChildAt(1);
        contentView.measure(widthMeasureSpec, heightMeasureSpec);
    }

        在系统底层measure调用了onMeasure(定义了宽高的约束)
	onMeasrue调用了setMeasureDimension(真实的宽高信息)
    3.通过onLayout方法绘制布局
	
 @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //把测量出菜单和内容绘制屏幕上
        View menuView = getChildAt(0);
        //设置菜单在屏幕的左侧显示(即隐藏)
        menuView.layout(-menuView.getMeasuredWidth(), t, 0, b);
        //主内容的绘制
        View contentView = getChildAt(1);
        contentView.layout(l, t, r, b);
    }

    4.处理屏幕的onTouchEvent事件实现菜单的隐藏与显示
	
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int scrollX;

        switch (event.getAction()) {
            //按下
            case MotionEvent.ACTION_DOWN:
                downX = (int) event.getX();
                break;
            //移动
            case MotionEvent.ACTION_MOVE:
                int moveX = (int) event.getX();
                //偏移量
                int deltax = downX - moveX;

                scrollX = getScrollX() + deltax;
                //根据当前位置确定屏幕的显示
                if (scrollX < -getChildAt(0).getMeasuredWidth()) {
                    scrollTo(-getChildAt(0).getMeasuredWidth(), 0);
                } else if (scrollX > 0) {
                    scrollTo(0, 0);
                } else {
                    scrollBy(deltax, 0);
                }
                downX = moveX;
                break;
            //抬起
            case MotionEvent.ACTION_UP:
                int center = -getChildAt(0).getMeasuredWidth() / 2;
                scrollX = getScrollX();
                if (scrollX < center) {
                    currentState = SCREEN_CONTENT;
                } else {
                    currentState = SCREEN_MAIN;
                }
                switchScreen();
                break;
        }
        return true;
    }

    /**
     * 根据currentState的状态来更改屏幕的显示
     */
    private void switchScreen() {
        int startX = getScrollX();  //当前屏幕的X位置
        int dX = 0;                 //增量=目的位置-当前位置
        switch (currentState) {
            case SCREEN_CONTENT:
//                scrollTo(-getChildAt(0).getMeasuredWidth(),0);
                dX = -getChildAt(0).getMeasuredWidth() - startX;
                break;
            case SCREEN_MAIN:
//                scrollTo(0,0);
                dX = 0 - startX;
                break;
        }
        int duration = Math.abs(dX) * 10;
        if (duration > 1000) {
            duration = 1000;
        }

        scroller.startScroll(startX, 0, dX, 0, duration);
        invalidate();
    }

    @Override
    public void computeScroll() {
        //当不在模拟数据时候跳出递归
        if (scroller.computeScrollOffset()) {
            //获取当前模拟的数据
            int currX = scroller.getCurrX();
            //更新位置
            scrollTo(currX, 0);
            invalidate();
        }
    }


       滑动的分析:
	 1.当点击屏幕时记录下当前的位置downX,在移动的过程中根据当前位置moveX和downX计算偏移量
	   根据偏移量的值不断的修正菜单和主内容在屏幕的显示位置;
         2.当抬起时,如果菜单显示出来的内容是否大于二分之一,那么滑动显示菜单,反之显示主内容
	 3.currentState用来记录当前屏幕显示的是菜单还是主内容,并且是屏幕固定时偏移量计算的依据
	 4.scroller.startScroll(startX,0,dX,0,duration)
	   用来模拟X轴从startX到偏移dX经过duration时间的过程,但是这个方法只是模拟,并不会改变
	   屏幕的显示,还需要通过invalidate()来修改屏幕的显示
	 5.invalidate()在ViewGroup中通过调用DrawChild()->再调view.draw->computeScroll修改屏幕
	   显示的内容,由于startScroll的数据是缓慢变化的,因此需要用递归不断的更新当前的显示,就
	   实现了松手后菜单缓慢移动的效果
   三、回调简介
	Android回调方法用的特别多,其原理类似于设计模式中的观察者模式,回调通过自身提供一个内部
	接口,在接口定义统一的方法,那么不管是谁调用我,只要实现我接口中定义的方法,使代码有了很
	好的封装性
   四、个人总结
	写自定义控件一定要有的步骤:
	1.分析控件的实现都有什么状态
	2.找出状态之间转换的临界条件
	3.实现即可


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值