Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android仿優酷圓形菜單學習筆記分享

Android仿優酷圓形菜單學習筆記分享

編輯:關於Android編程

先來看看效果:

首先來分析一下:

這個菜單可以分成三個菜單:

1.一級菜單(即最內圈那個菜單)

2.二級菜單(即中間圈那個菜單)

3.三級菜單(即最外圈那個菜單)

首先,可以將這三個菜單使用相對布局

一級菜單只有一個按鈕(即home),可以控制二級和三級菜單

二級菜單有三個按鈕(即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.youkumenu.MainActivity" >

  <!-- 三級菜單 -->

  <RelativeLayout
    android:id="@+id/level3_Rl"
    android:layout_width="220dp"
    android:layout_height="110dp"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:background="@drawable/level3" >

    <ImageView
      android:id="@+id/channel1"
      android:layout_marginLeft="5dp"
      android:layout_alignParentBottom="true" 
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel1"/>
    <ImageView
      android:id="@+id/channel2"
      android:layout_marginBottom="10dp"
      android:layout_marginLeft="25dp"
      android:layout_above="@id/channel1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel2"/>
    <ImageView
      android:layout_marginBottom="1dp"
      android:layout_marginLeft="52dp"
      android:layout_above="@id/channel2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel3"/>
    <ImageView
      android:layout_centerHorizontal="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel4"/>
    <ImageView
      android:id="@+id/channel7"
      android:layout_marginRight="5dp"
      android:layout_alignParentRight="true"
      android:layout_alignParentBottom="true" 
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel7"/>
    <ImageView
      android:id="@+id/channel6"
      android:layout_alignParentRight="true"
      android:layout_marginBottom="10dp"
      android:layout_marginRight="25dp"
      android:layout_above="@id/channel7"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel6"/>
    <ImageView
      android:layout_marginBottom="1dp"
      android:layout_marginRight="52dp"
      android:layout_alignParentRight="true"
      android:layout_above="@id/channel6"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel5"/>
  </RelativeLayout>

  <!-- 二級菜單 -->

  <RelativeLayout
    android:id="@+id/level2_Rl"
    android:layout_width="140dp"
    android:layout_height="70dp"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:background="@drawable/level2" >
    <ImageView
      android:layout_marginLeft="3dp"
      android:layout_alignParentBottom="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/icon_search"/>
    <ImageView
      android:id="@+id/menu_Iv"
      android:layout_centerHorizontal="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/icon_menu"/>
    <ImageView
      android:id="@+id/myyouku_Iv"
      android:layout_marginRight="3dp"
      android:layout_alignParentBottom="true"
      android:layout_alignParentRight="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/icon_myyouku"/>

  </RelativeLayout>
  <!-- 一級菜單 -->

  <RelativeLayout
    android:layout_width="80dp"
    android:layout_height="40dp"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:background="@drawable/level1" >

    <ImageView
      android:id="@+id/home_Iv"
      android:layout_centerInParent="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/icon_home" />
  </RelativeLayout>

</RelativeLayout>

那好,布局寫好,就能看到這樣的效果,只不過現在只是靜態的,沒有加邏輯而已

下面就該來分析下邏輯了,先來看看home(即一級菜單中間那個按鈕)

點擊home,會有三種情況,下面分情況考慮:

情況1.二級、三級菜單都顯示,就將二、三級菜單隱藏掉

情況2.二、三級菜單都不顯示的時候,就將二級菜單顯示

情況3.二級菜單顯示且三級菜單不顯示的時候,就將二級菜單隱藏

當然我們知道,要知道菜單隱藏或者顯示,只需要設個標記位即可

那要如何隱藏或顯示菜單,當然是使用動畫了,可以使用補間動畫和

屬性動畫,我這裡就使用補間動畫

下面就該來分析下邏輯了,先來看看menu(即二級菜單中間那個按鈕)

點擊menu,會有三種情況,下面分情況考慮:

情況1.三級顯示的時候,就將三級菜單隱藏

情況2.三級隱藏的時候,就將三級菜單顯示

這個就比較簡單了,就兩種情況。

public class MainActivity extends Activity implements OnClickListener{
  //一級菜單中的home按鈕
  private ImageView home_Iv;
  //二級菜單中的Menu按鈕
  private ImageView menu_Iv;
  //用於判斷二級菜單的顯示狀況,true為顯示,false為隱藏
  private boolean level2ListPlay = true;
  //用於判斷二級菜單的顯示狀況,true為顯示,false為隱藏
  private boolean level3ListPlay = true;
  //二級和三級菜單
  private RelativeLayout level2_Rl,level3_Rl;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initView();
  }  
  //初始化組件
  private void initView() {
    home_Iv = (ImageView) findViewById(R.id.home_Iv);
    home_Iv.setOnClickListener(this);

    level2_Rl = (RelativeLayout) findViewById(R.id.level2_Rl);
    level3_Rl = (RelativeLayout) findViewById(R.id.level3_Rl);

    menu_Iv = (ImageView) findViewById(R.id.menu_Iv);
    menu_Iv.setOnClickListener(this);
  }
  @Override
  public void onClick(View v) {
    switch (v.getId()) {
    case R.id.home_Iv:   //點擊home按鈕的邏輯代碼
      clickHomeIv();
      break;
    case R.id.menu_Iv:
      clickMenuIv();   //點擊二級菜單中的menu按鈕的邏輯代碼
      break;
    default:
      break;
    }
  }
  //點擊二級菜單中的menu按鈕的邏輯代碼
  private void clickMenuIv() {
    //分情況考慮
    //1.三級顯示的時候,就將三級菜單隱藏
    if (level3ListPlay) {
      hideMenu(level3_Rl,0);
      level3ListPlay = false;
      return;
    }
    //2.三級隱藏的時候,就將三級菜單顯示
    if (!level3ListPlay) {
      showMenu(level3_Rl);
      level3ListPlay = true;
      return;
    }
  }
  //點擊一級菜單中的home按鈕的邏輯代碼
  private void clickHomeIv() {
    //分情況考慮
    //1.二級、三級菜單都顯示,就將二、三級菜單隱藏掉
    if (level2ListPlay && level3ListPlay) {
      //將二三級菜單隱藏,並改變標記
      hideMenu(level2_Rl,300);
      hideMenu(level3_Rl,500);
      level2ListPlay = false;
      level3ListPlay = false;
      return;
    }
    //2.二、三級菜單都不顯示的時候,就將二級菜單顯示
    if (!level2ListPlay && !level3ListPlay) {
      showMenu(level2_Rl);
      level2ListPlay = true;
      return;
    }
    //3.二級菜單顯示且三級菜單不顯示的時候,就將二級菜單隱藏
    if (level2ListPlay && !level3ListPlay) {
      hideMenu(level2_Rl,0);
      level2ListPlay = false;
      return;
    }

  }
  /**
   * 顯示菜單
   * @param view 要顯示的菜單
   */
  private void showMenu(RelativeLayout view) {
//   view.setVisibility(View.VISIBLE);
    //旋轉動畫
    RotateAnimation animation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 
        0.5f, Animation.RELATIVE_TO_SELF, 1.0f);
    animation.setDuration(500);   //設置動畫持續的時間
    animation.setFillAfter(true); //動畫停留在動畫結束的位置
    view.startAnimation(animation);
  }
  /**
   * 隱藏菜單
   * @param view 要隱藏的菜單 ,startOffset 動畫延遲執行的時間
   */
  private void hideMenu(RelativeLayout view,long startOffset) {
//   view.setVisibility(View.GONE);
    /** 
     * 旋轉動畫 
     * RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue) 
     * fromDegrees 開始旋轉角度 
     * toDegrees 旋轉的結束角度 
     * pivotXType X軸 參照物 (X軸的伸縮模式,可以取值為ABSOLUTE、RELATIVE_TO_SELF)
     * pivotXValue x軸 旋轉的參考點(x坐標的伸縮值) 
     * pivotYType Y軸 參照物 (Y軸的伸縮模式,可以取值為ABSOLUTE、RELATIVE_TO_SELF)
     * pivotYValue Y軸 旋轉的參考點 ((Y坐標的伸縮值) )
     */ 
    RotateAnimation animation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 
        0.5f, Animation.RELATIVE_TO_SELF, 1.0f);
    animation.setDuration(500);
    animation.setFillAfter(true); //動畫停留在動畫結束的位置
    animation.setStartOffset(startOffset);   //設置動畫的延遲執行
    view.startAnimation(animation);
  }
}

