Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 自定義控件打造史上最簡單的側滑菜單

Android 自定義控件打造史上最簡單的側滑菜單

編輯:關於Android編程

 

側滑菜單在很多應用中都會見到,最近QQ5.0側滑還玩了點花樣~~對於側滑菜單,一般大家都會自定義ViewGroup,然後隱藏菜單欄,當手指滑動時,通過Scroller或者不斷的改變leftMargin等實現;多少都有點復雜,完成以後還需要對滑動沖突等進行處理~~今天給大家帶來一個簡單的實現,史上最簡單有點誇張,但是的確是我目前遇到過的最簡單的一種實現~~~

1、原理分析

既然是側滑,無非就是在巴掌大的屏幕,塞入大概兩巴掌大的布局,需要滑動可以出現另一個,既然這樣,大家為啥不考慮使用Android提供的HorizontalScrollView呢~

如果使用HorizontalScrollView,還需要在ACTION_DOWN , ACTION_MOVE裡面去監聽,判斷,不斷改變控件位置了麼? NO!!!HorizontalScrollView本身就帶了滑動的功能~~

還需要自己的手動處理各種沖突麼?NO!!!當然了,還是需要了解下事件分發機制的~~~

2、效果圖

/

嗯,主界面搞了QQ一張圖片,左邊盜用了一兄弟的布局文件~~罪過~~ 誰有好看的布局、圖片、圖標神馬的,可以給我發點,感激~

3、布局文件

 



    

        

        
        
    


首先是我們的自定義View,裡面一個方向水平的LinearLayout,然後就是一個是菜單的布局,一個是主布局了~

 

4、自定義SlidingMenu

接下來就是我們最核心的代碼了~

 

package com.example.zhy_slidingmenu;

import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

import com.zhy.utils.ScreenUtils;

public class SlidingMenu extends HorizontalScrollView
{
	/**
	 * 屏幕寬度
	 */
	private int mScreenWidth;
	/**
	 * dp
	 */
	private int mMenuRightPadding = 50;
	/**
	 * 菜單的寬度
	 */
	private int mMenuWidth;
	private int mHalfMenuWidth;

	private boolean once;

	public SlidingMenu(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		mScreenWidth = ScreenUtils.getScreenWidth(context);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		/**
		 * 顯示的設置一個寬度
		 */
		if (!once)
		{
			LinearLayout wrapper = (LinearLayout) getChildAt(0);
			ViewGroup menu = (ViewGroup) wrapper.getChildAt(0);
			ViewGroup content = (ViewGroup) wrapper.getChildAt(1);
			// dp to px
			mMenuRightPadding = (int) TypedValue.applyDimension(
					TypedValue.COMPLEX_UNIT_DIP, mMenuRightPadding, content
							.getResources().getDisplayMetrics());

			mMenuWidth = mScreenWidth - mMenuRightPadding;
			mHalfMenuWidth = mMenuWidth / 2;
			menu.getLayoutParams().width = mMenuWidth;
			content.getLayoutParams().width = mScreenWidth;

		}
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

	}

	@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);
			once = true;
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev)
	{
		int action = ev.getAction();
		switch (action)
		{
		// Up時,進行判斷,如果顯示區域大於菜單寬度一半則完全顯示,否則隱藏
		case MotionEvent.ACTION_UP:
			int scrollX = getScrollX();
			if (scrollX > mHalfMenuWidth)
				this.smoothScrollTo(mMenuWidth, 0);
			else
				this.smoothScrollTo(0, 0);
			return true;
		}
		return super.onTouchEvent(ev);
	}

}

哈哈,完工~上面的演示圖,就用到這麼點代碼~~

 

代碼怎麼樣,短不短~除了設置寬度這些雜七雜八的代碼~正在處理滑動的代碼不過10行~~我說史上最簡單不為過吧~

嗯,由於代碼過於短,就不解釋了,大家自己看下注釋~

5、擴展

嗯,就下來,我們完善下程序,我准備首先把菜單布局裡面改成ListView來證明我們是沒有沖突的;然後添加一個屬性讓用戶配置菜單距離右邊的邊距的值;再對外公布一個方法,點擊自動打開菜單,供用戶點擊某個按鈕,菜單慢慢滑出來~

1、添加自定義屬性

a、首先在values文件夾下新建一個attr.xml,寫入以下內容:

 




    

    
        
    

b、在布局中聲明命名空間和使用屬性

 

定義完了,肯定要使用麼。

 


可以看到我們的命名空間:xmlns:zhy=http://schemas.android.com/apk/res/com.example.zhy_slidingmenu 是http://schemas.android.com/apk/res/加上我們的包名;

 

我們的屬性:zhy:rightPadding=100dp這裡我設置了100dp;

注:很多人問我,沒有提示咋辦,這樣,你clean下項目,如果你運氣好,就有提示了,嗯,運氣好~

c、在我們自定義類中獲得屬性

 

public SlidingMenu(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
		mScreenWidth = ScreenUtils.getScreenWidth(context);

		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:
				// 默認50
				mMenuRightPadding = a.getDimensionPixelSize(attr,
						(int) TypedValue.applyDimension(
								TypedValue.COMPLEX_UNIT_DIP, 50f,
								getResources().getDisplayMetrics()));// 默認為10DP
				break;
			}
		}
		a.recycle();
	}

在三個參數的構造方法中,通過TypeArray獲取就行了~

 

好了,這樣就行了~如果你又很多自定義屬性,按照上面的步驟來就行了~~

2、對外公布一個打開菜單的方法

首先定義一個boolean isOpen變量,用來標識我們當前菜單的狀態~~然後記得在ACTION_UP的時候改變下狀態:

 

case MotionEvent.ACTION_UP:
			int scrollX = getScrollX();
			if (scrollX > mHalfMenuWidth)
			{
				this.smoothScrollTo(mMenuWidth, 0);
				isOpen = false;
			} else
			{
				this.smoothScrollTo(0, 0);
				isOpen = true;
			}
			return true;
		}

 

下面開始添加方法:

 

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

	/**
	 * 關閉菜單
	 */
	public void closeMenu()
	{
		if (isOpen)
		{
			this.smoothScrollTo(mMenuWidth, 0);
			isOpen = false;
		}
	}

	/**
	 * 切換菜單狀態
	 */
	public void toggle()
	{
		if (isOpen)
		{
			closeMenu();
		} else
		{
			openMenu();
		}
	}

順手多添加了兩個。。。

 

下面,我們挑一個進行測試:

主布局多添加一個按鈕,用於觸發toggleMenu()方法

主Activity

 

public class MainActivity extends Activity
{
	private SlidingMenu mMenu ; 

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		mMenu = (SlidingMenu) findViewById(R.id.id_menu);
	}
	
	public void toggleMenu(View view)
	{
		mMenu.toggle();
	}
}

好了,看下現在的效果圖:

 

/

我們把padding改成了100dp~

然後點擊我們的按鈕,看哈效果~~

3、添加ListView測試

/

好了~~ListView也測試完了~~大家可以根據自己的需求各種修改~~

對了,今天測試用QQ的目的是為了,下次我要拿上面的代碼,改造和QQ5.0一模一樣的效果,大家有興趣可以提前試一試,QQ的菜單好像是隱藏在主界面下面一樣,給人感覺不是劃出來的,我們這個例子也能做出那樣的效果,拭目以待吧;剩下就是各種縮放,透明度的動畫了~~~

 

源碼點擊下載

 

如果覺得不錯,評價下~哈~

 

 

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved