SlidingMenu源码分析及拓展:监听拉出菜单时的滚动事件,将主页变暗

这些效果以前都写过,但是之前没有积累的习惯,导致每次开始一个新项目时又要重新去翻阅资料、api,挺浪费时间的,所以打算记录一下,养成好习惯。

SlidingMenu与DrawerLayout:

SlidingMenu是一个非常火的侧拉菜单开源组件,基本上99%的项目都要用上他,Material Design之后出了一个DrawerLayout抽屉组件,也非常好用,两者对比了一下,DrawerLayout只能实现抽屉的效果,菜单拉出时覆盖在activity上面从而挡住了activity左边的部分试图,而slidingmenu的效果是推拉,会随着菜单的拉出慢慢的将activity平移推出屏幕,主要看需求吧。

效果演示
这里写图片描述

首先简单回顾一下slidingmenu的基本用法吧,以代码为主,不过多解释:

SlidingMenu menu = new SlidingMenu(this);  
        //设置菜单方向  
        menu.setMode(SlidingMenu.LEFT_RIGHT);  
        //设置滑动的范围  
        menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);  
        //设置滑动的宽度  
        menu.setBehindOffset(200);  
        //设置阴影部分的图片  
        menu.setShadowDrawable(R.color.colorPrimaryDark);  
        menu.setShadowWidth(10);  
        //设置淡入淡出的效果  
        menu.setFadeEnabled(true);  
        menu.setFadeDegree(0.4f);  
        //附加到activity  
        menu.attachToActivity(this,SlidingMenu.SLIDING_CONTENT);  
        //设置左右滑动的菜单  
        menu.setMenu(R.layout.slide_method_left);  

这个不是今天的重点,侧拉菜单是初始化出来了,但是如果我要监听菜单的滑出的距离来实时的设置某些view的值,该怎么实现呢?翻阅api及sliding源码,就这有这3个监听,根本不能满足我们的需要:

没办法只能去翻阅源码咯,源码太多,从哪开始入手呢,擒贼先禽王,谁滑动先找谁!

/**
     * Set the behind view (menu) content to the given View.
     *
     * @param view The desired content to display.
     */
    public void setMenu(View v) {
        mViewBehind.setContent(v);
    }

//找到初始化的地方
mViewBehind = new CustomViewBehind(context);
        mViewAbove = new CustomViewAbove(context);

mViewBehind就是我们的菜单view,那mViewAbove是什么呢?其实看名字就已经猜到了,behind代表在下面的菜单,那么above应该是上面的主页面,抱着这个想法我们去证实一下自己的猜测:

还记得menu.attachToActivity(this,SlidingMenu.SLIDING_CONTENT)这个方法吗?是让activity依附与slidingmenu,他有两种模式:

case SLIDING_WINDOW:
            mActionbarOverlay = false;
            ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();
            ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
            // save ActionBar themes that have transparent assets
            decorChild.setBackgroundResource(background);
            decor.removeView(decorChild);
            decor.addView(this);
            setContent(decorChild);
            break;
        case SLIDING_CONTENT:
            mActionbarOverlay = actionbarOverlay;
            // take the above view out of
            ViewGroup contentParent = (ViewGroup)activity.findViewById(android.R.id.content);
            View content = contentParent.getChildAt(0);
            contentParent.removeView(content);
            contentParent.addView(this);
            setContent(content);
            // save people from having transparent backgrounds
            if (content.getBackground() == null)
                content.setBackgroundResource(background);
            break;

/**
     * Set the above view content to the given View.
     *
     * @param view The desired content to display.
     */
    public void setContent(View view) {
        mViewAbove.setContent(view);
        showContent();
    }

代码中我们可以明确的看到,不管是那种模式,都是找到当前activity的根布局,然后先把里面的view删掉,然后把this也就是slidingmenu放入根布局中,最后将我们原来的这个主页view设置给了mViewAbove!!是不是也就是证实了我们的猜测,mViewAbove就是我们的主页,我们再找找mViewAbove、mViewBehind的一些相关事件,看能发现些什么。

一路find,终于有了发现:

mViewAbove.setOnPageChangeListener(new OnPageChangeListener() {
            public static final int POSITION_OPEN = 0;
            public static final int POSITION_CLOSE = 1;
            public static final int POSITION_SECONDARY_OPEN = 2;

            public void onPageScrolled(int position, float positionOffset,
                    int positionOffsetPixels) {
            }

            public void onPageSelected(int position) {
                if (position == POSITION_OPEN && mOpenListener != null) {
                    mOpenListener.onOpen();
                } else if (position == POSITION_CLOSE && mCloseListener != null) {
                    mCloseListener.onClose();
                } else if (position == POSITION_SECONDARY_OPEN && mSecondaryOpenListner != null ) {
                    mSecondaryOpenListner.onOpen();
                }
            }
        });

