仿QQ側滑菜單效果

這裏寫圖片描述

1、繼承HorizontalScrollerView(水平滾動條),好處:無需判斷高度只需考慮水平寬度,可以省去MOVE衝突的處理。
2、菜單佈局文件left_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/img_frame_background"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

          <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/img_1"
            android:gravity="center"
            android:textColor="#ffffff"
            android:textSize="20sp"
            android:text="第一個文本" />
          <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/img_2"
            android:gravity="center"
             android:textColor="#ffffff"
            android:textSize="20sp"
            android:text="第二個文本" />

    </LinearLayout> 

</RelativeLayout>

mainActivity.xml文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:dan="http://schemas.android.com/apk/res/com.example.recycleview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.recycleview.view.SlidingMenu
        android:id="@+id/id_menu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        dan:rightPadding="100dp" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal" >

            <include layout="@layout/left_menu" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/qq" >

                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:onClick="toggleMenu"
                    android:text="切換菜單" />
            </LinearLayout>
        </LinearLayout>
    </com.example.recycleview.view.SlidingMenu>

</RelativeLayout>

3、自定義View:SlidingMenu.java,繼承水平滾動控件類
1、首先實現其兩個參數的構造方法
2、將自定義的HorizontalScrollView名字改成自定義的屬性名 包名+類名
…………………………
>
3、自定義ViewGroup:
(1)、onMeasure:決定內部View(子View)的寬和高以及自己的寬和高
(2)、onLayout:決定子View放置的位置
(3)、onTouchEvent:判斷用戶的手指狀態


public class SlidingMenu extends HorizontalScrollView {
    private LinearLayout mWapper;
    private ViewGroup mMenu;
    private ViewGroup mContent;
    private int mScreenWidth;
    private int mMenuRightPadding = 50;// menu與屏幕右側的距離dp
    private int mMenuWidth;
    private boolean once;// onMeasure會調用多次,設置一個boolean值
    private boolean isOpen; //默認打開時爲false
    float scale;
    /*
     * 沒有使用自定義屬性時,調用這個參數
     */
    public SlidingMenu(Context context, AttributeSet attrs) {
        this(context, attrs,0);

    }

    /*
     * 自定義ViewGroup 1、onMeasure 決定內部view的寬和高 2、onLayout 決定子view的放置的位置
     * 3、onTouchEvent 判斷用戶的手指狀態
     */

    /*
     * 當使用了自定義屬性時,會調用此構造方法
     */

    public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // 獲取我們定義的屬性
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
                R.styleable.SlidingMenu, defStyle, 0);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);
            switch (attr) {
            case R.styleable.SlidingMenu_rightPadding:
                mMenuRightPadding = a.getDimensionPixelSize(attr,
                        (int) TypedValue.applyDimension(
                                TypedValue.COMPLEX_UNIT_DIP, 50, context
                                        .getResources().getDisplayMetrics()));// attr是新賦值,第二個是默認值
                break;

            }
        }

        a.recycle();// 釋放掉
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);// 寬高被賦值了
        mScreenWidth = outMetrics.widthPixels;

    }

    public SlidingMenu(Context context) {
        this(context, null);
        // TODO Auto-generated constructor stub
    }

    // 設置子view的寬和高,設置自己的寬和高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (!once) {
            mWapper = (LinearLayout) getChildAt(0);
            mMenu = (ViewGroup) mWapper.getChildAt(0);// LinearLayout第一個元素
            mContent = (ViewGroup) mWapper.getChildAt(1);// LinearLayout第二個元素
            mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth
                    - mMenuRightPadding;
            mContent.getLayoutParams().width = mScreenWidth;
            once = true;
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    // 通過設置偏移量,將menu隱藏
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (changed) {
            this.scrollTo(mMenuWidth, 0);// scrollTo是隱藏的方法,瞬間完成的動作

        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {// 默認自動能把隱藏的滑出來,所以關心Action_UP
        int action = ev.getAction();
        switch (action) {
        case MotionEvent.ACTION_UP:
            int scrollX = getScrollX();// scrollX隱藏在左邊的寬度
            if (scrollX >= mMenuWidth / 2) {
                this.smoothScrollTo(mMenuWidth, 0);// smoothScrollTo是動畫隱藏的方法
                isOpen=false;
            } else {
                this.smoothScrollTo(0, 0);//打開menu
                isOpen=true;
            }
            return true;

        }

        return super.onTouchEvent(ev);
    }
//  打開菜單
    public void openMenu(){
        if (isOpen) return;
        this.smoothScrollTo(0, 0);
        isOpen=true;

    }
    public void closeMenu(){
        if (!isOpen) return;
        this.smoothScrollTo(mMenuWidth, 0);
        isOpen=false;
    }
    //切換菜單
    public void toggle(){
        if(isOpen){
            closeMenu();
        }else {
            openMenu();
        }

    }

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
 scale=l*1.0f/mMenuWidth;//1~0
//調用屬性動畫,設置TranslationX     mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth- mMenuRightPadding;
 float rightScale=0.7f+0.3f*scale;
 float leftScale=1.0f-scale*0.3f;
 float leftAlpha=0.6f+0.4f*(1-scale);
 ViewHelper.setTranslationX(mMenu, mMenuWidth*scale*0.8f);
 ViewHelper.setScaleX(mMenu, leftScale);
 ViewHelper.setScaleY(mMenu,leftScale );
 ViewHelper.setAlpha(mMenu, leftAlpha);
// mContent的縮放及焦點
 ViewHelper.setScaleX(mContent,rightScale);
 ViewHelper.setScaleY(mContent,rightScale);
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight()/2);

}


}

4、、用戶自定義屬性
至此,側滑已經實現。接下來加入自定義屬性,可以讓用戶去設置菜單離屏幕右邊的邊距。
(1)、在values文件夾中創建一個xml文件,叫做attr.xml
(2)注意:在xml文件中編寫自定義屬性時是沒有代碼提示功能的,因此要注意代碼拼寫
(3)接下來要在mainActivity.xml文件中命名空間進行聲明:
xmlns:dan=”http://schemas.android.com/apk/res/com.example.recycleview”
注意:這裏的格式是xmlns:自己編寫,可以是任何名字=”http://schemas.android.com/apk/res/當前應用的包名,而不是View的包名”
(4)、接下來將自定義屬性放到View中進行使用
Alan:rightPadding=”100dp”
(5)、在剛纔未使用自定義屬性時,調用自身的構造方法,定義之後,需要生成另外兩個構造方法:將原來兩個參數構造方法中的方法拷貝到三個參數的構造方法之中,然後將兩個參數構造方法的第三個參數設置爲0,將一個參數的構造方法(傳入上下文對象方法)的第二個參數設置爲null,即調用兩個參數的構造方法。
(6)、獲取我們定義的屬性:在三個參數的構造方法中獲取:通過TypedArray這個類獲得自定義屬性,這裏需要注意的是TypedArray這個類用完之後需要進行釋放(recycled)。

5、attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="rightPadding" format="dimension"></attr>

    <declare-styleable name="SlidingMenu">
        <attr name="rightPadding"></attr>
    </declare-styleable>

</resources>

6、下面是MainActivity的實現


public class MainActivity extends Activity  {
    private SlidingMenu mLeftMenu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        mLeftMenu=(SlidingMenu) findViewById(R.id.id_menu);


    }
    public void toggleMenu(View v){

        mLeftMenu.toggle();

    }
}
發佈了81 篇原創文章 · 獲贊 21 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章