Android 自定義View修煉-打造完美的自定義側滑菜單/側滑View控件

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、源碼下載:

源碼下載http://www.demodashi.com/demo/12148.html

 真題園網http://www.zhentiyuan.com

相關文章
相關標籤/搜索