Android抽屜效果的實現(不擠壓,不覆蓋)

抽屜效果,顧名思義就是可以像抽屜一樣拉出來推進去,在Android中一般是通過滑動(從左到右,或者像簾子一樣從上往下拉,或者通過某個按鈕)來實現抽屜效果。其實Android的抽屜效果很簡單(V4.0以上),使用了一個叫做DrawerLayout的類就可以輕鬆實現。廢話少說,開始幹活。

Android官網的教程(需要翻牆):http://developer.android.com/training/implementing-navigation/nav-drawer.html

首先說說我今天準備實現的目標:

1、抽屜效果,就是可以推拉的,這個是基本(我的是從左向右滑動)。

2、擠壓效果。所謂擠壓,就是當把抽屜拉出來是,原來的屏幕不會被遮擋或者覆蓋,而是順勢向同樣的方向移動相同的距離。之所以會做這一個效果,是因爲官網的DrawerLayout是默認會擠壓的。

效果如下圖(由於不知道怎麼手機動態截屏,只能上靜態圖了,有知道的可以告訴我,當然騰訊手機管家的試過了,不流暢)


下面是具體的實現步驟

1、佈局文件mlayout.xml

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <!-- The main content view -->
	<RelativeLayout
	    android:id="@+id/content_frame"
	    android:layout_width="match_parent"
	    android:layout_height="match_parent" >
		<Button
		    android:id="@+id/mButton"
			android:text="這裏是主界面"
			android:gravity="left|center_vertical"
			android:layout_marginTop="20dp"
	        android:layout_width="match_parent"
	        android:layout_height="wrap_content"
	        android:layout_centerHorizontal="true"
			android:background="#aa0000"/>

    </RelativeLayout>
    
    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="180dp"
        android:background="#000000"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/white"
        android:dividerHeight="2dp"/>
    
</android.support.v4.widget.DrawerLayout>

需要注意的是:

(1)這裏的根標籤是android.support.v4.widget.DrawerLayout而不是普通的RelativeLayout之類的,裏面有2個部分,第一個部分是The main content view,主界面,也就是抽屜還沒打開之前的界面,這裏官網用的是FrameLayout,其實也就是一個主界面的佈局,所以都無所謂,我喜歡用RelativeLayout所以用它,主界面佈局內根據自己的需要隨意添加空間;

(2)第二個部分就是抽屜的界面,佈局也是隨意的。我用的是ListView,因爲一般拉出來的抽屜,都是系統的一些設置和檢查更新什麼的。

(3)主界面佈局寬和高,必須match_parent,抽屜的高也是,抽屜的寬度不得超過320dp(官方規定的),否則會全部遮擋(或擠壓)掉主佈局。

(4)抽屜有個屬性是layout_gravity,這個是指抽屜出來的方向,必須設置。一般可以設置left、end、right、start(不過貌似我出來start,其他的感覺都會使應用崩潰)


2、主類MainActivity.java,其中滑動和點擊按鈕都可以打開抽屜

package com.exam.drawerdemo;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.DrawerLayout.DrawerListener;
import android.view.Gravity;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.RelativeLayout;

public class MainActivity extends Activity {

	DrawerLayout mDrawerLayout;
	Button mButton;
	ListView mDrawerList;
	String[] str={"AA","BB","CC","DD","EE","FF"};
	RelativeLayout mRelativeLayout;
	int mDrawerWidth;//抽屜全部拉出來時的寬度
	float scrollWidth;//抽屜被拉出部分的寬度
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.mlayout);

		
		mDrawerLayout=(DrawerLayout)findViewById(R.id.drawer_layout);
		mRelativeLayout=(RelativeLayout) findViewById(R.id.content_frame);
		
		//填充抽屜ListView的內容
		mDrawerList=(ListView)findViewById(R.id.left_drawer);
		mDrawerList.setAdapter(new ArrayAdapter<String>(getApplicationContext(),
				android.R.layout.simple_expandable_list_item_1,str));
		//測量抽屜的寬度和高度
		measureView(mDrawerList);
		mDrawerWidth=mDrawerList.getMeasuredWidth();
		
		mButton=(Button)findViewById(R.id.mButton);
		mButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				mDrawerLayout.openDrawer(Gravity.LEFT);
			}
		});
		
		//必須給抽屜設置監聽事件
		mDrawerLayout.setDrawerListener(new DrawerListener() {
			
			@Override
			public void onDrawerStateChanged(int arg0) {
				
			}
			
			//抽屜被拉出來或者推回去
			@Override
			public void onDrawerSlide(View arg0, float arg1) {
				//因爲arg1的範圍是0.0-1.0,是一個相對整個抽屜寬度的比例
				//所以要準換成
				scrollWidth=arg1*mDrawerWidth;
				//setScroll中的參數,正數表示向左移動,負數向右
				mRelativeLayout.setScrollX((int)(-1*scrollWidth));
				
			}
			
			@Override
			public void onDrawerOpened(View arg0) {
				
			}
			
			@Override
			public void onDrawerClosed(View arg0) {
				
			}
		});

	}
	
	/**
	 * 此方法可以多次被不同的View對象調用。
	 * 在調用該方法後,
	 * 使用View對象的getMessuredHeight()獲高度(單位px)
	 * @param child 需要測量高度和寬度的View對象,
	 */
	private void measureView(View child) {    
        ViewGroup.LayoutParams params = child.getLayoutParams();    
        if (params == null) {    
            params = new ViewGroup.LayoutParams(    
                    ViewGroup.LayoutParams.MATCH_PARENT,    
                    ViewGroup.LayoutParams.WRAP_CONTENT);    
        }    
        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0,    
                params.width);    
        int lpHeight = params.height;    
        int childHeightSpec;    
        if (lpHeight > 0) {    
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,    
                    MeasureSpec.EXACTLY);    
        } else {    
            childHeightSpec = MeasureSpec.makeMeasureSpec(0,    
                    MeasureSpec.UNSPECIFIED);    
        }    
        child.measure(childWidthSpec, childHeightSpec);    
    }    
	

}
再囉嗦幾句:(1)擠壓效果的實現,其實就是通過監測抽屜向右滑動的距離,然後主界面也通過滑動相應距離實現的(setScroll,負數表示向右);(2)DrawerLayout有個方法openDrawer(Gravity arg)也可以打開抽屜,其關閉則是closeDrawer();但是用了按鈕打開抽屜(比如我上面的),不影響滑動也可以打開。

有問題和建議的,或者如上面說的有比較好的動態截屏方法的,歡迎再下面留言


源碼地址http://download.csdn.net/detail/programming2012/8554275

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章