自定义控件(视图)2期笔记02:自定义控件之使用系统控件(优酷案例之环形菜单布局)

1.首先我们看看效果图:

这是优酷布局效果图:

 

2. 下面是我们最终编写的程序的效果图:

 

3. 下面就是详细演示这个效果的实现过程

(1)新建一个Android工程,命名为"优酷菜单",如下:

 

(2)这里的图片资源都是美工开发好的给我们的,如下:

 

我们把这些图片拷贝到res/drawable(工程图片资源文件),如下:

 

(3)三级菜单实现的效果如下,布局activity_main.xml,如下:

 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="com.himi.youkumenu.MainActivity" >
 6 
 7     <TextView
 8         android:layout_width="wrap_content"
 9         android:layout_height="wrap_content"
10         android:layout_centerHorizontal="true"
11         android:layout_centerVertical="true"
12         android:text="@string/hello_world" />
13 
14     <ImageView
15         android:id="@+id/level1"
16         android:layout_width="100dp"
17         android:layout_height="50dp"
18         android:layout_alignParentBottom="true"
19         android:layout_centerHorizontal="true"
20         android:background="@drawable/level1" /> 
21 
22     <ImageView
23         android:id="@+id/level2"
24         android:layout_width="180dp"
25         android:layout_height="90dp"
26         android:layout_alignParentBottom="true"
27         android:layout_centerHorizontal="true"
28         android:background="@drawable/level2" />
29     
30      <ImageView
31         android:id="@+id/level3"
32         android:layout_width="280dp"
33         android:layout_height="140dp"
34         android:layout_alignParentBottom="true"
35         android:layout_centerHorizontal="true"
36         android:background="@drawable/level3" />
37 </RelativeLayout>

布局效果如下:

 

这样设计确实可以实现三级菜单的效果,但是后面每一级菜单上面都会有很多小图标,这里设置ImageView不利于后面菜单摆放图标,必须修改。

这里activity_main.xml修改,如下:

 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="com.himi.youkumenu.MainActivity" >
 6 
 7     <TextView
 8         android:layout_width="wrap_content"
 9         android:layout_height="wrap_content"
10         android:layout_centerHorizontal="true"
11         android:layout_centerVertical="true"
12         android:text="@string/hello_world" />
13 
14     <RelativeLayout
15         android:id="@+id/level1"
16         android:layout_width="100dp"
17         android:layout_height="50dp"
18         android:layout_alignParentBottom="true"
19         android:layout_centerHorizontal="true"
20         android:background="@drawable/level1" /> 
21 
22     <RelativeLayout
23         android:id="@+id/level2"
24         android:layout_width="180dp"
25         android:layout_height="90dp"
26         android:layout_alignParentBottom="true"
27         android:layout_centerHorizontal="true"
28         android:background="@drawable/level2" />
29     
30      <RelativeLayout
31         android:id="@+id/level3"
32         android:layout_width="280dp"
33         android:layout_height="140dp"
34         android:layout_alignParentBottom="true"
35         android:layout_centerHorizontal="true"
36         android:background="@drawable/level3" />
37 </RelativeLayout>

之前的ImageView改成RelativeLayout布局,方便之后每级菜单摆放小图标

 

(4)接下来实现三级菜单的图标摆放,如下:

