实现底部扇形展开菜单效果

先看效果图





项目的总结构



下面开始贴代码,由于必要的地方都添加了注释,所以不过多讲解


anim_button.xml

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent" >  
  5.   
  6.     <Button  
  7.         android:id="@+id/btn_sleep"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_alignParentBottom="true"  
  11.         android:layout_alignParentLeft="true"  
  12.         android:layout_marginBottom="10dp"  
  13.         android:layout_marginLeft="10dp"  
  14.         android:visibility="invisible"  
  15.         android:background="@drawable/composer_sleep" />  
  16.   
  17.     <Button  
  18.         android:id="@+id/btn_thought"  
  19.         android:layout_width="wrap_content"  
  20.         android:layout_height="wrap_content"  
  21.         android:layout_alignParentBottom="true"  
  22.         android:layout_alignParentLeft="true"  
  23.         android:layout_marginBottom="10dp"  
  24.         android:layout_marginLeft="10dp"  
  25.         android:visibility="invisible"  
  26.         android:background="@drawable/composer_thought" />  
  27.   
  28.     <Button  
  29.         android:id="@+id/btn_music"  
  30.         android:layout_width="wrap_content"  
  31.         android:layout_height="wrap_content"  
  32.         android:layout_alignParentBottom="true"  
  33.         android:layout_alignParentLeft="true"  
  34.         android:layout_marginBottom="10dp"  
  35.         android:layout_marginLeft="10dp"  
  36.         android:visibility="invisible"  
  37.         android:background="@drawable/composer_music" />  
  38.   
  39.     <Button  
  40.         android:id="@+id/btn_place"  
  41.         android:layout_width="wrap_content"  
  42.         android:layout_height="wrap_content"  
  43.         android:layout_alignParentBottom="true"  
  44.         android:layout_alignParentLeft="true"  
  45.         android:layout_marginBottom="10dp"  
  46.         android:layout_marginLeft="10dp"  
  47.         android:visibility="invisible"  
  48.         android:background="@drawable/composer_place" />  
  49.   
  50.     <Button  
  51.         android:id="@+id/btn_with"  
  52.         android:layout_width="wrap_content"  
  53.         android:layout_height="wrap_content"  
  54.         android:layout_alignParentBottom="true"  
  55.         android:layout_alignParentLeft="true"  
  56.         android:layout_marginBottom="10dp"  
  57.         android:layout_marginLeft="10dp"  
  58.         android:visibility="invisible"  
  59.         android:background="@drawable/composer_with" />  
  60.   
  61.     <Button  
  62.         android:id="@+id/btn_camera"  
  63.         android:layout_width="wrap_content"  
  64.         android:layout_height="wrap_content"  
  65.         android:layout_alignParentBottom="true"  
  66.         android:layout_alignParentLeft="true"  
  67.         android:layout_marginBottom="10dp"  
  68.         android:layout_marginLeft="10dp"  
  69.         android:visibility="invisible"  
  70.         android:background="@drawable/composer_camera" />  
  71.   
  72.     <Button  
  73.         android:id="@+id/btn_menu"  
  74.         android:layout_width="60dp"  
  75.         android:layout_height="60dp"  
  76.         android:layout_alignParentBottom="true"  
  77.         android:layout_alignParentLeft="true"  
  78.         android:background="@drawable/friends_delete" />  
  79.   
  80. </RelativeLayout>  

主界面的布局main.xml

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.       
  7.     <com.example.anim.AnimButtons  
  8.         android:id="@+id/animButtons"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="fill_parent"  
  11.         />  
  12. </LinearLayout>  

最重要的,自定义控件的实现

