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

Hi~大家好,出来创业快3个月了,一切还不错,前一段时间用了业余时间搞了个问答类网站YQMA.想做中国的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 androidcontentContext;
import androidcontentresTypedArray;
import androidutilAttributeSet;
import androidviewGravity;
import androidviewView;
import androidviewViewGroup;
import androidviewanimationAnimation;
import androidviewanimationAnticipateInterpolator;
import androidviewanimationOvershootInterpolator;
import androidviewanimationTranslateAnimation;
import androidwidgetFrameLayout;
import androidwidgetImageView; 

/**
 * @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 = {Rdrawablecomposer_camera,Rdrawablecomposer_music,
      Rdrawablecomposer_sleep,Rdrawablecomposer_music,Rdrawablecomposer_place}; 

  public PathMenuView(Context context){
    super(context);
    setupViews();
  } 

  public PathMenuView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = contextobtainStyledAttributes(attrs,
        RstyleablePathMenuView); 

    position = agetInt(RstyleablePathMenuView_position,3); 

    arecycle();
    setupViews();
  } 

  private void setupViews(){
    mContext = getContext(); 

    mHEIGHT = mContextgetResources()getDisplayMetrics()heightPixels;
    mWIDTH = mContextgetResources()getDisplayMetrics()widthPixels;
    mDensity = mContextgetResources()getDisplayMetrics()density; 

    xOffset = (int) (667 * mDensity);
    yOffset = (int) (667 * mDensity); 

    mHome = new ImageView(mContext); 

    mHomesetImageResource(Rdrawablecomposer_button);
    mHomesetOnClickListener(listener); 

    addView(mHome); 

    LayoutParams mHomeparams = (FrameLayoutLayoutParams)mHomegetLayoutParams();
    mHomeparamswidth = LayoutParamsWRAP_CONTENT;
    mHomeparamsheight = LayoutParamsWRAP_CONTENT; 

    switch (position) {
    case LEFT_TOP:
      mHomeparamsgravity = GravityLEFT | GravityTOP;
      for (int i = 0; i < menuResIdslength; i++) { 

        int width_padding = mWIDTH / ((menuResIdslength - 1) * 2);
        int height_padding = mHEIGHT / ((menuResIdslength - 1) * 2); 

        ImageView imageView = new ImageView(mContext);
        imageViewsetImageResource(menuResIds[i]);
        addView(imageView);
        LayoutParams params = (FrameLayoutLayoutParams) imageView
            getLayoutParams();
        paramswidth = LayoutParamsWRAP_CONTENT;
        paramsheight = LayoutParamsWRAP_CONTENT;
        paramsleftMargin = mWIDTH / 2
            - ((menuResIdslength - i - 1) * width_padding);
        paramstopMargin = mHEIGHT / 2 - i * height_padding;
        paramsgravity = GravityLEFT | GravityTOP;
        imageViewsetLayoutParams(params); 

      } 

      break;
    case RIGHT_TOP:
      mHomeparamsgravity = GravityRIGHT | GravityTOP;
      for (int i = 0; i < menuResIdslength; i++) { 

        int width_padding = mWIDTH / ((menuResIdslength - 1) * 2);
        int height_padding = mHEIGHT / ((menuResIdslength - 1) * 2); 

        ImageView imageView = new ImageView(mContext);
        imageViewsetImageResource(menuResIds[i]);
        addView(imageView);
        LayoutParams params = (FrameLayoutLayoutParams) imageView
            getLayoutParams();
        paramswidth = LayoutParamsWRAP_CONTENT;
        paramsheight = LayoutParamsWRAP_CONTENT;
        paramsrightMargin = mWIDTH / 2
            - ((menuResIdslength - i - 1) * width_padding);
        paramstopMargin = mHEIGHT / 2 - i * height_padding;
        paramsgravity = GravityRIGHT | GravityTOP;
        imageViewsetLayoutParams(params); 

      }
      break;
    case RIGHT_BOTTOM:
      mHomeparamsgravity = GravityRIGHT | GravityBOTTOM;
      for (int i = 0; i < menuResIdslength; i++) { 

        int width_padding = mWIDTH / ((menuResIdslength - 1) * 2);
        int height_padding = mHEIGHT / ((menuResIdslength - 1) * 2); 

        ImageView imageView = new ImageView(mContext);
        imageViewsetImageResource(menuResIds[i]);
        addView(imageView);
        LayoutParams params = (FrameLayoutLayoutParams) imageView
            getLayoutParams();
        paramswidth = LayoutParamsWRAP_CONTENT;
        paramsheight = LayoutParamsWRAP_CONTENT;
        paramsrightMargin = mWIDTH / 2
            - ((menuResIdslength - i - 1) * width_padding);
        paramsbottomMargin = mHEIGHT / 2 - i * height_padding;
        paramsgravity = GravityRIGHT | GravityBOTTOM;
        imageViewsetLayoutParams(params); 

      }
      break;
    case LEFT_BOTTOM:
      mHomeparamsgravity = GravityLEFT | GravityBOTTOM;
      for(int i = 0; i < menuResIdslength; i++){ 

        int width_padding = mWIDTH / ((menuResIdslength - 1) * 2);
        int height_padding = mHEIGHT / ((menuResIdslength -1) * 2); 

        ImageView imageView = new ImageView(mContext);
        imageViewsetImageResource(menuResIds[i]);
        addView(imageView);
        LayoutParams params = (FrameLayoutLayoutParams)imageViewgetLayoutParams();
        paramswidth = LayoutParamsWRAP_CONTENT;
        paramsheight = LayoutParamsWRAP_CONTENT;
        paramsleftMargin = mWIDTH / 2 - ((menuResIdslength - i - 1) * width_padding);
        paramsbottomMargin = mHEIGHT / 2 - i * height_padding;
        paramsgravity = GravityLEFT | GravityBOTTOM;
        imageViewsetLayoutParams(params);
      }
      break;
    default:
        break;
    }   

    mHomesetLayoutParams(mHomeparams);
  } 

  private OnClickListener listener = new OnClickListener() { 

    public void onClick(View v) {
      if (!bMenuShow) {
        startAnimationIn(PathMenuViewthis, 300);
      } else {
        startAnimationOut(PathMenuViewthis, 300);
      }
      bMenuShow = !bMenuShow;
    }
  }; 

  /**
   * 菜单隐藏动画
   *
   * @param group
   * @param duration
   */
  private void startAnimationIn(ViewGroup group, int duration) {
    for (int i = 1; i < groupgetChildCount(); i++) {
      ImageView imageview = (ImageView) groupgetChildAt(i);
      imageviewsetVisibility(0);
      MarginLayoutParams mlp = (MarginLayoutParams) imageview
          getLayoutParams(); 

      Animation animation = null; 

      switch (position) {
      case LEFT_TOP:
        animation = new TranslateAnimation(0F,-mlpleftMargin+xOffset,0F,-mlptopMargin + yOffset);
        break;
      case RIGHT_TOP:
        animation = new TranslateAnimation(mlprightMargin - xOffset,0F,-mlptopMargin + yOffset,0F);
        break;
      case LEFT_BOTTOM:
        animation = new TranslateAnimation(0F, -mlpleftMargin+ xOffset, 0F, -yOffset + mlpbottomMargin);
        break; 

      case RIGHT_BOTTOM:
        animation = new TranslateAnimation(mlprightMargin-xOffset,0F,-yOffset + mlpbottomMargin, 0F);
        break;
      default:
        break;
      } 

      animationsetFillAfter(true);
      animationsetDuration(duration);
      animationsetStartOffset((i * 100) / (-1 + groupgetChildCount()));
      animationsetInterpolator(new OvershootInterpolator(2F));
      imageviewstartAnimation(animation); 

    }
  } 

  /**
   * 菜单显示动画
   *
   * @param group
   * @param duration
   */
  private void startAnimationOut(ViewGroup group,int duration){
    for (int i = 1; i < groupgetChildCount(); i++) {
      final ImageView imageview = (ImageView) group
          getChildAt(i);
      MarginLayoutParams mlp = (MarginLayoutParams) imageviewgetLayoutParams(); 

      Animation animation = null; 

      switch (position) {
      case LEFT_TOP:
        animation = new TranslateAnimation(-mlpleftMargin+xOffset,0F,-mlptopMargin + yOffset,0F);
        break;
      case RIGHT_TOP:
        animation = new TranslateAnimation(0F,mlprightMargin - xOffset,0F,-mlptopMargin + yOffset);
        break; 

      case LEFT_BOTTOM:
        animation = new TranslateAnimation(-mlpleftMargin+xOffset,0F, -yOffset + mlpbottomMargin,0F);
        break; 

      case RIGHT_BOTTOM:
        animation = new TranslateAnimation(0F,mlprightMargin-xOffset, 0F,-yOffset + mlpbottomMargin);
        break;
      default:
        break;
      } 

      animationsetFillAfter(true);animationsetDuration(duration);
      animationsetStartOffset(((groupgetChildCount()-i) * 100)
          / (-1 + groupgetChildCount()));
      animationsetInterpolator(new AnticipateInterpolator(2F));
      imageviewstartAnimation(animation);
    }
  } 

} 

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

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