activity_main.xml,如下:

  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="com.himi.youkumenu.MainActivity" >
  6 
  7     <TextView
  8         android:layout_width="wrap_content"
  9         android:layout_height="wrap_content"
 10         android:layout_centerHorizontal="true"
 11         android:layout_centerVertical="true"
 12         android:text="@string/hello_world" />
 13 
 14     <RelativeLayout
 15         android:id="@+id/level1"
 16         android:layout_width="100dp"
 17         android:layout_height="50dp"
 18         android:layout_alignParentBottom="true"
 19         android:layout_centerHorizontal="true"
 20         android:background="@drawable/level1" >
 21 
 22         <ImageView
 23             android:id="@+id/icon_home"
 24             android:layout_width="wrap_content"
 25             android:layout_height="wrap_content"
 26             android:layout_centerInParent="true"
 27             android:background="@drawable/icon_home" />
 28     </RelativeLayout>
 29 
 30     <RelativeLayout
 31         android:id="@+id/level2"
 32         android:layout_width="180dp"
 33         android:layout_height="90dp"
 34         android:layout_alignParentBottom="true"
 35         android:layout_centerHorizontal="true"
 36         android:background="@drawable/level2" >
 37 
 38         <ImageView
 39             android:id="@+id/icon_search"
 40             android:layout_width="wrap_content"
 41             android:layout_height="wrap_content"
 42             android:layout_alignParentBottom="true"
 43             android:layout_margin="8dp"
 44             android:background="@drawable/icon_search" />
 45 
 46         <ImageView
 47             android:id="@+id/icon_menu"
 48             android:layout_width="wrap_content"
 49             android:layout_height="wrap_content"
 50             android:layout_alignParentTop="true"
 51             android:layout_centerHorizontal="true"
 52             android:layout_marginTop="5dp"
 53             android:background="@drawable/icon_menu" />
 54 
 55         <ImageView
 56             android:id="@+id/icon_myyouku"
 57             android:layout_width="wrap_content"
 58             android:layout_height="wrap_content"
 59             android:layout_alignParentBottom="true"
 60             android:layout_alignParentRight="true"
 61             android:layout_margin="8dp"
 62             android:background="@drawable/icon_myyouku" />
 63     </RelativeLayout>
 64 
 65     <RelativeLayout
 66         android:id="@+id/level3"
 67         android:layout_width="280dp"
 68         android:layout_height="140dp"
 69         android:layout_alignParentBottom="true"
 70         android:layout_centerHorizontal="true"
 71         android:background="@drawable/level3" >
 72 
 73         <ImageView
 74             android:id="@+id/channel1"
 75             android:layout_width="wrap_content"
 76             android:layout_height="wrap_content"
 77             android:layout_alignParentBottom="true"
 78             android:layout_marginBottom="10dp"
 79             android:layout_marginLeft="10dp"
 80             android:background="@drawable/channel1" />
 81 
 82         <ImageView
 83             android:id="@+id/channel2"
 84             android:layout_width="wrap_content"
 85             android:layout_height="wrap_content"
 86             android:layout_above="@id/channel1"
 87             android:layout_alignLeft="@id/channel1"
 88             android:layout_marginBottom="6dp"
 89             android:layout_marginLeft="20dp"
 90             android:background="@drawable/channel2" />
 91 
 92         <ImageView
 93             android:id="@+id/channel3"
 94             android:layout_width="wrap_content"
 95             android:layout_height="wrap_content"
 96             android:layout_above="@id/channel2"
 97             android:layout_alignLeft="@id/channel2"
 98             android:layout_marginBottom="6dp"
 99             android:layout_marginLeft="30dp"
100             android:background="@drawable/channel3" />
101 
102         <ImageView
103             android:id="@+id/channel4"
104             android:layout_width="wrap_content"
105             android:layout_height="wrap_content"
106             android:layout_centerHorizontal="true"
107             android:layout_marginTop="5dp"
108             android:background="@drawable/channel4" />
109 
110         <ImageView
111             android:id="@+id/channel7"
112             android:layout_width="wrap_content"
113             android:layout_height="wrap_content"
114             android:layout_alignParentBottom="true"
115             android:layout_alignParentRight="true"
116             android:layout_marginBottom="10dp"
117             android:layout_marginRight="10dp"
118             android:background="@drawable/channel7" />
119 
120         <ImageView
121             android:id="@+id/channel6"
122             android:layout_width="wrap_content"
123             android:layout_height="wrap_content"
124             android:layout_above="@id/channel7"
125             android:layout_alignRight="@id/channel7"
126             android:layout_marginBottom="6dp"
127             android:layout_marginRight="20dp"
128             android:background="@drawable/channel6" />
129         
130          <ImageView
131             android:id="@+id/channel5"
132             android:layout_width="wrap_content"
133             android:layout_height="wrap_content"
134             android:layout_above="@id/channel6"
135             android:layout_alignRight="@id/channel6"
136             android:layout_marginBottom="6dp"
137             android:layout_marginRight="30dp"
138             android:background="@drawable/channel5" />
139     </RelativeLayout>
140 
141 </RelativeLayout>

布局效果如下:

 

 

这里第1级菜单 和 第2级菜单实现没什么好讲的,关键是第3级菜单,分析思路如下:

 

