去年的優酷HD版有過這樣一種菜單,如下圖:
應用打開之後,先是三個弧形的三級菜單,點選實體鍵menu之後,這三個菜單依次旋轉退出,再點選實體鍵menu之後,一級菜單會旋轉進入,點選一級菜單,二級菜單旋轉進入,點選二級菜單的menu鍵,三級菜單旋轉進入,再次點選二級菜單的旋轉鍵,三級菜單又會旋轉退出,這時再點選一級菜單,二級菜單退出,最後點選實體menu鍵,一級菜單退出。
總體來說實作這樣的功能:
(1)點選實體menu鍵時,如果界面上有菜單顯示,不管有幾個,全部依次退出,如果界面上沒有菜單顯示,則顯示一級菜單。
(2)點選一級菜單的home鍵時,如果此時界面隻有一級菜單,則顯示二級菜單,否則讓除了一級菜單外的菜單全都依次退出。
(3)點選二級菜單的menu鍵時,如果三級菜單已經顯示,則讓它旋轉退出,如果三級菜單未顯示則讓它旋轉進入。
好了,今天我們主要實作上述效果。
先來看布局檔案
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.customwidget.MainActivity" >
<RelativeLayout
android:id="@+id/menu_level1"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level1" >
<ImageButton
android:id="@+id/level1_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginBottom="10dp"
android:background="@drawable/icon_home"
android:onClick="myClick" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/menu_level2"
android:layout_width="dp"
android:layout_height="dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level2" >
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="dp"
android:layout_marginLeft="dp"
android:background="@drawable/icon_search" />
<ImageButton
android:id="@+id/level2_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="dp"
android:background="@drawable/icon_menu"
android:onClick="myClick" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="dp"
android:layout_marginRight="dp"
android:background="@drawable/icon_myyouku" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/menu_level3"
android:layout_width="dp"
android:layout_height="dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level3" >
<ImageButton
android:id="@+id/level3_channel1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="dp"
android:layout_marginLeft="dp"
android:background="@drawable/channel1" />
<ImageButton
android:id="@+id/level3_channel2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/level3_channel1"
android:layout_marginBottom="dp"
android:layout_marginLeft="-dp"
android:layout_toRightOf="@id/level3_channel1"
android:background="@drawable/channel2" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/level3_channel2"
android:layout_marginBottom="dp"
android:layout_marginLeft="dp"
android:layout_toRightOf="@id/level3_channel2"
android:background="@drawable/channel3" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="dp"
android:background="@drawable/channel4" />
<ImageButton
android:id="@+id/level3_channel7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="dp"
android:layout_marginRight="dp"
android:background="@drawable/channel7" />
<ImageButton
android:id="@+id/level3_channel6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/level3_channel7"
android:layout_marginBottom="dp"
android:layout_marginRight="-dp"
android:layout_toLeftOf="@id/level3_channel7"
android:background="@drawable/channel6" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/level3_channel6"
android:layout_marginBottom="dp"
android:layout_marginRight="dp"
android:layout_toLeftOf="@id/level3_channel6"
android:background="@drawable/channel5" />
</RelativeLayout>
</RelativeLayout>
這裡是一個相對布局中嵌套了三個相對布局,嵌套的第一個相對布局負責顯示一級菜單,嵌套的第二個相對布局負責顯示二級菜單,嵌套的第三個相對布局負責顯示三級菜單。三個不同層次的菜單的背景都是弧形。我們通過指定具體的寬高來使三個層次的菜單具有不同的大小。
效果如下:
再看看MainActivity.java
/**
* 模仿優酷菜單
* 2015年5月19日
*/
public class MainActivity extends Activity {
//分别拿到不同等級的菜單
private RelativeLayout lv1;
private RelativeLayout lv2;
private RelativeLayout lv3;
private Animation animation;
//各級菜單是否顯示,預設全都顯示
private boolean isDisplaylv1 = true;
private boolean isDisplaylv2 = true;
private boolean isDisplaylv3 = true;
//動畫是否正在執行,預設動畫沒有執行
private boolean isAnimationRunning = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv1 = (RelativeLayout) this.findViewById(R.id.menu_level1);
lv2 = (RelativeLayout) this.findViewById(R.id.menu_level2);
lv3 = (RelativeLayout) this.findViewById(R.id.menu_level3);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//如果動畫正在執行,則不處理此事件
if (isAnimationRunning)
return super.onKeyDown(keyCode, event);
//如果點選的是菜單鍵
if (keyCode == KeyEvent.KEYCODE_MENU) {
//如果一級菜單已經顯示,判斷二級菜單是否顯示
if (isDisplaylv1) {
//設定動畫啟動延遲時間
int startOffset = ;
//如果二級菜單已經顯示,判斷三級菜單是否顯示,然後退出二級菜單
if (isDisplaylv2) {
if (isDisplaylv3) {
//如果三級菜單已經顯示,執行退出動畫
exitAnimation(lv3, startOffset);
//三級菜單退出動畫執行完畢之後,動畫的啟動時間延遲500ms
startOffset += ;
isDisplaylv3 = !isDisplaylv3;
}
//二級菜單退出,此時startOffset=500,即動畫啟動時間延遲500ms
exitAnimation(lv2, startOffset);
//二級菜單退出動畫執行完畢之後,動畫的啟動時間延遲500ms
startOffset += ;
isDisplaylv2 = !isDisplaylv2;
}
//一級菜單退出,此時startOffset=1000,即動畫啟動時間延遲1000ms
exitAnimation(lv1, startOffset);
//如果一級菜單未顯示,則一級菜單進入
} else {
enterAnimation(lv1);
}
isDisplaylv1 = !isDisplaylv1;
return true;
}
return super.onKeyDown(keyCode, event);
}
public void myClick(View v) {
//如果動畫正在執行,則不處理此事件
if (isAnimationRunning)
return;
switch (v.getId()) {
/**
* 當點選二級菜單的menu時,如果三級菜單已經顯示,則執行退出動畫,
* 否則執行進入動畫
*/
case R.id.level2_menu:
if (isDisplaylv3) {
exitAnimation(lv3, );
} else {
enterAnimation(lv3);
}
isDisplaylv3 = !isDisplaylv3;
break;
case R.id.level1_home:
// 如果二級菜單已經顯示,再判斷三級菜單是否顯示
if (isDisplaylv2) {
//通過設定動畫啟動延遲時間,來實作動畫依次退出效果
int startOffset = ;
// 如果三級菜單也顯示了,則讓他們依次退出
if (isDisplaylv3) {
exitAnimation(lv3, startOffset);
startOffset = ;
isDisplaylv3 = !isDisplaylv3;
}
exitAnimation(lv2, startOffset);
isDisplaylv2 = !isDisplaylv2;
// 如果二級菜單沒有顯示,就讓二級菜單顯示出來
} else {
enterAnimation(lv2);
isDisplaylv2 = !isDisplaylv2;
}
break;
}
}
/**
* 退出動畫
* @param layout 執行動畫的布局檔案
* @param startOffset 動畫啟動的延遲時間
*/
public void exitAnimation(RelativeLayout layout, long startOffset) {
animation = AnimationUtils.loadAnimation(this, R.anim.exit_menu);
animation.setFillAfter(true);
animation.setStartOffset(startOffset);
animation.setAnimationListener(new MyAnimationListener());
layout.startAnimation(animation);
}
/**
* 進入動畫
* @param layout 執行動畫的布局檔案
*/
public void enterAnimation(RelativeLayout layout) {
animation = AnimationUtils.loadAnimation(this, R.anim.enter_menu);
animation.setFillAfter(true);
animation.setAnimationListener(new MyAnimationListener());
layout.startAnimation(animation);
}
/**
* 判斷動畫是否正在執行
* @author 王松
*
*/
private class MyAnimationListener implements AnimationListener {
//動畫開始執行
@Override
public void onAnimationStart(Animation animation) {
isAnimationRunning = true;
}
//動畫執行結束
@Override
public void onAnimationEnd(Animation animation) {
isAnimationRunning = false;
}
@Override
public void onAnimationRepeat(Animation animation) {
}
}
}
代碼中注釋已經寫的很詳細了,這裡不再贅述。最後在給大家看看兩個動畫檔案:
enter_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="true">
<rotate
android:duration="1000"
android:fromDegrees="-180"
android:toDegrees="0"
android:pivotX="50%"
android:pivotY="100%" />
</set>
exit_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="true">
<rotate
android:duration="1000"
android:fromDegrees="0"
android:toDegrees="-180"
android:pivotX="50%"
android:pivotY="100%" />
</set>
關于動畫如果不太懂可以看這裡android之tween動畫詳解,android之frame動畫詳解。。
本項目完整代碼下載下傳