package comtutorpath; 

import androidappActivity;
import androidosBundle; 

public class PathTestActivity extends Activity { 

  @Override
  public void onCreate(Bundle savedInstanceState) {
    superonCreate(savedInstanceState);
    setContentView(Rlayoutmain);
  }
} 

main.xml代码如下:

<?xml version="0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemasandroidcom/apk/res/android"
  xmlns:tutor="http://schemasandroidcom/apk/res/comtutorpath"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical" > 

  <comtutorpathPathMenuView
    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:自定义在左下角,六个菜单。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, 仿path菜单
, path菜单
path半圆菜单
qq飞车高手进阶区、qq飞车论坛高手进阶区、android开发高手进阶、os x 高手进阶 v3 pdf、亚索攻略 高手进阶,以便于您获取更多的相关知识。

时间: 2024-09-09 13:50:06

Android高手进阶教程(二十六)之---Android超仿Path菜单的功能实现!_Android的相关文章

Android高手进阶教程(二十二)之Android中几种图像特效处理的集锦汇总!!_Android

大家好,这一节给大家分享的是Android中几种图像特效处理的小技巧,比如圆角,倒影,还有就是图片缩放,Drawable转化为Bitmap,Bitmap转化为Drawable等等. 废话少说了,直接讲解今天的实例,本例主要是先获取壁纸(getWallpaper()),然后对当前壁纸的一些特效处理.大家按步骤一步一步来: 第一步:新建一个Android工程命名为ImageDemo,工程结构如下: 第二步:新建一个.Java文件,命名为ImageUtil.java,在里面定义一些图片处理方法,代码如