寫到這裡,應該差不多可以看到效果了,但是細心的伙伴應該會發現兩個bug:

第一:當你快速點擊一級菜單home按鈕或二級菜單menu按鈕的時候,會發現二級菜單或三級菜單的第一次動畫還沒執行完,又執行第二次動畫,看起來就在晃一樣。(原因:就是執行的動畫都設定了一定時間,你點擊的時間快於動畫執行的時間)

解決辦法:

對動畫進行監聽,當動畫開始執行和結束的時候,對它進行監聽,大家應該會想到用一個標記位來判斷,可我們知道一個標記為只能判斷兩種狀態,可這裡有兩種動畫(顯示的動畫和隱藏的動畫),一個標記位肯定不行,可以用一個Int值來控制

//用於記錄有多少個動畫在執行
  private int annimationCount = 0;
  //對動畫進行監聽的時候
  animation.setAnimationListener(new AnimationListener() {
      @Override
      public void onAnimationStart(Animation animation) {
//       menu_Iv.setOnClickListener(null);
//       home_Iv.setOnClickListener(null);
        annimationCount ++;
      }
      @Override
      public void onAnimationRepeat(Animation animation) {

      }
      @Override
      public void onAnimationEnd(Animation animation) {
//       menu_Iv.setOnClickListener(MainActivity.this);
//       home_Iv.setOnClickListener(MainActivity.this);
        annimationCount --;
      }
    //當點擊的時候就可以進行判斷,只要annimationCount值大於0,說明還有動畫在執行
    if (annimationCount > 0) {
      return ;
    }

第二:當二級菜單隱藏的時候,你點擊二級菜單中menu按鈕(雖然現在看不見)時,你會驚奇的發現三級菜單居然顯示了。(原因:補間動畫,沒有真正的改變組件的屬性,而屬性動畫就不一樣,大家有時間可以試試屬性動畫做做)

解決辦法:

只要當二級菜單隱藏的時候,就讓二級菜單的所有選項按鈕都不可點。因為二級菜單有可以能有多個按鈕,所以拿到父容器,去使它的子控件失去焦點即可。

//如果要顯示菜單,那麼就將相應的控件設為有焦點
    //獲取父容器中有幾個子控件
    int childCount = view.getChildCount();
    for (int i = 0; i < childCount; i++) {
      view.getChildAt(i).setEnabled(true);
    }

寫到這裡就差不多了,大家可以試試

這裡把我寫的完整代碼貼出來:

public class MainActivity extends Activity implements OnClickListener{
  //一級菜單中的home按鈕
  private ImageView home_Iv;
  //二級菜單中的Menu按鈕
  private ImageView menu_Iv;
  //用於判斷二級菜單的顯示狀況,true為顯示,false為隱藏
  private boolean level2ListPlay = true;
  //用於判斷二級菜單的顯示狀況,true為顯示,false為隱藏
  private boolean level3ListPlay = true;
  //二級和三級菜單
  private RelativeLayout level2_Rl,level3_Rl;
  //用於記錄有多少個動畫在執行
  private int annimationCount = 0;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initView();
  }  
  //初始化組件
  private void initView() {
    home_Iv = (ImageView) findViewById(R.id.home_Iv);
    home_Iv.setOnClickListener(this);

    level2_Rl = (RelativeLayout) findViewById(R.id.level2_Rl);
    level3_Rl = (RelativeLayout) findViewById(R.id.level3_Rl);

    menu_Iv = (ImageView) findViewById(R.id.menu_Iv);
    menu_Iv.setOnClickListener(this);
  }
  @Override
  public void onClick(View v) {
    switch (v.getId()) {
    case R.id.home_Iv:   //點擊home按鈕的邏輯代碼
      clickHomeIv();
      break;
    case R.id.menu_Iv:
      clickMenuIv();   //點擊二級菜單中的menu按鈕的邏輯代碼
      break;
    default:
      break;
    }
  }
  //點擊二級菜單中的menu按鈕的邏輯代碼
  private void clickMenuIv() {
    //當點擊的時候就可以進行判斷,只要annimationCount值大於0,說明還有動畫在執行
    if (annimationCount > 0) {
      return ;
    }
    //分情況考慮
    //1.三級顯示的時候,就將三級菜單隱藏
    if (level3ListPlay) {
      hideMenu(level3_Rl,0);
      level3ListPlay = false;
      return;
    }
    //2.三級隱藏的時候,就將三級菜單顯示
    if (!level3ListPlay) {
      showMenu(level3_Rl);
      level3ListPlay = true;
      return;
    }
  }
  //點擊一級菜單中的home按鈕的邏輯代碼
  private void clickHomeIv() {
    //當點擊的時候就可以進行判斷,只要annimationCount值大於0,說明還有動畫在執行
    if (annimationCount > 0) {
      return ;
    }
    //分情況考慮
    //1.二級、三級菜單都顯示,就將二、三級菜單隱藏掉
    if (level2ListPlay && level3ListPlay) {
      //將二三級菜單隱藏,並改變標記
      hideMenu(level2_Rl,300);
      hideMenu(level3_Rl,500);
      level2ListPlay = false;
      level3ListPlay = false;
      return;
    }
    //2.二、三級菜單都不顯示的時候,就將二級菜單顯示
    if (!level2ListPlay && !level3ListPlay) {
      showMenu(level2_Rl);
      level2ListPlay = true;
      return;
    }
    //3.二級菜單顯示且三級菜單不顯示的時候,就將二級菜單隱藏
    if (level2ListPlay && !level3ListPlay) {
      hideMenu(level2_Rl,0);
      level2ListPlay = false;
      return;
    }

  }
  /**
   * 顯示菜單
   * @param view 要顯示的菜單
   */
  private void showMenu(RelativeLayout view) {
//   view.setVisibility(View.VISIBLE);
    //如果要顯示菜單,那麼就將相應的控件設為有焦點
    //獲取父容器中有幾個子控件
    int childCount = view.getChildCount();
    for (int i = 0; i < childCount; i++) {
      view.getChildAt(i).setEnabled(true);
    }
    //旋轉動畫
    RotateAnimation animation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 
        0.5f, Animation.RELATIVE_TO_SELF, 1.0f);
    animation.setDuration(500);   //設置動畫持續的時間
    animation.setFillAfter(true); //動畫停留在動畫結束的位置
    view.startAnimation(animation);
    animation.setAnimationListener(new AnimationListener() {
      @Override
      public void onAnimationStart(Animation animation) {
        //動畫開始的時候回調
//       menu_Iv.setOnClickListener(null);
//       home_Iv.setOnClickListener(null);
        annimationCount ++;
      }

      @Override
      public void onAnimationRepeat(Animation animation) {
        //動畫執行過程調用
      }

      @Override
      public void onAnimationEnd(Animation animation) {
        //動畫結束的時候調用
//       menu_Iv.setOnClickListener(MainActivity.this);
//       home_Iv.setOnClickListener(MainActivity.this);
        annimationCount --;
      }
    });
  }
  /**
   * 隱藏菜單
   * @param view 要隱藏的菜單 ,startOffset 動畫延遲執行的時間
   */
  private void hideMenu(RelativeLayout view,long startOffset) {
//   view.setVisibility(View.GONE);
    //如果要隱藏菜單,那麼就將相應的控件設為沒有焦點
    //獲取父容器中有幾個子控件
    int childCount = view.getChildCount();
    for (int i = 0; i < childCount; i++) {
      view.getChildAt(i).setEnabled(false);
    }
    /** 
     * 旋轉動畫 
     * RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue) 
     * fromDegrees 開始旋轉角度 
     * toDegrees 旋轉的結束角度 
     * pivotXType X軸 參照物 (X軸的伸縮模式,可以取值為ABSOLUTE、RELATIVE_TO_SELF)
     * pivotXValue x軸 旋轉的參考點(x坐標的伸縮值) 
     * pivotYType Y軸 參照物 (Y軸的伸縮模式,可以取值為ABSOLUTE、RELATIVE_TO_SELF)
     * pivotYValue Y軸 旋轉的參考點 ((Y坐標的伸縮值) )
     */ 
    RotateAnimation animation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 
        0.5f, Animation.RELATIVE_TO_SELF, 1.0f);
    animation.setDuration(500);
    animation.setFillAfter(true); //動畫停留在動畫結束的位置
    animation.setStartOffset(startOffset);   //設置動畫的延遲執行
    view.startAnimation(animation);
    animation.setAnimationListener(new AnimationListener() {
      @Override
      public void onAnimationStart(Animation animation) {
//       menu_Iv.setOnClickListener(null);
//       home_Iv.setOnClickListener(null);
        annimationCount ++;
      }
      @Override
      public void onAnimationRepeat(Animation animation) {

      }
      @Override
      public void onAnimationEnd(Animation animation) {
//       menu_Iv.setOnClickListener(MainActivity.this);
//       home_Iv.setOnClickListener(MainActivity.this);
        annimationCount --;
      }
    });
  }
}

