【0055】自定义控件-2-组合已有控件实现自定义控件-优酷菜单
1.优酷菜单的界面效果及代码书写步骤
1.1 优酷菜单的界面效果

【说明】优酷菜单的控件布局使用从内向外的方式进行布局;
命名的方式是从内到外依次是level1-level3;
1.2 代码书写步骤

2.界面初始化
2.1 level1-3的布局-使用相对布局

【1】图片的宽高可以直接写死;
【2】即使level2的图片覆盖在level1 的图片上,因为此图片是透明的 ,因此不会妨碍点击事件;
2.2.level1-3中的图片按钮的添加
2.2.1 图片按钮中的背景的处理

【处理方法1】

【处理方法2】

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

3.1【执行动画的效果】
【1】在初始的界面下,点击level2的菜单按键,最外层的level3的所有图标收回;
【2】在level3收起的情况下,点击level1的home按键,level2收回;
3.2【分配id】只需要5个id,两个点击事件的和三个执行动画的;
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=".MainActivity" > 6 7 <RelativeLayout 8 android:id="@+id/rl_level1" //第1个id 执行动画 9 android:layout_width="100dp" 10 android:layout_height="50dp" 11 android:layout_alignParentBottom="true" 12 android:layout_centerHorizontal="true" 13 android:background="@drawable/level1" > 14 15 <ImageButton 16 android:id="@+id/ib_home" //第2个id 点击事件 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 android:layout_centerInParent="true" 20 android:background="@null" 21 android:src="@drawable/icon_home" /> 22 </RelativeLayout> 23 24 <RelativeLayout 25 android:id="@+id/rl_level2" //第3个id 执行动画 26 android:layout_width="180dp" 27 android:layout_height="90dp" 28 android:layout_alignParentBottom="true" 29 android:layout_centerHorizontal="true" 30 android:background="@drawable/level2" > 31 32 <ImageButton 33 android:id="@+id/ib_menu"//第4个id 点击事件 34 android:layout_width="wrap_content" 35 android:layout_height="wrap_content" 36 android:layout_centerHorizontal="true" 37 android:background="@null" 38 android:layout_marginTop="5dp" 39 android:src="@drawable/icon_menu" /> 40 41 42 <ImageButton 43 android:layout_width="wrap_content" 44 android:layout_height="wrap_content" 45 android:layout_alignParentBottom="true" 46 android:layout_alignParentLeft="true" 47 android:layout_marginLeft="10dp" 48 android:layout_marginBottom="5dp" 49 android:background="@null" 50 android:src="@drawable/icon_search" /> 51 52 <ImageButton 53 android:layout_width="wrap_content" 54 android:layout_height="wrap_content" 55 android:layout_alignParentBottom="true" 56 android:layout_alignParentRight="true" 57 android:layout_marginRight="10dp" 58 android:layout_marginBottom="5dp" 59 android:background="@null" 60 android:src="@drawable/icon_myyouku" /> 61 62 </RelativeLayout> 63 64 <RelativeLayout 65 android:id="@+id/rl_level3"//第5个id 执行动画 66 android:layout_width="280dp" 67 android:layout_height="140dp" 68 android:layout_alignParentBottom="true" 69 android:layout_centerHorizontal="true" 70 android:background="@drawable/level3" > 71 72 <ImageButton 73 android:layout_width="wrap_content" 74 android:layout_height="wrap_content" 75 android:layout_alignParentBottom="true" 76 android:layout_alignParentLeft="true" 77 android:layout_marginLeft="10dp" 78 android:layout_marginBottom="5dp" 79 android:background="@null" 80 android:src="@drawable/channel1" /> 81 82 <ImageButton 83 android:layout_width="wrap_content" 84 android:layout_height="wrap_content" 85 android:layout_marginLeft="30dp" 86 android:layout_marginTop="60dp" 87 android:background="@null" 88 android:src="@drawable/channel2" /> 89 <ImageButton 90 android:layout_width="wrap_content" 91 android:layout_height="wrap_content" 92 android:layout_marginLeft="65dp" 93 android:layout_marginTop="25dp" 94 android:background="@null" 95 android:src="@drawable/channel3" /> 96 97 <ImageButton 98 android:layout_width="wrap_content" 99 android:layout_height="wrap_content" 100 android:layout_centerHorizontal="true" 101 android:background="@null" 102 android:layout_marginTop="5dp" 103 android:src="@drawable/channel4" /> 104 105 106 <ImageButton 107 android:layout_width="wrap_content" 108 android:layout_height="wrap_content" 109 android:layout_alignParentRight="true" 110 android:background="@null" 111 android:layout_marginRight="30dp" 112 android:layout_marginTop="60dp" 113 android:src="@drawable/channel5" /> 114 115 <ImageButton 116 android:layout_width="wrap_content" 117 android:layout_height="wrap_content" 118 android:layout_marginRight="65dp" 119 android:layout_marginTop="25dp" 120 android:layout_alignParentRight="true" 121 android:background="@null" 122 android:src="@drawable/channel6" /> 123 124 <ImageButton 125 android:layout_width="wrap_content" 126 android:layout_height="wrap_content" 127 android:layout_alignParentBottom="true" 128 android:layout_alignParentRight="true" 129 android:layout_marginRight="10dp" 130 android:layout_marginBottom="5dp" 131 android:background="@null" 132 android:src="@drawable/channel7" /> 133 134 </RelativeLayout> 135 136 </RelativeLayout>
3.3 添加home键和menu键的点击事件
3.3.1 menu键功能
【代码逻辑】在初始化的状态下,点击menu键然后level3隐藏;
如果level3隐藏了,则点击menu键level3显示;