这个是不是很熟悉,有点想viewpage的滑动事件,就在这里打印log试试效果吧!

public void onPageScrolled(int position, float positionOffset,
                    int positionOffsetPixels) {
                Log.i("TAG","positionOffset:"+positionOffset+" , positionOffsetPixels:"+positionOffsetPixels);
            }

打印结果:
这里写图片描述

对了,就是它了!当主页向左滑动,偏移量数值在慢慢的减少,找到了根源就好办事咯,我给他加一个滚动监听回调,不就能解决我们的问题了吗,这是我自己加的代码:

private OnScrollDistanceListener mOnScrollDistanceListener;

public void setOnScrollDistanceListener(OnScrollDistanceListener listener){
        this.mOnScrollDistanceListener = listener;
    }

    /**
     * 监听SlidingMenu移动距离
     */
    public interface OnScrollDistanceListener{
        void  onPageScrolled( float positionOffset,
                                        int positionOffsetPixels);
    }

public void onPageScrolled(int position, float positionOffset,
                    int positionOffsetPixels) {
                if(mOnScrollDistanceListener != null){
                    mOnScrollDistanceListener.onPageScrolled(Math.abs(positionOffset),Math.abs(positionOffsetPixels));
                }
            }

有了移动的距离,是不是该给主页view设置半透明黑色遮障了,大家一定第一个想到的就是getWindow().getAttributes();然后设置alpha,这样搞了你会发现,什么鬼!我明明只想将滑出时的主页变成灰色,为什么我的菜单也变灰了。要知道getWindow()指的是整个activity界面,在刚刚的源码中我们已经看到slidingmenu已经将菜单和主页都放在了activity中,那么当然是全部都变灰了!!!

有人在想了,那我们来设置主页的alpha行吗?行,这会变色的范围定位准了,但是alpha是从不透明到透明的一个过度,不透明的时候界面变成了白色,而不是我们需要的灰色,这怎么搞?其实很简单,用最原始的办法,给主页布局最上层加一个view,大小与整个主页相等,然后通过设置它的背景色和透明度来实现,虽然听上去low一点,但是暂时真的没有找到更好的方法来实现:

<!--遮障view-->
<View
        android:id="@+id/v_filter"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#494949"
        android:visibility="gone"
        />
 //滑动距离监听
        slidingMenu.setOnScrollDistanceListener(new SlidingMenu.OnScrollDistanceListener() {
            @Override
            public void onPageScrolled(float positionOffset, int positionOffsetPixels) {
                setActivityFilter(positionOffset);
            }
        });


    /**
     * 设置activity滤镜效果
     */
    private void setActivityFilter(float positionOffset) {
        float alpha = positionOffset * 0.7f;
        iv_filter.setAlpha(alpha);
        if (alpha <= 0) {
            if (iv_filter.isShown())
                iv_filter.setVisibility(View.GONE);
        } else {
            if (!iv_filter.isShown())
                iv_filter.setVisibility(View.VISIBLE);
        }
    }

想看源码的可以参考我的开源项目:https://github.com/18973809797/BaseStorehouse
里面还有很多实用的app框架实现哦~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
slidingmenu包含slidingmenuDemo跟两个slidingmenu_lib,slidingmenu_actionbar,直接可以用。slidingmenu_lib是开源项目ActionBarSherlock-master的library类库,slidingmenu_actionbar是开源项目ActionBarSherlock-master的actionbarsherlock类库,只是重命名了,slidingmenuDemo是开源项目ActionBarSherlock-maste的Example。注意:(已修改) 1.可能报找不到getSupportActionBar等ActionBarSherLock的方法。原因是使用ActionBarSherLock的Activity需继承于SherlockActivity,修改SlidingMenu liberary(slidingmenu_lib)中的 SlidingFragmentActivity,让它继承于SherlockFragmentActivity,重新编译liberary导入。 2.项目红叉或红叹号,删除support_v4包,ActionBarSherLock(slidingmenu_actionbar)已包含此包,会冲突。也有可能是主题问题,注意appication theme是否正确,参照exsample。 3.注意把ActionBar、某些Fragment等替换成ActionBarSherLock包中的类。 SlidingMenu依赖ActionBarSherlock。可以去官网下载最新的ActionBarSherlock。在导入的SlidingMenu-master/library中的 SlidingActivity.java、SlidingFragmentActivity.java SlidingPreferenceActivity.java三个文件作如下修改就好了。 SlidingActivity extends Activity SlidingFragmentActivity extends FragmentActivity SlidingPreferenceActivity extends PreferenceActivity 分别替换成 SlidingActivity extends SherlockActivity SlidingFragmentActivity extends SherlockFragmentActivity SlidingPreferenceActivity extends SherlockPreferenceActivity

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值