Android如何实现老版优酷客户端三级环形菜单

来源:互联网 发布:d3.js echarts 区别 编辑:程序博客网 时间:2024/05/03 04:12

转载请附上本文链接:http://blog.csdn.net/cyp331203/article/details/40423727


先来看看效果:




一眼看上去好像还挺炫的,感觉比较复杂。。。实际上并不难,下面我们来看看如何实现:

基本素材就是下面三个:






我们先来看看布局文件怎么写,实际上这里这三张图片都差不多,我们这里使用RelativeLayout,方便后续小图标的加入,基本就是centerInParentaliagnParentBottom,只是外圈小图标的安排要稍微注意一下,这里我们左半边图标以最左边的一个图标为基准,右半边的图标以最右边的一个图标为基准,在这里分别是iv_channel1iv_channel7


[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     tools:context="${relativePackage}.${activityClass}" >  
  6.   
  7.   
  8.     <RelativeLayout  
  9.         android:id="@+id/level1"  
  10.         android:layout_width="100dp"  
  11.         android:layout_height="50dp"  
  12.         android:layout_alignParentBottom="true"  
  13.         android:layout_centerHorizontal="true"  
  14.         android:background="@drawable/level1" >  
  15.   
  16.   
  17.         <ImageView  
  18.             android:id="@+id/iv_icon_home"  
  19.             android:layout_width="50dp"  
  20.             android:layout_height="50dp"  
  21.             android:layout_centerInParent="true"  
  22.             android:src="@drawable/icon_home" />  
  23.     </RelativeLayout>  
  24.   
  25.   
  26.     <RelativeLayout  
  27.         android:id="@+id/level2"  
  28.         android:layout_width="180dp"  
  29.         android:layout_height="90dp"  
  30.         android:layout_alignParentBottom="true"  
  31.         android:layout_centerHorizontal="true"  
  32.         android:background="@drawable/level2" >  
  33.   
  34.   
  35.         <ImageView  
  36.             android:layout_width="wrap_content"  
  37.             android:layout_height="wrap_content"  
  38.             android:layout_alignParentBottom="true"  
  39.             android:layout_margin="10dp"  
  40.             android:src="@drawable/icon_search" >  
  41.         </ImageView>  
  42.   
  43.   
  44.         <ImageView  
  45.             android:layout_width="wrap_content"  
  46.             android:layout_height="wrap_content"  
  47.             android:layout_alignParentBottom="true"  
  48.             android:layout_alignParentRight="true"  
  49.             android:layout_margin="10dp"  
  50.             android:src="@drawable/icon_myyouku" >  
  51.         </ImageView>  
  52.   
  53.   
  54.         <ImageView  
  55.             android:id="@+id/iv_icon_menu"  
  56.             android:layout_width="wrap_content"  
  57.             android:layout_height="wrap_content"  
  58.             android:layout_centerHorizontal="true"  
  59.             android:layout_marginTop="5dp"  
  60.             android:src="@drawable/icon_menu" />  
  61.   
  62.   
  63.     </RelativeLayout>  
  64.   
  65.   
  66.     <RelativeLayout  
  67.         android:id="@+id/level3"  
  68.         android:layout_width="260dp"  
  69.         android:layout_height="130dp"  
  70.         android:layout_alignParentBottom="true"  
  71.         android:layout_centerHorizontal="true"  
  72.         android:background="@drawable/level3" >  
  73.   
  74.   
  75.         <ImageView  
  76.             android:id="@+id/iv_channel1"  
  77.             android:layout_width="wrap_content"  
  78.             android:layout_height="wrap_content"  
  79.             android:layout_alignParentBottom="true"  
  80.             android:layout_marginBottom="10dp"  
  81.             android:layout_marginLeft="5dp"  
  82.             android:src="@drawable/channel1" />  
  83.   
  84.   
  85.         <ImageView  
  86.             android:id="@+id/iv_channel2"  
  87.             android:layout_width="wrap_content"  
  88.             android:layout_height="wrap_content"  
  89.             android:layout_above="@id/iv_channel1"  
  90.             android:layout_alignLeft="@id/iv_channel1"  
  91.             android:layout_marginBottom="7dp"  
  92.             android:layout_marginLeft="18dp"  
  93.             android:src="@drawable/channel2" />  
  94.   
  95.   
  96.   
  97.   
  98.         <ImageView  
  99.             android:id="@+id/iv_channel3"  
  100.             android:layout_width="wrap_content"  
  101.             android:layout_height="wrap_content"  
  102.             android:layout_above="@id/iv_channel2"  
  103.             android:layout_alignLeft="@id/iv_channel2"  
  104.             android:layout_marginBottom="2dp"  
  105.             android:layout_marginLeft="35dp"  
  106.             android:src="@drawable/channel3" />  
  107.   
  108.   
  109.         <ImageView  
  110.             android:id="@+id/iv_channel4"  
  111.             android:layout_width="wrap_content"  
  112.             android:layout_height="wrap_content"  
  113.             android:layout_centerHorizontal="true"  
  114.             android:layout_marginTop="5dp"  
  115.             android:src="@drawable/channel4" />  
  116.   
  117.   
  118.         <ImageView  
  119.             android:id="@+id/iv_channel7"  
  120.             android:layout_width="wrap_content"  
  121.             android:layout_height="wrap_content"  
  122.             android:layout_alignParentBottom="true"  
  123.             android:layout_alignParentRight="true"  
  124.             android:layout_marginBottom="10dp"  
  125.             android:layout_marginRight="5dp"  
  126.             android:src="@drawable/channel7" />  
  127.   
  128.   
  129.         <ImageView  
  130.             android:id="@+id/iv_channel6"  
  131.             android:layout_width="wrap_content"  
  132.             android:layout_height="wrap_content"  
  133.             android:layout_above="@id/iv_channel7"  
  134.             android:layout_alignRight="@id/iv_channel7"  
  135.             android:layout_marginBottom="7dp"  
  136.             android:layout_marginRight="18dp"  
  137.             android:src="@drawable/channel6" />  
  138.   
  139.   
  140.         <ImageView  
  141.             android:id="@+id/iv_channel5"  
  142.             android:layout_width="wrap_content"  
  143.             android:layout_height="wrap_content"  
  144.             android:layout_above="@id/iv_channel6"  
  145.             android:layout_alignRight="@id/iv_channel6"  
  146.             android:layout_marginBottom="2dp"  
  147.             android:layout_marginRight="35dp"  
  148.             android:src="@drawable/channel5" />  
  149.     </RelativeLayout>  
  150.   
  151. </RelativeLayout>  



布局完之后的效果:




之后我们就可以开始着手这个怎么实现,我们的基本想法是(小房子图标所在的为level1,第二圈灰色的部分为level2,最外圈为level3):

1、点击小房子图标,如果level2和level3都处于显示状态,则将这两层都隐藏,如果这两层都不存在,则只将level2显示出来;如果只有level2显示着,那么将level2隐藏


2、点击levle2的”三“字图标,则实现隐藏和显示level3组件


3、点击手机的menu键,则实现如果level1,2,3都处于显示状态,则将三者都隐藏,如果只有level1、level2显示,则将level1、2隐藏,如果只有level1显示,则将level1隐藏;如果没有任何level显示着,则将level1和level2显示出来


4、上面的显示和隐藏的过程,都使用动画来实现


基本逻辑关系已经理清楚了,那么现在的问题就在于这个Animation如何写;显然我们这里需要用到一个RotateAnimation旋转动画,由于这里牵涉到旋出和旋入的效果,我们必须要清楚这个动画的角度是如何定的比如从0~180是旋入还是旋出效果

经过实验,我们发现,RotateAnimation的角度如下,我们可以发现,它的角度定义是按照顺时针增长的



那么按照这个角度来看,我们如果想要组件顺时针旋入,同时顺时针旋出的话,角度是要如何确定的呢



从上图可以比较容易看出来,顺时针旋出的话,角度是从0~180度,那么旋入呢?是不是从180~0度?,实际上这里旋入应该是180~360度

同样的,如果这里想实现逆时针出入的话,角度可以设为0~-180和-180~-360度,留给大家自己试试。


在角度确定好之后呢,我们可以来着手实现动画效果,这里由于三个组件level1、level2、level3的动画都是一致的,所以这里选择使用一个工具类,来实现几个静态方法,来定义动画,达到复用的效果:

工具类如下:


[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.alexchen.youkumenuexercise.utils;  
  2.   
  3. import android.view.View;  
  4. import android.view.animation.RotateAnimation;  
  5.   
  6. public class AnimationUtils {  
  7.     //旋出的动画,无延迟时间  
  8.     public static void startAnimationOut(View view) {  
  9.         startAnimationOut(view, 0);  
  10.   
  11.     }  
  12.     //旋入的动画,无延迟时间  
  13.     public static void startAnimationIn(View view) {  
  14.         startAnimationIn(view, 0);  
  15.     }  
  16.       
  17.     //旋出的动画  
  18.     //delay为动画延迟的时间,单位是毫秒  
  19.     public static void startAnimationOut(View view, long delay) {  
  20.         RotateAnimation animation = new RotateAnimation(0180,  
  21.                 view.getWidth() / 2, view.getHeight());  
  22.         animation.setDuration(500);  
  23.         animation.setStartOffset(delay);  
  24.         animation.setFillAfter(true);  
  25.         view.startAnimation(animation);  
  26.   
  27.     }  
  28.     //旋入的动画  
  29.     //delay为动画延迟的时间,单位是毫秒  
  30.     public static void startAnimationIn(View view, long delay) {  
  31.         RotateAnimation animation = new RotateAnimation(180360,  
  32.                 view.getWidth() / 2, view.getHeight());  
  33.         animation.setDuration(500);  
  34.         animation.setStartOffset(delay);  
  35.         animation.setFillAfter(true);  
  36.         view.startAnimation(animation);  
  37.     }  
  38.   
  39. }  



其中设置了两个能够延时开启动画的方法,为的是让三个组件进出的时候能够体现出层次感,让用户体验更好。


最后是Activity中的代码,这里没有做任何生命周期相关的处理,只是简单的实现功能:


[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.alexchen.youkumenuexercise;  
  2.   
  3. import com.alexchen.youkumenuexercise.utils.AnimationUtils;  
  4.   
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.view.KeyEvent;  
  8. import android.view.View;  
  9. import android.view.View.OnClickListener;  
  10. import android.widget.ImageView;  
  11. import android.widget.RelativeLayout;  
  12.   
  13. public class MainActivity extends Activity implements OnClickListener {  
  14.   
  15.     private RelativeLayout level1;  
  16.     private RelativeLayout level2;  
  17.     private RelativeLayout level3;  
  18.   
  19.     private ImageView iv_icon_menu;  
  20.     private ImageView iv_icon_home;  
  21.     /** 
  22.      * 表示level3是否是现状状态,默认为true 
  23.      */  
  24.     private boolean isLevel3In;  
  25.     private boolean isLevel2In;  
  26.     private boolean isLevel1In;  
  27.   
  28.     @Override  
  29.     protected void onCreate(Bundle savedInstanceState) {  
  30.         super.onCreate(savedInstanceState);  
  31.         setContentView(R.layout.activity_main);  
  32.         isLevel3In = true;  
  33.         isLevel2In = true;  
  34.         isLevel1In = true;  
  35.         initViews();  
  36.         setOnclickListenersForViews();  
  37.     }  
  38.   
  39.     /** 
  40.      * 设置views的监听事件 
  41.      */  
  42.     private void setOnclickListenersForViews() {  
  43.         iv_icon_home.setOnClickListener(this);  
  44.         iv_icon_menu.setOnClickListener(this);  
  45.   
  46.     }  
  47.   
  48.     /** 
  49.      * 初始化需要的view组件 
  50.      */  
  51.     private void initViews() {  
  52.         level1 = (RelativeLayout) findViewById(R.id.level1);  
  53.         level2 = (RelativeLayout) findViewById(R.id.level2);  
  54.         level3 = (RelativeLayout) findViewById(R.id.level3);  
  55.         iv_icon_menu = (ImageView) findViewById(R.id.iv_icon_menu);  
  56.         iv_icon_home = (ImageView) findViewById(R.id.iv_icon_home);  
  57.     }  
  58.   
  59.     /** 
  60.      * activity响应的点击事件 
  61.      */  
  62.     @Override  
  63.     public void onClick(View v) {  
  64.         switch (v.getId()) {  
  65.         case R.id.iv_icon_menu:  
  66.             if (isLevel3In) {  
  67.                 // 如果level3是显示的,那么就让出去  
  68.                 AnimationUtils.startAnimationOut(level3);  
  69.                 isLevel3In = false;  
  70.             } else {  
  71.                 // 如果level3是不显示的,那么让其进入  
  72.                 AnimationUtils.startAnimationIn(level3);  
  73.                 isLevel3In = true;  
  74.             }  
  75.   
  76.             break;  
  77.         case R.id.iv_icon_home:  
  78.             if (isLevel2In) {  
  79.                 // 如果level2是显示状态  
  80.                 AnimationUtils.startAnimationOut(level2, 200);  
  81.                 isLevel2In = false;  
  82.             } else {  
  83.                 AnimationUtils.startAnimationIn(level2);  
  84.                 isLevel2In = true;  
  85.             }  
  86.             if (isLevel3In) {  
  87.                 AnimationUtils.startAnimationOut(level3);  
  88.                 isLevel3In = false;  
  89.             }  
  90.   
  91.             break;  
  92.   
  93.         default:  
  94.             break;  
  95.         }  
  96.     }  
  97.   
  98.     @Override  
  99.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  100.         if (keyCode == KeyEvent.KEYCODE_MENU) {  
  101.             // 如果是menu键按下的话:  
  102.             changeLevelState();  
  103.   
  104.         }  
  105.         return super.onKeyDown(keyCode, event);  
  106.     }  
  107.   
  108.     /** 
  109.      * 改变三个圆环的状态 
  110.      */  
  111.     private void changeLevelState() {  
  112.         if (isLevel1In) {  
  113.             AnimationUtils.startAnimationOut(level1, 400);  
  114.             isLevel1In = false;  
  115.         } else {  
  116.             AnimationUtils.startAnimationIn(level1);  
  117.             isLevel1In = true;  
  118.         }  
  119.         if (isLevel2In) {  
  120.             AnimationUtils.startAnimationOut(level2, 200);  
  121.             isLevel2In = false;  
  122.         } else {  
  123.             AnimationUtils.startAnimationIn(level2, 200);  
  124.             isLevel2In = true;  
  125.         }  
  126.         if (isLevel3In) {  
  127.             AnimationUtils.startAnimationOut(level3);  
  128.             isLevel3In = false;  
  129.         }  
  130.     }  
  131.   

0 0
原创粉丝点击