AnimButtons.java

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.example.anim;  
  2.   
  3. import android.R.anim;  
  4. import android.content.Context;  
  5. import android.util.AttributeSet;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.view.animation.Animation;  
  9. import android.view.animation.Animation.AnimationListener;  
  10. import android.view.animation.ScaleAnimation;  
  11. import android.view.animation.TranslateAnimation;  
  12. import android.widget.Button;  
  13. import android.widget.RelativeLayout;  
  14.   
  15. /** 
  16.  * 底部展开菜单实现 
  17.  *  
  18.  * @author ZhaoKaiQiang 
  19.  *  
  20.  *         Time:2014年3月11日 
  21.  */  
  22. public class AnimButtons extends RelativeLayout {  
  23.   
  24.     private Context context;  
  25.     private int leftMargin = 0, bottomMargin = 0;  
  26.     private final int buttonWidth = 58;// 图片宽高  
  27.     private final int r = 180;// 半径  
  28.     private final int maxTimeSpent = 200;// 最长动画耗时  
  29.     private final int minTimeSpent = 80;// 最短动画耗时  
  30.     private int intervalTimeSpent;// 每相邻2个的时间间隔  
  31.     private Button[] btns;  
  32.     private Button btn_menu;  
  33.     private RelativeLayout.LayoutParams params;  
  34.     private boolean isOpen = false;// 是否菜单打开状态  
  35.     private float angle;// 每个按钮之间的夹角  
  36.   
  37.     public int bottomMargins = this.getMeasuredHeight() - buttonWidth  
  38.             - bottomMargin;  
  39.   
  40.     public AnimButtons(Context context) {  
  41.         super(context);  
  42.         this.context = context;  
  43.     }  
  44.   
  45.     public AnimButtons(Context context, AttributeSet attrs) {  
  46.         super(context, attrs);  
  47.         this.context = context;  
  48.     }  
  49.   
  50.     @Override  
  51.     protected void onFinishInflate() {  
  52.         super.onFinishInflate();  
  53.         View view = LayoutInflater.from(context).inflate(R.layout.anim_buttons,  
  54.                 this);  
  55.   
  56.         initButtons(view);  
  57.   
  58.     }  
  59.   
  60.     private void initButtons(View view) {  
  61.         // 可以根据按钮的个数自己增减  
  62.         btns = new Button[4];  
  63.         btns[0] = (Button) view.findViewById(R.id.btn_camera);  
  64.         btns[1] = (Button) view.findViewById(R.id.btn_with);  
  65.         btns[2] = (Button) view.findViewById(R.id.btn_place);  
  66.         btns[3] = (Button) view.findViewById(R.id.btn_music);  
  67.         // btns[4] = (Button) view.findViewById(R.id.btn_thought);  
  68.         // btns[5] = (Button) view.findViewById(R.id.btn_sleep);  
  69.         btn_menu = (Button) view.findViewById(R.id.btn_menu);  
  70.   
  71.         leftMargin = ((RelativeLayout.LayoutParams) (btn_menu.getLayoutParams())).leftMargin;  
  72.         bottomMargin = ((RelativeLayout.LayoutParams) (btn_menu  
  73.                 .getLayoutParams())).bottomMargin;  
  74.   
  75.         for (int i = 0; i < btns.length; i++) {  
  76.             // 初始化的时候按钮重合  
  77.             btns[i].setLayoutParams(btn_menu.getLayoutParams());  
  78.             btns[i].setTag(String.valueOf(i));  
  79.             btns[i].setOnClickListener(clickListener);  
  80.         }  
  81.   
  82.         intervalTimeSpent = (maxTimeSpent - minTimeSpent) / btns.length;  
  83.         angle = (float) Math.PI / (2 * (btns.length - 1));  
  84.     }  
  85.   
  86.     @Override  
  87.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  88.         super.onSizeChanged(w, h, oldw, oldh);  
  89.         bottomMargins = this.getMeasuredHeight() - buttonWidth - bottomMargin;  
  90.         btn_menu.setOnClickListener(new OnClickListener() {  
  91.   
  92.             @Override  
  93.             public void onClick(View v) {  
  94.                 if (!isOpen) {  
  95.                     openMenu();  
  96.                 } else {  
  97.                     closeMenu();  
  98.                 }  
  99.             }  
  100.         });  
  101.   
  102.     }  
  103.   
  104.     public void closeMenu() {  
  105.         if (isOpen == true) {  
  106.             isOpen = false;  
  107.             for (int i = 0; i < btns.length; i++) {  
  108.                 float xLenth = (float) (r * Math.sin(i * angle));  
  109.                 float yLenth = (float) (r * Math.cos(i * angle));  
  110.                 btns[i].startAnimation(animTranslate(-xLenth, yLenth,  
  111.                         leftMargin, bottomMargins, btns[i], maxTimeSpent - i  
  112.                                 * intervalTimeSpent));  
  113.                 btns[i].setVisibility(View.INVISIBLE);  
  114.             }  
  115.         }  
  116.     }  
  117.   
  118.     public void openMenu() {  
  119.         isOpen = true;  
  120.         for (int i = 0; i < btns.length; i++) {  
  121.             float xLenth = (float) (r * Math.sin(i * angle));  
  122.             float yLenth = (float) (r * Math.cos(i * angle));  
  123.             btns[i].startAnimation(animTranslate(xLenth, -yLenth, leftMargin  
  124.                     + (int) xLenth, bottomMargins - (int) yLenth, btns[i],  
  125.                     minTimeSpent + i * intervalTimeSpent));  
  126.             btns[i].setVisibility(View.VISIBLE);  
  127.         }  
  128.   
  129.     }  
  130.   
  131.     private Animation animScale(float toX, float toY) {  
  132.         Animation animation = new ScaleAnimation(1.0f, toX, 1.0f, toY,  
  133.                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,  
  134.                 0.5f);  
  135.         animation.setInterpolator(context,  
  136.                 anim.accelerate_decelerate_interpolator);  
  137.         animation.setDuration(400);  
  138.         animation.setFillAfter(false);  
  139.         return animation;  
  140.   
  141.     }  
  142.   
  143.     private Animation animTranslate(float toX, float toY, final int lastX,  
  144.             final int lastY, final Button button, long durationMillis) {  
  145.         Animation animation = new TranslateAnimation(0, toX, 0, toY);  
  146.         animation.setAnimationListener(new AnimationListener() {  
  147.   
  148.             @Override  
  149.             public void onAnimationStart(Animation animation) {  
  150.   
  151.             }  
  152.   
  153.             @Override  
  154.             public void onAnimationRepeat(Animation animation) {  
  155.   
  156.             }  
  157.   
  158.             @Override  
  159.             public void onAnimationEnd(Animation animation) {  
  160.                 params = new RelativeLayout.LayoutParams(00);  
  161.                 params.height = buttonWidth;  
  162.                 params.width = buttonWidth;  
  163.                 params.setMargins(lastX, lastY, 00);  
  164.                 button.setLayoutParams(params);  
  165.                 button.clearAnimation();  
  166.   
  167.             }  
  168.         });  
  169.         animation.setDuration(durationMillis);  
  170.         return animation;  
  171.     }  
  172.   
  173.     View.OnClickListener clickListener = new View.OnClickListener() {  
  174.   
  175.         @Override  
  176.         public void onClick(View v) {  
  177.             int selectedItem = Integer.parseInt((String) v.getTag());  
  178.             for (int i = 0; i < btns.length; i++) {  
  179.                 if (i == selectedItem) {  
  180.                     btns[i].startAnimation(animScale(2.0f, 2.0f));  
  181.                 } else {  
  182.                     btns[i].startAnimation(animScale(0.0f, 0.0f));  
  183.                 }  
  184.             }  
  185.             if (onButtonClickListener != null) {  
  186.                 onButtonClickListener.onButtonClick(v, selectedItem);  
  187.             }  
  188.         }  
  189.   
  190.     };  
  191.   
  192.     public boolean isOpen() {  
  193.         return isOpen;  
  194.     }  
  195.   
  196.     private OnButtonClickListener onButtonClickListener;  
  197.   
  198.     public interface OnButtonClickListener {  
  199.         void onButtonClick(View v, int id);  
  200.     }  
  201.   
  202.     public void setOnButtonClickListener(  
  203.             OnButtonClickListener onButtonClickListener) {  
  204.         this.onButtonClickListener = onButtonClickListener;  
  205.     }  
  206.   
  207. }  

AnimButtonsActivity.java

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.example.anim;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.view.View;  
  6. import android.widget.Toast;  
  7. /** 
  8.  * 主界面 
  9.  * @author  ZhaoKaiQiang 
  10.  *           
  11.  *          Time:2014年3月11日 
  12.  */  
  13. public class AnimButtonsActivity extends Activity {  
  14.   
  15.     private AnimButtons animButtons;  
  16.       
  17.     @Override  
  18.     public void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.main);  
  21.         animButtons = (AnimButtons) findViewById(R.id.animButtons);  
  22.         animButtons  
  23.                 .setOnButtonClickListener(new AnimButtons.OnButtonClickListener() {  
  24.                     @Override  
  25.                     public void onButtonClick(View v, int id) {  
  26.                         Toast.makeText(AnimButtonsActivity.this"id-->" + id,  
  27.                                 0).show();  
  28.                         animButtons.closeMenu();  
  29.                     }  
  30.                 });  
  31.     }  
  32. }  

点击下载源码


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值