說明
早上看到一篇文章介紹了ResideMenu得使用,這是一個類似SlidingMenu的控件,感覺有點高尚大,反正我之前沒見過,本着湊熱鬧的好奇心,立馬clone把玩下,項目地址奉上:
https://github.com/SpecialCyCi/AndroidResideMenu.git

原理概述
在分析源代碼之前,簡單談談,這個效果在這里是如何實現的。
點擊按鈕畫面縮小為50%同時向右側滑動至中間位置,也可以向右滑動,然后那幾個個菜單項就會帶着動畫出現,動畫這里用的是nineoldandroids的兼容包,在整個過程中有三個東西要理解,一是菜單view,二是內容view,還有就是承載他們的父view,在點擊后調用AnimatorSet組合動畫把內容view向右改變,然后在把菜單view加進來。
實現分析
看過代碼后其實這個的實現方式與其他的開源控件確實不太通,之前很少看到有用承載activity的節點view來做的。
怎么使用我就不說了,直接看作者的介紹;https://github.com/SpecialCyCi/AndroidResideMenu/blob/master/README_CN.md
// attach to current activity; resideMenu = new ResideMenu(this); resideMenu.setBackground(R.drawable.menu_background); resideMenu.attachToActivity(this);
// create menu items;
String titles[] = { "Home", "Profile", "Calendar", "Settings" };
int icon[] = { R.drawable.icon_home, R.drawable.icon_profile, R.drawable.icon_calendar, R.drawable.icon_settings };
for (int i = 0; i < titles.length; i++){
ResideMenuItem item = new ResideMenuItem(this, icon[i], titles[i]);
item.setOnClickListener(this);
resideMenu.addMenuItem(item);
}
下面我們來看這個ResideMenu是怎么寫的

scaleDown_activity是一個AnimationSet的實例,直接開始動畫,view_decor當然就是承載activity的父view,最后把菜單加進來,你會發現這里加了兩次,感覺非常奇怪,因為這個sv_menu本身是處在this里面的,

按道理來說一個view是不能同時處在來個節點當中,當時我就斯巴達了,原來這里作者其實寫一個比較古怪的方法,先把sv_menu從this當中移除,在加到外面的view_dector中,也就是 if (sv_menu.getParent() != null) removeMenuLayout();這句話的用意,在菜單第一次加載時,我先出於this中,此時和sv_menu.getParent()是同一個指向,這樣的寫法在我看來味的作用就是可以減少view結構的層數,別無它用,所以完全可以這樣來寫:
話說回來作者的寫法也許有其他考量,我暫時沒注意到,修改后的代碼可以正常運行。至於前一個 if (getParent() != null) view_decor.removeView(this);比較好理解就是把菜單view先移除,不過也沒什么意義,這樣每次都重新移除加入是出於什么考慮有待商榷,所以把這兩個地方都改一下,就是:
只在第一次的時候才把菜單加入到view_dector里面再看看關閉菜單是怎么寫的:
這幾個AnimationSet的創建寫的還是比較合理,放大還原這個里面只寫了縮放的操作,縮小的里面還有縮放坐標點的設置,默認的話是view的中心,這不是我們希望的。


為了跟好的理解這個縮放的坐標點我花了一張示意圖,箭頭指向的點為屏幕寬度X1.5,高度為屏幕高度X0.5,view的高寬都縮放為50%,得到的就是紅色的位置。

其他的參考源代碼,這里只做核心的代碼分析。
