`
shuai1234
  • 浏览: 932023 次
  • 性别: Icon_minigender_1
  • 来自: 山西
社区版块
存档分类
最新评论

Android超仿Path菜单的实现!

 
阅读更多

好了,今天给大家分享的是Path菜单的简单实现,可以支持自定义方向(左上,右上,右下,左下),并且可以自定义菜单的个数,难点就是菜单的摆放位置(动态设置margin),还有动画的实现,其实动画只是简单用了个TranslateAnimation,N个菜单一起移动的时候感觉很cool~

这里也用到了自定义标签,这里不懂的童鞋可以看我 Android高手进阶教程(四)之----Android 中自定义属性(attr.xml,TypedArray)的使用! 这篇文章.好了废话不多说了,

首先创建一个android工程命名为PathTest.目录结构如下图:

 

第二步:在values文件夹下新建一个attrs.xml文件,代码如下:

 

[html] view plaincopy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <declare-styleable name="PathMenuView">    
  4.         <attr name="position">   
  5.             <enum name="left_top" value="0"></enum>  
  6.             <enum name="right_top" value="1"></enum>  
  7.             <enum name="right_bottom" value="2"></enum>  
  8.             <enum name="left_bottom" value="3"></enum>  
  9.         </attr>  
  10.     </declare-styleable>    
  11. </resources>  

 

第三步:新建一个PathMenuView.java这个就是我们自定义的Path菜单控件,代码如下:

 

[java] view plaincopy
 
  1. package com.tutor.path;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.util.AttributeSet;  
  6. import android.view.Gravity;  
  7. import android.view.View;  
  8. import android.view.ViewGroup;  
  9. import android.view.animation.Animation;  
  10. import android.view.animation.AnticipateInterpolator;  
  11. import android.view.animation.OvershootInterpolator;  
  12. import android.view.animation.TranslateAnimation;  
  13. import android.widget.FrameLayout;  
  14. import android.widget.ImageView;  
  15.   
  16.   
  17. /** 
  18.  * @author frankiewei. 
  19.  * 超级仿path菜单 
  20.  * position定义菜单的位置,目前支持:左上;右上;右下;左下四个方向。 
  21.  * menuResIds定义出现的菜单的资源ID 
  22.  */  
  23. public class PathMenuView extends FrameLayout {  
  24.       
  25.     private static final int LEFT_TOP = 0;  
  26.       
  27.     private static final int RIGHT_TOP = 1;  
  28.       
  29.     private static final int RIGHT_BOTTOM = 2;  
  30.       
  31.     private static final int LEFT_BOTTOM = 3;  
  32.       
  33.       
  34.     /** 
  35.      * 默认的位置是在右下角. 
  36.      */  
  37.     private int position = 3;  
  38.       
  39.     /** 
  40.      * 那个圆形菜单. 
  41.      */  
  42.     private ImageView mHome;  
  43.       
  44.     /** 
  45.      * 上下文. 
  46.      */  
  47.     private Context mContext;  
  48.       
  49.       
  50.     /** 
  51.      * 设备的宽度. 
  52.      */  
  53.     private int mWIDTH = 0;  
  54.       
  55.     /** 
  56.      * 设备的高度. 
  57.      */  
  58.     private int mHEIGHT = 0;  
  59.       
  60.     /** 
  61.      * 设备的density. 
  62.      */  
  63.     private float mDensity;  
  64.       
  65.     /** 
  66.      * 菜单是否显示. 
  67.      */  
  68.     private boolean bMenuShow;  
  69.       
  70.     private static int  xOffset     = 15;  
  71.     private static int  yOffset     = -13;  
  72.       
  73.     /** 
  74.      * 菜单的资源个数. 
  75.      */  
  76.     private int[] menuResIds = {R.drawable.composer_camera,R.drawable.composer_music,  
  77.             R.drawable.composer_sleep,R.drawable.composer_music,R.drawable.composer_place};  
  78.       
  79.   
  80.     public PathMenuView(Context context){  
  81.         super(context);  
  82.         setupViews();  
  83.     }  
  84.       
  85.     public PathMenuView(Context context, AttributeSet attrs) {  
  86.         super(context, attrs);  
  87.         TypedArray a = context.obtainStyledAttributes(attrs,    
  88.                 R.styleable.PathMenuView);  
  89.           
  90.         position = a.getInt(R.styleable.PathMenuView_position,3);  
  91.           
  92.         a.recycle();  
  93.         setupViews();  
  94.     }  
  95.       
  96.     private void setupViews(){  
  97.         mContext = getContext();  
  98.   
  99.         mHEIGHT = mContext.getResources().getDisplayMetrics().heightPixels;  
  100.         mWIDTH = mContext.getResources().getDisplayMetrics().widthPixels;  
  101.         mDensity = mContext.getResources().getDisplayMetrics().density;  
  102.           
  103.         xOffset = (int) (10.667 * mDensity);  
  104.         yOffset = (int) (8.667 * mDensity);  
  105.           
  106.         mHome = new ImageView(mContext);  
  107.           
  108.         mHome.setImageResource(R.drawable.composer_button);  
  109.         mHome.setOnClickListener(listener);  
  110.           
  111.         addView(mHome);  
  112.           
  113.         LayoutParams mHomeparams = (FrameLayout.LayoutParams)mHome.getLayoutParams();  
  114.         mHomeparams.width = LayoutParams.WRAP_CONTENT;  
  115.         mHomeparams.height = LayoutParams.WRAP_CONTENT;  
  116.           
  117.         switch (position) {  
  118.         case LEFT_TOP:  
  119.             mHomeparams.gravity = Gravity.LEFT | Gravity.TOP;  
  120.             for (int i = 0; i < menuResIds.length; i++) {  
  121.   
  122.                 int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);  
  123.                 int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2);  
  124.   
  125.                 ImageView imageView = new ImageView(mContext);  
  126.                 imageView.setImageResource(menuResIds[i]);  
  127.                 addView(imageView);  
  128.                 LayoutParams params = (FrameLayout.LayoutParams) imageView  
  129.                         .getLayoutParams();  
  130.                 params.width = LayoutParams.WRAP_CONTENT;  
  131.                 params.height = LayoutParams.WRAP_CONTENT;  
  132.                 params.leftMargin = mWIDTH / 2  
  133.                         - ((menuResIds.length - i - 1) * width_padding);  
  134.                 params.topMargin = mHEIGHT / 2 - i * height_padding;  
  135.                 params.gravity = Gravity.LEFT | Gravity.TOP;  
  136.                 imageView.setLayoutParams(params);  
  137.   
  138.             }  
  139.               
  140.             break;  
  141.         case RIGHT_TOP:  
  142.             mHomeparams.gravity = Gravity.RIGHT | Gravity.TOP;  
  143.             for (int i = 0; i < menuResIds.length; i++) {  
  144.   
  145.                 int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);  
  146.                 int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2);  
  147.   
  148.                 ImageView imageView = new ImageView(mContext);  
  149.                 imageView.setImageResource(menuResIds[i]);  
  150.                 addView(imageView);  
  151.                 LayoutParams params = (FrameLayout.LayoutParams) imageView  
  152.                         .getLayoutParams();  
  153.                 params.width = LayoutParams.WRAP_CONTENT;  
  154.                 params.height = LayoutParams.WRAP_CONTENT;  
  155.                 params.rightMargin = mWIDTH / 2  
  156.                         - ((menuResIds.length - i - 1) * width_padding);  
  157.                 params.topMargin = mHEIGHT / 2 - i * height_padding;  
  158.                 params.gravity = Gravity.RIGHT | Gravity.TOP;  
  159.                 imageView.setLayoutParams(params);  
  160.   
  161.             }  
  162.             break;  
  163.         case RIGHT_BOTTOM:  
  164.             mHomeparams.gravity = Gravity.RIGHT | Gravity.BOTTOM;  
  165.             for (int i = 0; i < menuResIds.length; i++) {  
  166.   
  167.                 int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);  
  168.                 int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2);  
  169.   
  170.                 ImageView imageView = new ImageView(mContext);  
  171.                 imageView.setImageResource(menuResIds[i]);  
  172.                 addView(imageView);  
  173.                 LayoutParams params = (FrameLayout.LayoutParams) imageView  
  174.                         .getLayoutParams();  
  175.                 params.width = LayoutParams.WRAP_CONTENT;  
  176.                 params.height = LayoutParams.WRAP_CONTENT;  
  177.                 params.rightMargin = mWIDTH / 2  
  178.                         - ((menuResIds.length - i - 1) * width_padding);  
  179.                 params.bottomMargin = mHEIGHT / 2 - i * height_padding;  
  180.                 params.gravity = Gravity.RIGHT | Gravity.BOTTOM;  
  181.                 imageView.setLayoutParams(params);  
  182.   
  183.             }  
  184.             break;  
  185.         case LEFT_BOTTOM:  
  186.             mHomeparams.gravity = Gravity.LEFT | Gravity.BOTTOM;  
  187.             for(int i = 0; i < menuResIds.length; i++){  
  188.                   
  189.                 int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);  
  190.                 int height_padding = mHEIGHT / ((menuResIds.length -1) * 2);  
  191.                   
  192.                 ImageView imageView = new ImageView(mContext);  
  193.                 imageView.setImageResource(menuResIds[i]);  
  194.                 addView(imageView);  
  195.                 LayoutParams params = (FrameLayout.LayoutParams)imageView.getLayoutParams();  
  196.                 params.width = LayoutParams.WRAP_CONTENT;  
  197.                 params.height = LayoutParams.WRAP_CONTENT;            
  198.                 params.leftMargin = mWIDTH / 2 - ((menuResIds.length - i - 1) * width_padding);  
  199.                 params.bottomMargin = mHEIGHT / 2 - i * height_padding;  
  200.                 params.gravity = Gravity.LEFT | Gravity.BOTTOM;  
  201.                 imageView.setLayoutParams(params);                        
  202.             }  
  203.             break;  
  204.         default:  
  205.                 break;  
  206.         }     
  207.           
  208.         mHome.setLayoutParams(mHomeparams);       
  209.     }  
  210.       
  211.     private OnClickListener listener = new OnClickListener() {  
  212.           
  213.         public void onClick(View v) {  
  214.             if (!bMenuShow) {  
  215.                 startAnimationIn(PathMenuView.this300);  
  216.             } else {  
  217.                 startAnimationOut(PathMenuView.this300);  
  218.             }  
  219.             bMenuShow = !bMenuShow;  
  220.         }  
  221.     };  
  222.       
  223.       
  224.     /** 
  225.      * 菜单隐藏动画. 
  226.      *  
  227.      * @param group 
  228.      * @param duration 
  229.      */  
  230.     private void startAnimationIn(ViewGroup group, int duration) {  
  231.         for (int i = 1; i < group.getChildCount(); i++) {  
  232.             ImageView imageview = (ImageView) group.getChildAt(i);  
  233.             imageview.setVisibility(0);  
  234.             MarginLayoutParams mlp = (MarginLayoutParams) imageview  
  235.                     .getLayoutParams();  
  236.               
  237.               
  238.             Animation animation = null;  
  239.               
  240.               
  241.             switch (position) {  
  242.             case LEFT_TOP:  
  243.                 animation = new TranslateAnimation(0F,-mlp.leftMargin+xOffset,0F,-mlp.topMargin + yOffset);  
  244.                 break;  
  245.             case RIGHT_TOP:  
  246.                 animation = new TranslateAnimation(mlp.rightMargin - xOffset,0F,-mlp.topMargin + yOffset,0F);  
  247.                 break;            
  248.             case LEFT_BOTTOM:  
  249.                 animation = new TranslateAnimation(0F, -mlp.leftMargin+ xOffset, 0F, -yOffset + mlp.bottomMargin);  
  250.                 break;  
  251.                   
  252.             case RIGHT_BOTTOM:  
  253.                 animation = new TranslateAnimation(mlp.rightMargin-xOffset,0F,-yOffset + mlp.bottomMargin, 0F);  
  254.                 break;  
  255.             default:  
  256.                 break;  
  257.             }  
  258.   
  259.             animation.setFillAfter(true);  
  260.             animation.setDuration(duration);  
  261.             animation.setStartOffset((i * 100) / (-1 + group.getChildCount()));  
  262.             animation.setInterpolator(new OvershootInterpolator(2F));  
  263.             imageview.startAnimation(animation);  
  264.   
  265.         }  
  266.     }  
  267.       
  268.     /** 
  269.      * 菜单显示动画. 
  270.      *  
  271.      * @param group 
  272.      * @param duration 
  273.      */  
  274.     private void startAnimationOut(ViewGroup group,int duration){  
  275.         for (int i = 1; i < group.getChildCount(); i++) {  
  276.             final ImageView imageview = (ImageView) group  
  277.                     .getChildAt(i);  
  278.             MarginLayoutParams mlp = (MarginLayoutParams) imageview.getLayoutParams();  
  279.               
  280.             Animation animation = null;  
  281.               
  282.             switch (position) {  
  283.             case LEFT_TOP:  
  284.                 animation = new TranslateAnimation(-mlp.leftMargin+xOffset,0F,-mlp.topMargin + yOffset,0F);  
  285.                 break;  
  286.             case RIGHT_TOP:  
  287.                 animation = new TranslateAnimation(0F,mlp.rightMargin - xOffset,0F,-mlp.topMargin + yOffset);  
  288.                 break;  
  289.   
  290.             case LEFT_BOTTOM:  
  291.                 animation = new TranslateAnimation(-mlp.leftMargin+xOffset,0F, -yOffset + mlp.bottomMargin,0F);  
  292.                 break;  
  293.   
  294.             case RIGHT_BOTTOM:  
  295.                 animation = new TranslateAnimation(0F,mlp.rightMargin-xOffset, 0F,-yOffset + mlp.bottomMargin);  
  296.                 break;  
  297.             default:  
  298.                 break;  
  299.             }  
  300.               
  301.             animation.setFillAfter(true);animation.setDuration(duration);  
  302.             animation.setStartOffset(((group.getChildCount()-i) * 100)  
  303.                     / (-1 + group.getChildCount()));  
  304.             animation.setInterpolator(new AnticipateInterpolator(2F));  
  305.             imageview.startAnimation(animation);  
  306.         }  
  307.     }  
  308.   
  309. }  


第四步:PathTestActivity.java以及用到的布局文件main.xml代码如下:

 

PathTestActivity.java(基本没修改代码)代码如下:

 

[java] view plaincopy
 
  1. package com.tutor.path;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5.   
  6. public class PathTestActivity extends Activity {  
  7.   
  8.     @Override  
  9.     public void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.main);     
  12.     }  
  13. }  


main.xml代码如下:

 

 

[java] view plaincopy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:tutor="http://schemas.android.com/apk/res/com.tutor.path"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <com.tutor.path.PathMenuView  
  9.         android:id="@+id/text"  
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="fill_parent"  
  12.         tutor:position="right_bottom"  
  13.          />  
  14.   
  15. </LinearLayout>  


运行点击效果如下:

 

     

  图1:默认是在右下方这里menuResIds定义了五个菜单                图2:点击红色菜单,菜单收回.

 

下面我们修改main.xml的tutor属性为left_bottom,并且修改PathMenuView.java中的menuResIds.

 

[java] view plaincopy
 
  1. tutor:position="left_bottom"  


效果如下:

 

图3:自定义在左下角,六个菜单。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics