Android高手进阶教程(二十六)之---Android超仿Path菜单的实现!

Hi~大家好,出来创业快3个月了,一切还不错,前一段时间用了业余时间搞了个问答类网站YQMA(http://yqma.net).想做中国的stackoverflow,哈哈,只是YY下,希望大家多多支持!

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

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

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



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

<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="PathMenuView"> <attr name="position"> <enum name="left_top" value="0"></enum> <enum name="right_top" value="1"></enum> <enum name="right_bottom" value="2"></enum> <enum name="left_bottom" value="3"></enum> </attr> </declare-styleable> </resources>

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

package com.tutor.path; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnticipateInterpolator; import android.view.animation.OvershootInterpolator; import android.view.animation.TranslateAnimation; import android.widget.FrameLayout; import android.widget.ImageView; /** * @author frankiewei. * 超级仿path菜单 * position定义菜单的位置,目前支持:左上;右上;右下;左下四个方向。 * menuResIds定义出现的菜单的资源ID */ public class PathMenuView extends FrameLayout { private static final int LEFT_TOP = 0; private static final int RIGHT_TOP = 1; private static final int RIGHT_BOTTOM = 2; private static final int LEFT_BOTTOM = 3; /** * 默认的位置是在右下角. */ private int position = 3; /** * 那个圆形菜单. */ private ImageView mHome; /** * 上下文. */ private Context mContext; /** * 设备的宽度. */ private int mWIDTH = 0; /** * 设备的高度. */ private int mHEIGHT = 0; /** * 设备的density. */ private float mDensity; /** * 菜单是否显示. */ private boolean bMenuShow; private static int xOffset = 15; private static int yOffset = -13; /** * 菜单的资源个数. */ private int[] menuResIds = {R.drawable.composer_camera,R.drawable.composer_music, R.drawable.composer_sleep,R.drawable.composer_music,R.drawable.composer_place}; public PathMenuView(Context context){ super(context); setupViews(); } public PathMenuView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PathMenuView); position = a.getInt(R.styleable.PathMenuView_position,3); a.recycle(); setupViews(); } private void setupViews(){ mContext = getContext(); mHEIGHT = mContext.getResources().getDisplayMetrics().heightPixels; mWIDTH = mContext.getResources().getDisplayMetrics().widthPixels; mDensity = mContext.getResources().getDisplayMetrics().density; xOffset = (int) (10.667 * mDensity); yOffset = (int) (8.667 * mDensity); mHome = new ImageView(mContext); mHome.setImageResource(R.drawable.composer_button); mHome.setOnClickListener(listener); addView(mHome); LayoutParams mHomeparams = (FrameLayout.LayoutParams)mHome.getLayoutParams(); mHomeparams.width = LayoutParams.WRAP_CONTENT; mHomeparams.height = LayoutParams.WRAP_CONTENT; switch (position) { case LEFT_TOP: mHomeparams.gravity = Gravity.LEFT | Gravity.TOP; for (int i = 0; i < menuResIds.length; i++) { int width_padding = mWIDTH / ((menuResIds.length - 1) * 2); int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2); ImageView imageView = new ImageView(mContext); imageView.setImageResource(menuResIds[i]); addView(imageView); LayoutParams params = (FrameLayout.LayoutParams) imageView .getLayoutParams(); params.width = LayoutParams.WRAP_CONTENT; params.height = LayoutParams.WRAP_CONTENT; params.leftMargin = mWIDTH / 2 - ((menuResIds.length - i - 1) * width_padding); params.topMargin = mHEIGHT / 2 - i * height_padding; params.gravity = Gravity.LEFT | Gravity.TOP; imageView.setLayoutParams(params); } break; case RIGHT_TOP: mHomeparams.gravity = Gravity.RIGHT | Gravity.TOP; for (int i = 0; i < menuResIds.length; i++) { int width_padding = mWIDTH / ((menuResIds.length - 1) * 2); int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2); ImageView imageView = new ImageView(mContext); imageView.setImageResource(menuResIds[i]); addView(imageView); LayoutParams params = (FrameLayout.LayoutParams) imageView .getLayoutParams(); params.width = LayoutParams.WRAP_CONTENT; params.height = LayoutParams.WRAP_CONTENT; params.rightMargin = mWIDTH / 2 - ((menuResIds.length - i - 1) * width_padding); params.topMargin = mHEIGHT / 2 - i * height_padding; params.gravity = Gravity.RIGHT | Gravity.TOP; imageView.setLayoutParams(params); } break; case RIGHT_BOTTOM: mHomeparams.gravity = Gravity.RIGHT | Gravity.BOTTOM; for (int i = 0; i < menuResIds.length; i++) { int width_padding = mWIDTH / ((menuResIds.length - 1) * 2); int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2); ImageView imageView = new ImageView(mContext); imageView.setImageResource(menuResIds[i]); addView(imageView); LayoutParams params = (FrameLayout.LayoutParams) imageView .getLayoutParams(); params.width = LayoutParams.WRAP_CONTENT; params.height = LayoutParams.WRAP_CONTENT; params.rightMargin = mWIDTH / 2 - ((menuResIds.length - i - 1) * width_padding); params.bottomMargin = mHEIGHT / 2 - i * height_padding; params.gravity = Gravity.RIGHT | Gravity.BOTTOM; imageView.setLayoutParams(params); } break; case LEFT_BOTTOM: mHomeparams.gravity = Gravity.LEFT | Gravity.BOTTOM; for(int i = 0; i < menuResIds.length; i++){ int width_padding = mWIDTH / ((menuResIds.length - 1) * 2); int height_padding = mHEIGHT / ((menuResIds.length -1) * 2); ImageView imageView = new ImageView(mContext); imageView.setImageResource(menuResIds[i]); addView(imageView); LayoutParams params = (FrameLayout.LayoutParams)imageView.getLayoutParams(); params.width = LayoutParams.WRAP_CONTENT; params.height = LayoutParams.WRAP_CONTENT; params.leftMargin = mWIDTH / 2 - ((menuResIds.length - i - 1) * width_padding); params.bottomMargin = mHEIGHT / 2 - i * height_padding; params.gravity = Gravity.LEFT | Gravity.BOTTOM; imageView.setLayoutParams(params); } break; default: break; } mHome.setLayoutParams(mHomeparams); } private OnClickListener listener = new OnClickListener() { public void onClick(View v) { if (!bMenuShow) { startAnimationIn(PathMenuView.this, 300); } else { startAnimationOut(PathMenuView.this, 300); } bMenuShow = !bMenuShow; } }; /** * 菜单隐藏动画. * * @param group * @param duration */ private void startAnimationIn(ViewGroup group, int duration) { for (int i = 1; i < group.getChildCount(); i++) { ImageView imageview = (ImageView) group.getChildAt(i); imageview.setVisibility(0); MarginLayoutParams mlp = (MarginLayoutParams) imageview .getLayoutParams(); Animation animation = null; switch (position) { case LEFT_TOP: animation = new TranslateAnimation(0F,-mlp.leftMargin+xOffset,0F,-mlp.topMargin + yOffset); break; case RIGHT_TOP: animation = new TranslateAnimation(mlp.rightMargin - xOffset,0F,-mlp.topMargin + yOffset,0F); break; case LEFT_BOTTOM: animation = new TranslateAnimation(0F, -mlp.leftMargin+ xOffset, 0F, -yOffset + mlp.bottomMargin); break; case RIGHT_BOTTOM: animation = new TranslateAnimation(mlp.rightMargin-xOffset,0F,-yOffset + mlp.bottomMargin, 0F); break; default: break; } animation.setFillAfter(true); animation.setDuration(duration); animation.setStartOffset((i * 100) / (-1 + group.getChildCount())); animation.setInterpolator(new OvershootInterpolator(2F)); imageview.startAnimation(animation); } } /** * 菜单显示动画. * * @param group * @param duration */ private void startAnimationOut(ViewGroup group,int duration){ for (int i = 1; i < group.getChildCount(); i++) { final ImageView imageview = (ImageView) group .getChildAt(i); MarginLayoutParams mlp = (MarginLayoutParams) imageview.getLayoutParams(); Animation animation = null; switch (position) { case LEFT_TOP: animation = new TranslateAnimation(-mlp.leftMargin+xOffset,0F,-mlp.topMargin + yOffset,0F); break; case RIGHT_TOP: animation = new TranslateAnimation(0F,mlp.rightMargin - xOffset,0F,-mlp.topMargin + yOffset); break; case LEFT_BOTTOM: animation = new TranslateAnimation(-mlp.leftMargin+xOffset,0F, -yOffset + mlp.bottomMargin,0F); break; case RIGHT_BOTTOM: animation = new TranslateAnimation(0F,mlp.rightMargin-xOffset, 0F,-yOffset + mlp.bottomMargin); break; default: break; } animation.setFillAfter(true);animation.setDuration(duration); animation.setStartOffset(((group.getChildCount()-i) * 100) / (-1 + group.getChildCount())); animation.setInterpolator(new AnticipateInterpolator(2F)); imageview.startAnimation(animation); } } }
第四步:PathTestActivity.java以及用到的布局文件main.xml代码如下:

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

package com.tutor.path; import android.app.Activity; import android.os.Bundle; public class PathTestActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } }
main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tutor="http://schemas.android.com/apk/res/com.tutor.path" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <com.tutor.path.PathMenuView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="fill_parent" tutor:position="right_bottom" /> </LinearLayout>
运行点击效果如下:


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


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

tutor:position="left_bottom"
效果如下:

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

好了,今天就讲到这里了,菜单的圆弧不是很圆哈,凑合着学习,我也来无耻下,如果想要源代码的,可以去我的http://www.yqma.net注册一个用户,并且提一个问题,或者回答一个问题,我会把源代码发到你的邮箱里!谢谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值