【动画该如何显示】使用补间动画RotateAnimation进行显示,创建动画执行的类AnimationUtils
【Android中的角度的约定】顺时针角度增加,逆时针角度减小;

【动画约定的旋转中心点】



3.3.2 home键功能
【说明】可以直接参考menu键的功能;
【动画实现的源码】
【MainActivity源码】
1 package it.oztaking.com.youkumenu; 2 3 import android.content.Context; 4 import android.support.v7.app.AppCompatActivity; 5 import android.os.Bundle; 6 import android.view.View; 7 import android.view.View.OnClickListener; 8 import android.widget.ImageButton; 9 import android.widget.RelativeLayout; 10 11 import it.oztaking.com.MyAnimationUtils.MyAnimationUtils; 12 13 public class MainActivity extends AppCompatActivity implements OnClickListener { 14 15 private RelativeLayout rl_level1; 16 private RelativeLayout rl_level2; 17 private RelativeLayout rl_level3; 18 private ImageButton ib_home; 19 private ImageButton ib_menu; 20 21 private boolean isLevel3Display = true; 22 private boolean isLevel2Display = true; 23 24 private Context mContext = this; 25 26 27 @Override 28 protected void onCreate(Bundle savedInstanceState) { 29 super.onCreate(savedInstanceState); 30 setContentView(R.layout.activity_main); 31 32 33 //动画的初始化 34 initAnimator(); 35 36 } 37 38 private void initAnimator() { 39 rl_level1 = (RelativeLayout) findViewById(R.id.rl_level1); 40 rl_level2 = (RelativeLayout) findViewById(R.id.rl_level2); 41 rl_level3 = (RelativeLayout) findViewById(R.id.rl_level3); 42 43 44 ib_home = (ImageButton) findViewById(R.id.ib_home); 45 ib_menu = (ImageButton) findViewById(R.id.ib_menu); 46 47 ib_home.setOnClickListener(this); 48 ib_menu.setOnClickListener(this); 49 50 51 } 52 53 @Override 54 public void onClick(View v) { 55 56 switch (v.getId()) { 57 case R.id.ib_home: 58 if (isLevel2Display) { 59 MyAnimationUtils.rotateOutAnim(rl_level2); 60 } else { 61 MyAnimationUtils.rotateInAnim(rl_level2); 62 } 63 isLevel2Display = !isLevel2Display; 64 break; 65 66 case R.id.ib_menu: 67 if (isLevel3Display) { 68 MyAnimationUtils.rotateOutAnim(rl_level3); 69 } else { 70 MyAnimationUtils.rotateInAnim(rl_level3); 71 } 72 isLevel3Display = !isLevel3Display; 73 break; 74 default: 75 break; 76 77 } 78 } 79 }
【MyAnimationUtils源码】
1 package it.oztaking.com.MyAnimationUtils; 2 3 import android.view.animation.Animation; 4 import android.view.animation.RotateAnimation; 5 import android.widget.RelativeLayout; 6 7 /** 8 * Created by Administrator on 2018-01-04. 9 */ 10 11 public class MyAnimationUtils { 12 13 //旋转出去的动画 14 public static void rotateOutAnim(RelativeLayout rl){ 15 RotateAnimation ra = new RotateAnimation( 16 0f, -180f, 17 Animation.RELATIVE_TO_SELF, 0.5f, 18 Animation.RELATIVE_TO_SELF, 1.0f); 19 ra.setFillAfter(true); 20 ra.setDuration(500); 21 rl.startAnimation(ra); 22 } 23 24 //旋转进来的动画 25 public static void rotateInAnim(RelativeLayout rl){ 26 RotateAnimation ra = new RotateAnimation( 27 -180f,0f, 28 Animation.RELATIVE_TO_SELF, 0.5f, 29 Animation.RELATIVE_TO_SELF, 1.0f); 30 ra.setFillAfter(true); 31 ra.setDuration(500); 32 rl.startAnimation(ra); 33 } 34 }
3.3.3 存在的问题
【bug1】【说明】在初始化的状态下,直接点击home键之后不会顾及level2,直接操作level3,会在level2处出现空白;

【改正的方法】在点击home键之后,level3和level2不是同时旋转,level3先旋转,然后level2再旋转;


【存在的问题】上面修改之后的状态是level3和level2同时转出去,应该level2延时一下;
但是,在主线程中不可以随便延时;
【再次修正】增加了传入的延时参数;

【bug2】出现了动画还没有执行结束再次点击按钮就会出现动画直接返回了;

【问题的解决】记录当前已经执行了几个动画,如果执行的动画个数大于2,则屏蔽home键的作用;
需要添加动画的监听;



【实现监听类】

4.菜单按钮的功能的添加
【菜单按钮的功能】点击菜单按钮之后有个level就将几个level都显示出来;
【事件码】在Android手机的按键上,每个按键都会对应一个keycode码;


在Android手机的按键上,每个按键都会对应一个keycode码;


【返回值的指定】需要返回值为true;

【menu按键事件源码】
【注意】需要判断menu键多次按下是否会出现所有的level没有完全出现或者隐藏就接着执行隐藏或者出现的动作,即闪现或者闪退的情况;
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { // keyCode 事件码 System.out.println("onKeyDown: " + keyCode); if(keyCode == KeyEvent.KEYCODE_MENU){ if(AnimationUtils.runningAnimationCount > 0){ // 当前有动画正在执行, 取消当前事件 return true; } // 如果按下的是菜单按钮 if(isLevel1Display){ long delay = 0; // 隐藏三级菜单 if(isLevel3Display){ AnimationUtils.rotateOutAnim(rl_level3, 0); isLevel3Display = false; delay += 200; } // 隐藏二级菜单 if(isLevel2Display){ AnimationUtils.rotateOutAnim(rl_level2, delay); isLevel2Display = false; delay += 200; } // 隐藏一级菜单 AnimationUtils.rotateOutAnim(rl_level1, delay); }else { // 顺次转进来 AnimationUtils.rotateInAnim(rl_level1, 0); AnimationUtils.rotateInAnim(rl_level2, 200); AnimationUtils.rotateInAnim(rl_level3, 400); isLevel3Display = true; isLevel2Display = true; } isLevel1Display = !isLevel1Display; return true;// 消费了当前事件 } return super.onKeyDown(keyCode, event); }
5.BUG-补间动画的缺点
【缺点】即使动画消失之后,原来的按钮还是存在在原来的位置的;
例如,在下图中的level2中的菜单按钮,仍然会起作用;

【解决办法】将level2的按钮禁用掉;
1 public class AnimationUtils { 2 3 // 正在运行的动画个数 4 public static int runningAnimationCount = 0; 5 6 // 旋转出去的动画 7 public static void rotateOutAnim(RelativeLayout layout, long delay) { 8 int childCount = layout.getChildCount(); 9 // 如果隐藏. 则找到所有的子View, 禁用 10 for (int i = 0; i < childCount; i++) { 11 layout.getChildAt(i).setEnabled(false); 12 } 13 ............ 14 } 15 16 // 旋转进来的动画 17 public static void rotateInAnim(RelativeLayout layout, long delay) { 18 19 int childCount = layout.getChildCount(); 20 // 如果隐藏. 则找到所有的子View, 启用 21 for (int i = 0; i < childCount; i++) { 22 layout.getChildAt(i).setEnabled(true); 23 } 24 ............ 25 26 } 27 28 }
浙公网安备 33010602011771号