zoukankan      html  css  js  c++  java
  • 自定义控件(视图)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)部署程序到模拟器上,如下:

  • 相关阅读:
    基于Python的人脸动漫转换
    let 与 var的区别
    【LeetCode】汇总
    【HDU】4632 Palindrome subsequence(回文子串的个数)
    【算法】均匀的生成圆内的随机点
    【LeetCode】725. Split Linked List in Parts
    【LeetCode】445. Add Two Numbers II
    【LeetCode】437. Path Sum III
    【LeetCode】222. Count Complete Tree Nodes
    【LeetCode】124. Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/hebao0514/p/4828575.html
Copyright © 2011-2022 走看看