第3级菜单左右分为一半,同时channel4为中间一个。

左半部分:channel1为左半部分定位基准

•channel1为左边第一个,让它和父容器的底部对齐(默认是靠左),为了美观好看一点我们添加属性:android:layout_marginBottom="10dp"  和 android:layout_marginLeft="10dp"

•channel2是以channel1为基准进行对齐的,channel2在channel1右上角,但是只要实现channel2在channel1上面的属性:android:layout_above="@id/channel1",没有实现直接属性实现channel2在channel1的右边,该怎么办呢? 这里我们可以先让channel2和channel1进行左对齐,然后设置靠左的边距适当即可:android:layout_alignLeft="@id/channel1"(channel2和channel1左对齐),android:layout_marginLeft="20dp"(设置靠左边距)

•同样道理channel3是以channel2为基准进行对齐的,思路和上面一样。

 

右半部分:思路和上面过程是一致的,这个时候是以channel7为右半部分定位基准

•channel7为右半部分定位基准,而且channel7和channel1是对称的,这样的话,也就是channel7和channel1布局是一致只不过,左右位置调换,如下:

      

 

•其余也是对称设置,channel2 和channel6   ,channel3 和channel5

 

(5)下面就要实现代码部分,利用Animation旋转出现、消失菜单。

首先我们必须知道旋转的坐标系,如下:

 

(6)来到MainActivity,搭建实现逻辑框架,如下:

  1 package com.himi.youkumenu;
  2 
  3 import android.app.Activity;
  4 import android.os.Bundle;
  5 import android.view.KeyEvent;
  6 import android.view.View;
  7 import android.view.View.OnClickListener;
  8 import android.widget.ImageView;
  9 import android.widget.RelativeLayout;
 10 
 11 public class MainActivity extends Activity implements OnClickListener {
 12     private ImageView icon_menu;
 13     private ImageView icon_home;
 14     
 15     private RelativeLayout level1;
 16     private RelativeLayout level2;
 17     private RelativeLayout level3;
 18     /**
 19      * 判断第3级菜单是否显示
 20      * true 显示 (默认)
 21      * false 隐藏
 22      */
 23     private boolean isLevel3Show = true;
 24     /**
 25      * 判断2级菜单是否显示
 26      * true 显示 (默认)
 27      * false 隐藏
 28      */
 29     private boolean isLevel2Show = true;
 30     /**
 31      * 判断1级菜单是否显示
 32      * true 显示 (默认)
 33      * false 隐藏
 34      */
 35     private boolean isLevel1Show = true;
 36 
 37     @Override
 38     protected void onCreate(Bundle savedInstanceState) {
 39         super.onCreate(savedInstanceState);
 40         setContentView(R.layout.activity_main);
 41         
 42         icon_home = (ImageView) findViewById(R.id.icon_home);
 43         icon_menu = (ImageView) findViewById(R.id.icon_menu);
 44         
 45         level1 = (RelativeLayout) findViewById(R.id.level1);
 46         level2 = (RelativeLayout) findViewById(R.id.level2);
 47         level3 = (RelativeLayout) findViewById(R.id.level3);
 48         
 49         icon_home.setOnClickListener(this);
 50         icon_menu.setOnClickListener(this);
 51     }
 52 
 53     public void onClick(View v) {
 54         switch (v.getId()) {
 55         case R.id.icon_menu:// 处理menu的点击的事件
 56             // 如果第3级菜单是显示状态,那么将其隐藏
 57             if (isLevel3Show) {
 58                 MyUtils.startAnimOut(level3);
 59             } else {
 60                 // 如果第3级菜单是隐藏状态,那么将其显示
 61                 MyUtils.startAnimIn(level3);
 62             }
 63 
 64             isLevel3Show = !isLevel3Show;
 65             break;
 66 
 67         case R.id.icon_home:// 处理home的点击的事件
 68             // 如果第2级菜单是显示状态,那么就隐藏2,3级菜单
 69             if (isLevel2Show) {
 70                 MyUtils.startAnimOut(level2);
 71                 isLevel2Show = false;
 72 
 73                 if (isLevel3Show) {// 如果此时第3级菜单是显示状态,那么将其隐藏
 74 
 75                     // 这里不能使用Thread.sleep延迟时间,因为这个办法会是整个线程处于休眠状态,上面的2级菜单也不会旋转离开
 76                     MyUtils.startAnimOut(level3, 200);
 77                     isLevel3Show = false;
 78                 }
 79 
 80             } else {
 81                 // 如果第2级菜单是隐藏状态,那么就显示2级菜单
 82                 MyUtils.startAnimIn(level2);
 83                 isLevel2Show = true;
 84             }
 85 
 86             break;
 87         }
 88     }
 89     
 90     /**
 91      * 监听按键的动作
 92      */
 93     @Override
 94     public boolean onKeyDown(int keyCode, KeyEvent event) {
 95         if(keyCode == KeyEvent.KEYCODE_MENU) {//监听menu按键
 96             changeLevelState();
 97         }
 98         return super.onKeyDown(keyCode, event);
 99     }
100 
101     /**
102      * 改变第1级菜单的状态
103      */
104     private void changeLevelState() {
105         //如果第1菜单是显示状态,隐藏1,2,3级菜单
106         
107         if(isLevel1Show) {
108             MyUtils.startAnimOut(level1);
109             isLevel1Show = false;
110             
111             if(isLevel2Show) {
112                 MyUtils.startAnimOut(level2,100);
113                 isLevel2Show = false;
114                 
115                 if(isLevel3Show) {
116                     MyUtils.startAnimOut(level3,200);
117                     isLevel3Show = false;
118                 }
119             }    
120             
121         } else {
122             //如果第1菜单是隐藏状态,显示1,2级菜单
123             MyUtils.startAnimIn(level1);
124             isLevel1Show = true;
125             
126             MyUtils.startAnimIn(level2,200);
127             isLevel2Show = true;
128         }
129         
130     }
131     
132 
133 
134     
135 }

