抽屜效果,顧名思義就是可以像抽屜一樣拉出來推進去,在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