布局文件:

<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.youkumenu.MainActivity" >

  <!-- 三級菜單 -->

  <RelativeLayout
    android:id="@+id/level3_Rl"
    android:layout_width="220dp"
    android:layout_height="110dp"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:background="@drawable/level3" >

    <ImageView
      android:id="@+id/channel1"
      android:layout_marginLeft="5dp"
      android:layout_alignParentBottom="true" 
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel1"/>
    <ImageView
      android:id="@+id/channel2"
      android:layout_marginBottom="10dp"
      android:layout_marginLeft="25dp"
      android:layout_above="@id/channel1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel2"/>
    <ImageView
      android:layout_marginBottom="1dp"
      android:layout_marginLeft="52dp"
      android:layout_above="@id/channel2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel3"/>
    <ImageView
      android:layout_centerHorizontal="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel4"/>
    <ImageView
      android:id="@+id/channel7"
      android:layout_marginRight="5dp"
      android:layout_alignParentRight="true"
      android:layout_alignParentBottom="true" 
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel7"/>
    <ImageView
      android:id="@+id/channel6"
      android:layout_alignParentRight="true"
      android:layout_marginBottom="10dp"
      android:layout_marginRight="25dp"
      android:layout_above="@id/channel7"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel6"/>
    <ImageView
      android:layout_marginBottom="1dp"
      android:layout_marginRight="52dp"
      android:layout_alignParentRight="true"
      android:layout_above="@id/channel6"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/channel5"/>
  </RelativeLayout>

  <!-- 二級菜單 -->

  <RelativeLayout
    android:id="@+id/level2_Rl"
    android:layout_width="140dp"
    android:layout_height="70dp"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:background="@drawable/level2" >
    <ImageView
      android:layout_marginLeft="3dp"
      android:layout_alignParentBottom="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/icon_search"/>
    <ImageView
      android:id="@+id/menu_Iv"
      android:layout_centerHorizontal="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/icon_menu"/>
    <ImageView
      android:id="@+id/myyouku_Iv"
      android:layout_marginRight="3dp"
      android:layout_alignParentBottom="true"
      android:layout_alignParentRight="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/icon_myyouku"/>

  </RelativeLayout>
  <!-- 一級菜單 -->

  <RelativeLayout
    android:layout_width="80dp"
    android:layout_height="40dp"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:background="@drawable/level1" >

    <ImageView
      android:id="@+id/home_Iv"
      android:layout_centerInParent="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:src="@drawable/icon_home" />
  </RelativeLayout>

</RelativeLayout>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家繼續關注本站的更多精彩內容!

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