Android简明开发教程二十二:使用资源Resources

在前面的例子中,我们忽略了一个重要的原则,在代码和Layout中,直接使用了字符串常量,比如: <Button android:text="Pattern" android:id="@+id/btnPattern" android:layout_width="wrap_content" android:textColor="@color/black" android:checked="true" an

Android简明开发教程二十四:总结及示例代码下载

Android 简明开发教程使用了引路蜂二维图形库作为例子,引路蜂二维图形库是引路蜂地图开发包 (http://www.imobilebbs.com/wordpress/?page_id=6)一部分,引路蜂地图开发包提供了对几乎所有软件平台(桌面和移动平台 )的支持,采用统一的接口使用包括Google 地图,Bing地图,MapABC地图在内多达二十多种地图类型,并在同一开发包中支持离 线地图,矢量地图显示. 引路蜂地图开发包Android平台示例可以参见:http://www.imobileb

Android简明开发教程二十:Broadcast Receiver短信触发示例

Android 中BroadCast Receiver可以用来侦听广播事件.在使用Broadcast 之前,必须使用代码或是在AndroidManifest.xml 进行注册. 下面的例子实现使用短信来触发AndroidGraphics2DTutorial中的示例.短信格式为:@demo:xxxx ,xxxx为 示例名称,比如 , 启动Colors示例, 则向手机发送: @demo:Colors . 手机在收到短信后,先检测短信格式是否符合 @demo:xxxx, 若符合, 这启动对应的示例.

仿酷狗音乐播放器开发日志二十六 duilib在标题栏弹出菜单的方法

转载请说明原出处,谢谢~~        上篇日志说明了怎么让自定义控件响应右键消息.之后我给主窗体的标题栏增加右键响应,观察原酷狗后可以发现,在整个标题栏都是可以响应右键并弹出菜单的.应该的效果如下:        本以为像上一片博客那样,处理标题栏的布局的右键消息就可以了.后来发现在duilib的标题栏中无法像在客户区那样自如响应UIEVENT_CONTEXTMENU消息的.所以还得用另外的方法.       在非客户区处理右击消息对应的是WM_NCRBUTTONUP,WM_NCRBUTTO

C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(二十六)

C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(二十六)通用型角色头像面板 目前游戏的开发进度已经基本实现了精灵对象之间的普通交互,接下来我们需要朝着实现战斗系统的目标前行.而实现它的前提是必须完善精灵控件的基本属性,如添加生命值.魔法值.活力值.经验值等基本属性并通过窗体界面进行完美体现,本节我将为大家讲解上述内容的具体实现. 既然是为精灵添加属性,大家首先想到的当然是为精灵控件加入属性值索引器: /// <summary> /// 生命值,[0]-当前

Bootstrap &lt;基础二十六&gt;进度条

原文:Bootstrap <基础二十六>进度条 Bootstrap 进度条.在本教程中,你将看到如何使用 Bootstrap 创建加载.重定向或动作状态的进度条. Bootstrap 进度条使用 CSS3 过渡和动画来获得该效果.Internet Explorer 9 及之前的版本和旧版的 Firefox 不支持该特性,Opera 12 不支持动画. 默认的进度条 创建一个基本的进度条的步骤如下: 添加一个带有 class .progress 的 <div>. 接着,在上面的 &l

二十六步获得网站流量

原文标题:The A to Z Guide to Getting Website Traffic 原文作者:Shawn Campbell 原文地址:http://www.sitepronews.com/archives/2006/apr/12.html 这是孙波翻译的一篇文章,主要讲的是英文网站开发的文章,大部分内容对于中文内容的网站也有指导意义,供参考.转载本文请保留原文出处和作者以及翻译作者信息.以下是译文. 二十六步获得网站流量 1999年9月的时候,Brett Tabke在Webmast

微信小程序把玩(二十六)navigator组件

原文:微信小程序把玩(二十六)navigator组件 navigator跳转分为两个状态一种是关闭当前页面一种是不关闭当前页面.用redirect属性指定. 主要属性: wxml <navigator url="../index/index">点击跳转不关闭当前页面</navigator> <navigator url="../logs/logs" redirect="true" >点击跳转关闭当前页面<