1、概述html
在App中,常常會出現側滑菜單,側滑滑出View等效果,雖說Android有不少第三方開源庫,可是實際上android
我們能夠本身也寫一個自定義的側滑View控件,其實不難,主要涉及到如下幾個要點:ide
1.對Android中Window類中的DecorView有所瞭解佈局
2.對Scroller類實現平滑移動效果post
3.自定義ViewGroup的實現動畫
首先來看看效果圖吧:this
下面如今就來講說這裏我們實現側滑View的基本思路吧,這裏我採用的是自定義一個繼承於RelativeLayout的控件叫作XCSlideView類吧。spa
首先從佈局文件中inflater出來一個menuView,而後經過addView的方法,將該側滑View添加到自定義的控件View中.net
怎麼讓XCSlideView 這個側滑View 隱藏到屏幕以外呢?很簡單經過ScrollTo方法,移動一個屏幕寬度的距離便可,這裏以設計
左側滑出爲例吧,只須要這樣 XCSlideView.this.scrollTo(mScreenWidth, 0);mScreenWidth是屏幕寬度。下面還要處理的就是底下的
半透明黑色的蒙層效果,這個其實就是一個View,而後設置半透明效果。這個固然簡單了,關鍵是我們讓他顯示在我們的自定義側滑View的下面呢,
這裏我們先給出DecorView的簡單分析,方便下面介紹添加半透明View蒙層下:
下面是對上面這張圖的解釋:
一、DecorView爲整個Window界面的最頂層View。
二、DecorView只有一個子元素爲LinearLayout。表明整個Window界面,包含通知欄,標題欄,內容顯示欄三塊區域。
三、LinearLayout裏有兩個FrameLayout子元素。
(20)爲標題欄顯示界面。只有一個TextView顯示應用的名稱。也能夠自定義標題欄,載入後的自定義標題欄View將加入FrameLayout中。
(21)爲內容欄顯示界面。就是setContentView()方法載入的佈局界面,加入其中。
有了上面的DecorVIew知識背景,如今就來講說 怎麼添加蒙層View和將自定義側滑View添加到Activity的DecorView中,首先把蒙層View添加到
(31)customView中去,而後將自定義側滑View添加到 (21)FrameLayout中去,至於爲何要這樣,是由於考慮到自定義側滑View不必定是寬度爲
屏幕寬度,因此才這麼作,並且也方面處理有無標題欄,有無採用沉浸式狀態欄設計等狀況。
2、自定義側滑View的實現
根據上面的概述,你們應該知道大概的思路了,下面我就給出自定義側滑View類的核心代碼:
一、自定義側滑View用到的變量:
//側滑方向-從哪側滑出 public static enum Positon { LEFT, RIGHT } private Context mContext; private Activity mActivity; private Scroller mScroller = null; //側滑菜單佈局View private View mMenuView; //底部蒙層View private View mMaskView; private int mMenuWidth = 0; //屏幕寬度 private int mScreenWidth = 0; //是否在滑動中 private boolean mIsMoving = false; //顯示登陸界面與否 private boolean mShow = false; //滑動動畫時間 private int mDuration = 600; //缺省側滑方向爲左 private Positon mPositon = Positon.LEFT;
二、初始化建立自定義側滑View:
** * 建立側滑菜單View */ public static XCSlideView create(Activity activity) { XCSlideView view = new XCSlideView(activity); return view; } /** * 建立側滑菜單View */ public static XCSlideView create(Activity activity, Positon positon) { XCSlideView view = new XCSlideView(activity); view.mPositon = positon; return view; }
三、建立半透明蒙層View,並添加到contentView中去
/** * 建立 蒙層View並添加到contentView中 */ private void attachToContentView(Activity activity, Positon positon) { mPositon = positon; ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content); ViewGroup contentView = ((ViewGroup) contentFrameLayout.getChildAt(0)); mMaskView = new View(activity); mMaskView.setBackgroundColor(mContext.getResources().getColor(R.color.mask_color)); contentView.addView(mMaskView, contentView.getLayoutParams()); mMaskView.setVisibility(View.GONE); mMaskView.setClickable(true); mMaskView.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if (isShow()) { dismiss(); } } }); }
四、設置側滑菜單View,並添加到DectorView->LinearLayout->內容顯示區域View(FrameLayout)中
/** * 設置側滑菜單View,並添加到DectorView->LinearLayout->內容顯示區域View中 */ public void setMenuView(Activity activity, View view) { mActivity = activity; mMenuView = view; LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); addView(mMenuView, params); mMenuView.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub mMenuWidth = mMenuView.getWidth(); switch (mPositon) { case LEFT: XCSlideView.this.scrollTo(mScreenWidth, 0); break; case RIGHT: XCSlideView.this.scrollTo(-mScreenWidth, 0); break; } } }); ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content); ViewGroup contentView = contentFrameLayout; contentView.addView(this); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) this.getLayoutParams(); switch (mPositon) { case LEFT: layoutParams.gravity = Gravity.LEFT; layoutParams.leftMargin = 0; break; case RIGHT: layoutParams.gravity = Gravity.RIGHT; layoutParams.rightMargin = 0; break; } TextView titleFrameLayout = (TextView) activity.findViewById(android.R.id.title); if( titleFrameLayout != null){ layoutParams.topMargin = DensityUtil.getStatusBarHeight(mContext); } int flags = mActivity.getWindow().getAttributes().flags; int flag = (flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); if(flag == WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS){ //說明狀態欄使用沉浸式 layoutParams.topMargin = DensityUtil.getStatusBarHeight(mContext); } this.setLayoutParams(layoutParams); }
五、處理自定義側滑View的側滑滑動和隱藏效果:
/** * 顯示側滑菜單View */ public void show(){ if(isShow() && !mIsMoving) return; switch (mPositon) { case LEFT: startScroll(mMenuWidth, -mMenuWidth, mDuration); break; case RIGHT: startScroll(-mMenuWidth, mMenuWidth, mDuration); break; } switchMaskView(true); mShow = true; } /** * 蒙層顯示開關 */ private void switchMaskView(boolean bShow){ if(bShow){ mMaskView.setVisibility(View.VISIBLE); Animation animation = new AlphaAnimation(0.0f, 1.0f); animation.setDuration(mDuration); mMaskView.startAnimation(animation); }else{ mMaskView.setVisibility(View.GONE); } } /** * 關閉側滑菜單View */ public void dismiss() { // TODO Auto-generated method stub if(!isShow() && !mIsMoving) return; switch (mPositon) { case LEFT: startScroll(XCSlideView.this.getScrollX(), mMenuWidth, mDuration); break; case RIGHT: startScroll(XCSlideView.this.getScrollX(), -mMenuWidth, mDuration); break; } switchMaskView(false); mShow = false; } public boolean isShow(){ return mShow; } @Override public void computeScroll() { // TODO Auto-generated method stub if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); // 更新界面 postInvalidate(); mIsMoving = true; } else { mIsMoving = false; } super.computeScroll(); } /** * 拖動移動 */ public void startScroll(int startX, int dx,int duration){ mIsMoving = true; mScroller.startScroll(startX,0,dx,0,duration); invalidate(); }
3、如何使用該自定義側滑View控件
使用起來,比較簡單,經過create方法建立一個側滑VIew,而後經過setMenuView方法設置一個側滑View進去,有須要設置
寬度的話, 經過setMenuWidth方法來設置便可,最後用show()方法滑出來就能夠啦,使用起來是否是很方便?
private XCSlideView mSlideViewLeft; //屏幕寬度 private int mScreenWidth = 0; View menuViewLeft = LayoutInflater.from(mContext).inflate(R.layout.layout_slideview,null); mSlideViewLeft = XCSlideView.create(this, XCSlideView.Positon.LEFT); mSlideViewLeft.setMenuView(MainActivity.this, menuViewLeft); mSlideViewLeft.setMenuWidth(mScreenWidth * 7 / 9); Button left = (Button)findViewById(R.id.btn_left); left.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if (!mSlideViewLeft.isShow()) mSlideViewLeft.show(); } });
4、源碼下載: