Android自定義控件之仿優(yōu)酷菜單
去年的優(yōu)酷HD版有過這樣一種菜單,如下圖:
應(yīng)用打開之后,先是三個(gè)弧形的三級(jí)菜單,點(diǎn)擊實(shí)體鍵menu之后,這三個(gè)菜單依次旋轉(zhuǎn)退出,再點(diǎn)擊實(shí)體鍵menu之后,一級(jí)菜單會(huì)旋轉(zhuǎn)進(jìn)入,點(diǎn)擊一級(jí)菜單,二級(jí)菜單旋轉(zhuǎn)進(jìn)入,點(diǎn)擊二級(jí)菜單的menu鍵,三級(jí)菜單旋轉(zhuǎn)進(jìn)入,再次點(diǎn)擊二級(jí)菜單的旋轉(zhuǎn)鍵,三級(jí)菜單又會(huì)旋轉(zhuǎn)退出,這時(shí)再點(diǎn)擊一級(jí)菜單,二級(jí)菜單退出,最后點(diǎn)擊實(shí)體menu鍵,一級(jí)菜單退出。
總體來說實(shí)現(xiàn)這樣的功能:
(1)點(diǎn)擊實(shí)體menu鍵時(shí),如果界面上有菜單顯示,不管有幾個(gè),全部依次退出,如果界面上沒有菜單顯示,則顯示一級(jí)菜單。
(2)點(diǎn)擊一級(jí)菜單的home鍵時(shí),如果此時(shí)界面只有一級(jí)菜單,則顯示二級(jí)菜單,否則讓除了一級(jí)菜單外的菜單全都依次退出。
(3)點(diǎn)擊二級(jí)菜單的menu鍵時(shí),如果三級(jí)菜單已經(jīng)顯示,則讓它旋轉(zhuǎn)退出,如果三級(jí)菜單未顯示則讓它旋轉(zhuǎn)進(jìn)入。
好了,今天我們主要實(shí)現(xiàn)上述效果。
先來看布局文件
<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="200dp" android:layout_height="100dp" 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="10dp" android:layout_marginLeft="15dp" 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="7dp" 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="10dp" android:layout_marginRight="15dp" android:background="@drawable/icon_myyouku" /> </RelativeLayout> <RelativeLayout android:id="@+id/menu_level3" android:layout_width="320dp" android:layout_height="162dp" 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="10dp" android:layout_marginLeft="12dp" 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="17dp" android:layout_marginLeft="-5dp" 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="15dp" android:layout_marginLeft="13dp" 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="10dp" 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="10dp" android:layout_marginRight="12dp" 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="17dp" android:layout_marginRight="-5dp" 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="15dp" android:layout_marginRight="13dp" android:layout_toLeftOf="@id/level3_channel6" android:background="@drawable/channel5" /> </RelativeLayout> </RelativeLayout>
這里是一個(gè)相對(duì)布局中嵌套了三個(gè)相對(duì)布局,嵌套的第一個(gè)相對(duì)布局負(fù)責(zé)顯示一級(jí)菜單,嵌套的第二個(gè)相對(duì)布局負(fù)責(zé)顯示二級(jí)菜單,嵌套的第三個(gè)相對(duì)布局負(fù)責(zé)顯示三級(jí)菜單。三個(gè)不同層次的菜單的背景都是弧形。我們通過指定具體的寬高來使三個(gè)層次的菜單具有不同的大小。
效果如下:
再看看MainActivity.java
/** * 模仿優(yōu)酷菜單 * 2015年5月19日 */ public class MainActivity extends Activity { //分別拿到不同等級(jí)的菜單 private RelativeLayout lv1; private RelativeLayout lv2; private RelativeLayout lv3; private Animation animation; //各級(jí)菜單是否顯示,默認(rèn)全都顯示 private boolean isDisplaylv1 = true; private boolean isDisplaylv2 = true; private boolean isDisplaylv3 = true; //動(dòng)畫是否正在執(zhí)行,默認(rèn)動(dòng)畫沒有執(zhí)行 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) { //如果動(dòng)畫正在執(zhí)行,則不處理此事件 if (isAnimationRunning) return super.onKeyDown(keyCode, event); //如果點(diǎn)擊的是菜單鍵 if (keyCode == KeyEvent.KEYCODE_MENU) { //如果一級(jí)菜單已經(jīng)顯示,判斷二級(jí)菜單是否顯示 if (isDisplaylv1) { //設(shè)置動(dòng)畫啟動(dòng)延遲時(shí)間 int startOffset = 0; //如果二級(jí)菜單已經(jīng)顯示,判斷三級(jí)菜單是否顯示,然后退出二級(jí)菜單 if (isDisplaylv2) { if (isDisplaylv3) { //如果三級(jí)菜單已經(jīng)顯示,執(zhí)行退出動(dòng)畫 exitAnimation(lv3, startOffset); //三級(jí)菜單退出動(dòng)畫執(zhí)行完畢之后,動(dòng)畫的啟動(dòng)時(shí)間延遲500ms startOffset += 500; isDisplaylv3 = !isDisplaylv3; } //二級(jí)菜單退出,此時(shí)startOffset=500,即動(dòng)畫啟動(dòng)時(shí)間延遲500ms exitAnimation(lv2, startOffset); //二級(jí)菜單退出動(dòng)畫執(zhí)行完畢之后,動(dòng)畫的啟動(dòng)時(shí)間延遲500ms startOffset += 500; isDisplaylv2 = !isDisplaylv2; } //一級(jí)菜單退出,此時(shí)startOffset=1000,即動(dòng)畫啟動(dòng)時(shí)間延遲1000ms exitAnimation(lv1, startOffset); //如果一級(jí)菜單未顯示,則一級(jí)菜單進(jìn)入 } else { enterAnimation(lv1); } isDisplaylv1 = !isDisplaylv1; return true; } return super.onKeyDown(keyCode, event); } public void myClick(View v) { //如果動(dòng)畫正在執(zhí)行,則不處理此事件 if (isAnimationRunning) return; switch (v.getId()) { /** * 當(dāng)點(diǎn)擊二級(jí)菜單的menu時(shí),如果三級(jí)菜單已經(jīng)顯示,則執(zhí)行退出動(dòng)畫, * 否則執(zhí)行進(jìn)入動(dòng)畫 */ case R.id.level2_menu: if (isDisplaylv3) { exitAnimation(lv3, 0); } else { enterAnimation(lv3); } isDisplaylv3 = !isDisplaylv3; break; case R.id.level1_home: // 如果二級(jí)菜單已經(jīng)顯示,再判斷三級(jí)菜單是否顯示 if (isDisplaylv2) { //通過設(shè)置動(dòng)畫啟動(dòng)延遲時(shí)間,來實(shí)現(xiàn)動(dòng)畫依次退出效果 int startOffset = 0; // 如果三級(jí)菜單也顯示了,則讓他們依次退出 if (isDisplaylv3) { exitAnimation(lv3, startOffset); startOffset = 700; isDisplaylv3 = !isDisplaylv3; } exitAnimation(lv2, startOffset); isDisplaylv2 = !isDisplaylv2; // 如果二級(jí)菜單沒有顯示,就讓二級(jí)菜單顯示出來 } else { enterAnimation(lv2); isDisplaylv2 = !isDisplaylv2; } break; } } /** * 退出動(dòng)畫 * @param layout 執(zhí)行動(dòng)畫的布局文件 * @param startOffset 動(dòng)畫啟動(dòng)的延遲時(shí)間 */ 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); } /** * 進(jìn)入動(dòng)畫 * @param layout 執(zhí)行動(dòng)畫的布局文件 */ public void enterAnimation(RelativeLayout layout) { animation = AnimationUtils.loadAnimation(this, R.anim.enter_menu); animation.setFillAfter(true); animation.setAnimationListener(new MyAnimationListener()); layout.startAnimation(animation); } /** * 判斷動(dòng)畫是否正在執(zhí)行 * @author 王松 * */ private class MyAnimationListener implements AnimationListener { //動(dòng)畫開始執(zhí)行 @Override public void onAnimationStart(Animation animation) { isAnimationRunning = true; } //動(dòng)畫執(zhí)行結(jié)束 @Override public void onAnimationEnd(Animation animation) { isAnimationRunning = false; } @Override public void onAnimationRepeat(Animation animation) { } } }
代碼中注釋已經(jīng)寫的很詳細(xì)了,這里不再贅述。最后在給大家看看兩個(gè)動(dòng)畫文件:
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>
關(guān)于動(dòng)畫如果不太懂可以看這里:Android基礎(chǔ)知識(shí)之tween動(dòng)畫效果 Android基礎(chǔ)知識(shí)之frame動(dòng)畫效果
源碼下載:http://xiazai.jb51.net/201606/yuanma/Androidyouku(jb51.net).rar
原文鏈接:http://blog.csdn.net/u012702547/article/details/45842963
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android編程實(shí)現(xiàn)仿優(yōu)酷圓盤旋轉(zhuǎn)菜單效果的方法詳解【附demo源碼下載】
- Android仿優(yōu)酷圓形菜單學(xué)習(xí)筆記分享
- Android編程實(shí)現(xiàn)仿優(yōu)酷旋轉(zhuǎn)菜單效果(附demo源碼)
- Android 帶有彈出收縮動(dòng)畫的扇形菜單實(shí)例
- Android菜單(動(dòng)畫菜單、360波紋菜單)
- Android實(shí)現(xiàn)360手機(jī)助手底部的動(dòng)畫菜單
- Android程序開發(fā)之使用Design包實(shí)現(xiàn)QQ動(dòng)畫側(cè)滑效果和滑動(dòng)菜單導(dǎo)航
- Android利用屬性動(dòng)畫實(shí)現(xiàn)優(yōu)酷菜單
相關(guān)文章
Android 兩個(gè)Fragment之間傳遞數(shù)據(jù)實(shí)例詳解
這篇文章主要介紹了Android 兩個(gè)Fragment之間傳遞數(shù)據(jù)實(shí)例詳解的相關(guān)資料,這里附有實(shí)例代碼,實(shí)現(xiàn)該功能,需要的朋友可以參考下2016-12-12Android Doze模式下Alarm定時(shí)任務(wù)實(shí)現(xiàn)流程詳解
這篇文章主要介紹了Android Doze模式下Alarm定時(shí)任務(wù)實(shí)現(xiàn),Android的定時(shí)任務(wù)有兩種,一種是JavaAPI提供的Timer類,另一種就是使用Android的Alarm機(jī)制2022-11-11Android動(dòng)畫之3D翻轉(zhuǎn)效果實(shí)現(xiàn)函數(shù)分析
Android中的翻轉(zhuǎn)動(dòng)畫效果的實(shí)現(xiàn),Android中并沒有提供直接做3D翻轉(zhuǎn)的動(dòng)畫,所以關(guān)于3D翻轉(zhuǎn)的動(dòng)畫效果需要我們自己實(shí)現(xiàn),那么我們首先來分析一下Animation 和 Transformation,感興趣的朋友可以了解下啊2013-01-0130分鐘搞清楚Android Touch事件分發(fā)機(jī)制
30分鐘搞清楚Android Touch事件分發(fā)機(jī)制,Touch事件分發(fā)中只有兩個(gè)主角:ViewGroup和View,想要深入學(xué)習(xí)的朋友可以參考本文2016-03-03flutter實(shí)現(xiàn)磨砂玻璃效果實(shí)例詳解
這篇文章主要為大家介紹了flutter實(shí)現(xiàn)磨砂玻璃效果實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Android仿天貓橫向滑動(dòng)指示器功能的實(shí)現(xiàn)
這篇文章主要介紹了Android仿天貓橫向滑動(dòng)指示器,Android開發(fā)中會(huì)有很多很新奇的交互,比如天貓商城的首頁頭部的分類,使用的是GridLayoutManager+橫向指示器實(shí)現(xiàn)的,需要的朋友可以參考下2022-08-08Android ListView實(shí)現(xiàn)單選及多選等功能示例
這篇文章主要介紹了Android ListView實(shí)現(xiàn)單選及多選等功能的方法,結(jié)合實(shí)例形式分析了ListView單選、多選及長按多選等功能相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-08-08Android實(shí)現(xiàn)簡單的文件下載與上傳
今天小編就為大家分享一篇關(guān)于Android實(shí)現(xiàn)簡單的文件下載與上傳,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12