其中要用到的工具类MyUtils(实现View旋转的方法工具),如下:

 1 package com.himi.youkumenu;
 2 
 3 import android.view.animation.RotateAnimation;
 4 import android.widget.RelativeLayout;
 5 
 6 public class MyUtils {
 7     
 8     /**
 9      * 菜单顺时针旋转离开
10      * @param view
11      */
12     public static void startAnimOut(RelativeLayout view) {
13         startAnimOut(view, 0);
14     }
15 
16     
17     /**
18      * 菜单顺时针旋转进入
19      * @param view
20      */
21     public static void startAnimIn(RelativeLayout view) {
22         startAnimIn(view,0);
23     }
24     
25     /**
26      * 让指定的view延时执行旋转离开的画面
27      * @param view
28      * @param offset 延时时间
29      */
30     public static void startAnimOut(RelativeLayout view, long offset) {
31         /**
32          * 默认圆心为view的左上角
33          * 水平向右为 0度
34          * 顺时针旋转度数增加
35          * 顺时针旋转离开度数变化是:0 ~ 180
36          */
37         RotateAnimation animation = new RotateAnimation(0, 180, view.getWidth()/2, view.getHeight());
38         animation.setDuration(500);//设置运行的时间
39         animation.setFillAfter(true);//动画执行完了之后,保持最后的状态
40         animation.setStartOffset(offset);//设置延时执行的时间参数
41         view.startAnimation(animation);//上面是设置动画效果参数,传入到view的方法startAnimation()方法.    
42     }
43 
44     /**
45      * 让指定的view延时执行旋转进入的画面
46      * @param view
47      * @param offset 延时时间
48      */
49 
50     public static void startAnimIn(RelativeLayout view, long offset) {
51         /**
52          * 默认圆心为view的左上角
53          * 水平向右为 0度
54          * 顺时针旋转度数增加
55          * 顺时针旋转离开度数变化是:180 ~ 360
56          */
57         RotateAnimation animation = new RotateAnimation(180, 360, view.getWidth()/2, view.getHeight());
58         animation.setDuration(500);//设置运行的时间
59         animation.setFillAfter(true);//动画执行完了之后,保持最后的状态
60         animation.setStartOffset(offset);
61         view.startAnimation(animation);
62         
63     }
64 
65 }

 

(7)部署程序到模拟器上,如下:

 

posted on 2015-09-22 12:24  鸿钧老祖  阅读(294)  评论(0编辑  收藏  举报

导航