模仿QQ5.0侧滑菜单栏

/*
 * 自定义的ViewGroup
 * 
 * 1/onMeasure
 * 决定内部的子View的宽和高,以及最后决定自己的宽和高
 * 
 * 2/onLayout
 * 决定子View的摆放位置
 * 
 * 3/onTouchEvent
 * 
 */

import com.nineoldandroids.view.ViewHelper;

import android.content.Context;
import android.content.res.Resources;
import android.text.method.MovementMethod;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

public class SlidingMenu extends HorizontalScrollView {

    private LinearLayout mWapper;
    private ViewGroup mMenu;
    private ViewGroup mContent;

    private int WindowWidth;

    //单位是dp,但是我们要px,需要转化
    private int mMenuRightPadding = 50;

    private int mMenuWidth;

    private boolean once;

    private boolean isOpen;

    /**
     * 未使用自定义属性是,调用两个参数的构造方法
     * @param context
     * @param attrs
     */
    public SlidingMenu(Context context, AttributeSet attrs) {
        super(context, attrs);
        getResources();

        /**
         * Activity类里面有getSystemService方法,Context类下也有getSystemService方法
         * 
         * 两个getSystemService的参数是Context.xxx 如Context.WINDOW_SERVICE Context.LOCATION_SEVICE
         */

        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);

        WindowWidth = outMetrics.widthPixels;

        /**
         * context有getResource方法,View也有getResource方法,Activity也有getResource方法
         */
        //把dp转化为px
        mMenuRightPadding = 
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());

    }


    /*
     * 设置子view的宽和高,设置自己的宽和高
     * @see android.widget.HorizontalScrollView#onMeasure(int, int)
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        /**
         * onMeasure会被多次调用,为避免每次都设置一下宽和高,使用once
         */
        if(!once){
            /*
             * ViewGroup下的getChildAt(index)方法 ,返回值类型为View
             */
            //HorizontalScrollView里面有且只有一个LinearLayout
            mWapper = (LinearLayout) getChildAt(0);

            mMenu = (ViewGroup) mWapper.getChildAt(0);
            mContent = (ViewGroup) mWapper.getChildAt(1);

            /*
             * View下面的getLayoutParams()方法,返回类型为ViewGroup.LayoutParams
             */
            mMenuWidth = mMenu.getLayoutParams().width = WindowWidth - mMenuRightPadding;
            mContent.getLayoutParams().width = WindowWidth;

            //mWapper里面有mMenu和mContent,就不显示设置自己了

            once = true;


        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);


    }

    /***
     * 设置偏移量,将Menu隐藏
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
        super.onLayout(changed, l, t, r, b);

        //如果布局发生改变
        if(changed){
            /*
             * x为正,内容区向左移动
             */
            this.scrollTo(mMenuWidth, 0);
        }

    }


    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub

        int action = ev.getAction();

        switch (action) {
        case MotionEvent.ACTION_UP:
            int scrollX = getScrollX();//获取当前所处的X坐标
            if(scrollX > mMenuWidth/2){
                this.smoothScrollTo(mMenuWidth, 0);
                isOpen = false;
            }
            else{
                this.smoothScrollTo(0, 0);
                isOpen = true;
            }
            return true;

        default:
            break;
        }

        return super.onTouchEvent(ev);
    }

    public void openMenu(){
        if(isOpen){

        }
        else{
            this.smoothScrollTo(0, 0);
            isOpen = true;
        }
    }

    public void closeMenu(){
        if(isOpen){
            this.smoothScrollTo(mMenuWidth, 0);
            isOpen = false;
        }
    }

    public void switchMenu(){
        if(isOpen){
            closeMenu();
        }
        else{
            openMenu();
        }
    }


    /*
     * 滚动发生时,不管是自动滚动还是手动滚动
     * (non-Javadoc)
     * @see android.view.View#onScrollChanged(int, int, int, int)
     */
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        // TODO Auto-generated method stub

        super.onScrollChanged(l, t, oldl, oldt);
        /*
         * 调用属性动画,设置TranslationX
         * 
         * PS:Translation意思是平移
         */
        float scale = (float) (1.0*l/mMenuWidth); //由于l的变化,是scale在0-1之间变化
        ViewHelper.setTranslationX(mMenu, (float) (mMenuWidth*scale*0.7));
        /*直接mMenu.setTranslationX(l);兼容到3.0,

            或者ViewHelper.setTransklationX(mMenu, l);兼容到2.0,
         * 
         */
        float mContentScale = (float) (0.7 + 0.3 * scale);
        ViewHelper.setScaleX(mContent, mContentScale);
        ViewHelper.setScaleY(mContent, mContentScale);
        ViewHelper.setPivotX(mContent, 0);
        ViewHelper.setPivotY(mContent, (float) (1.0* mContent.getHeight() / 2));

        float mMenuScale = (float) (1.0 - 0.3 * scale);
        ViewHelper.setScaleX(mMenu, mMenuScale);
        ViewHelper.setScaleY(mMenu, mMenuScale);
        ViewHelper.setPivotX(mMenu, 0);
        ViewHelper.setPivotY(mMenu, (float) (1.0*mMenu.getHeight()/2));

        float mMenuAlpha = (float) (1.0 - 0.3 * scale);
        ViewHelper.setAlpha(mMenu, mMenuAlpha);
        ViewHelper.setPivotX(mMenu, 0);
        ViewHelper.setPivotY(mMenu, (float) (1.0*mMenu.getHeight()/2));
    }

    /**
     * QQ5.0抽屉式效果,显示菜单时,菜单区大小比例由0.7到1.0,
     * 内容区大小比例由1.0到0.7,菜单区透明度由0.7到1.0
     * float scale 1.0-0.0
     * float mMenuScale = 0.7 + 0.3 * scale
     * float mContentScale = 1.0 - 0.3 * scale
     * float mMenuAlpha = 0.7 + 0.3 * scale
     */

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值