侧滑菜单的实现方式(一):自定乂控件

主页面的布局


   
   

   
   

    
    
    
        
     
     
        
     
     
    
    
    


   
   

左边菜单的布局


   
   

   
   

    
    
    

        
     
     
        
     
     

        
     
     

        
     
     

        
     
     

        
     
     

        
     
     

        
     
     

        
     
     

    
    
    



   
   

右边菜单的布局

    
    

    
    
    
    
     
     

    
     
     

        
      
      

        
      
      
        
        
      
      
    
     
     
    
    
     
     


    
    

自定义控件的代码
package com.example.administrator.slidingmenu;

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

/*
 *  @项目名:  SlidingMenu 
 *  @包名:    com.example.administrator.slidingmenu
 *  @文件名:   SlidingMenu
 *  @创建者:   Administrator
 *  @创建时间:  2016/8/16 0016 下午 4:35
 *  @描述:    TODO
 */
public class SlidingMenu extends ViewGroup {
    private static final String TAG = "SlidingMenu";
    private float mStartX;
    private float mStartY;
    private View mChildLeft;
    private Scroller mScroller;
    private boolean flag = false;


    public SlidingMenu(Context context) {
        this(context, null);

    }

    public SlidingMenu(Context context, AttributeSet attrs) {
        super(context, attrs);
        mScroller = new Scroller(context);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);


    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        //得到右边菜单的view
        View childRight = getChildAt(1);
        childRight.layout(0, 0, childRight.getMeasuredWidth(), childRight.getMeasuredHeight());
        //得到左边的菜单view,进行布局
        mChildLeft = getChildAt(0);
        mChildLeft.layout(-mChildLeft.getMeasuredWidth(), 0, 0, mChildLeft.getMeasuredHeight());


    }

    //对左右滑动的事件进行拦截,父容器自己消费
    @Override
    public boolean onInterceptHoverEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //得到初始的位置
                mStartX = event.getX();
                mStartY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                //得到当前的位置
                float currentX = event.getX();
                float currentY = event.getY();
                //取水平和上下移动的距离绝对值
                float dx = Math.abs(currentX - mStartX);
                float dy = Math.abs(currentY - mStartX);
                //如果水平距离大于上下距离,则消费事件
                if (dx > dy) {
                    return true;
                }
                break;
        }
        return super.onInterceptTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mStartX = event.getX();
                mStartY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float moveX = event.getX();
                float dx = mStartX - moveX;//得到是一个相对值,这个值可以直接作为偏移量(正负)
                //得到绝对距离,
                float finalX = getScrollX() + dx;
                //确定平移的边界
                if (dx > 0) {//偏移量大于0,向左边移动,越界
                    scrollTo(0, 0);
                    return true;
                }
                if (finalX < -mChildLeft.getMeasuredWidth()) {
                    //坐标为负的,偏移量为正
                    scrollTo(-mChildLeft.getMeasuredWidth(), 0);
                    return true;
                }
                scrollBy((int) dx, 0);

                break;
            case MotionEvent.ACTION_UP:
                //放开的时候,如果左边菜单一半,滑出.否则退回
                int the = -mChildLeft.getMeasuredWidth() / 2;
                if (getScrollX() > the) {
                    //没有一半,退回
                    //                    scrollTo(0, 0);
                    close();
                    return true;

                } else if (getScrollX() < the) {
                    //                    scrollTo(-mChildLeft.getMeasuredWidth(), 0);
                    open();
                    return true;
                }
                break;
        }
        return true;

    }

    //定义一个平滑滑动的方法,可以控制滑动目的的时间和距离
    private void smoothScrollTo(int end) {
        //相对与起始点已将滑动的距离
        int startX = getScrollX();
        int dx = end - startX;
        //开始滑动
        mScroller.startScroll(startX, 0, dx, 0, 500);
        //重新绘制
        invalidate();
    }

    //重新computescroller方法,用于得到子容器的布局参数值的变化
    @Override
    public void computeScroll() {

        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), 0);
            invalidate();
        }

    }

    private void open() {
        smoothScrollTo(-mChildLeft.getMeasuredWidth());
        flag=true;

    }

    private void close() {
        smoothScrollTo(0);
        flag=false;
    }
    public  void toggle(){
        if (flag){
            close();
        }else{
            open();
        }
    }
}

acitvity页面的代码
public class MainActivity extends AppCompatActivity {

    private SlidingMenu mSlidingMenu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSlidingMenu = (SlidingMenu) findViewById(R.id.slidingmenu);
    }
    public void  onBack(View view){
        mSlidingMenu.toggle();
    }
    public void OnTabClick(View v) {
        //点击菜单选项,关闭侧滑菜单,弹出toast
        mSlidingMenu.toggle();

    }
}

源码下载


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值