文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2022-06-06 05:45

关注

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; 
 
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; 
   
  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; 
    } 
  }; 
   
  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); 
    } 
  } 
   
  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自定义View系列之Path绘制仿支付宝支付成功动画Android通过Path实现搜索按钮和时钟复杂效果Android Path绘制贝塞尔曲线实现QQ拖拽泡泡Android编程开发之在Canvas中利用Path绘制基本图形(圆形,矩形,椭圆,三角形等)Android 开发实例简单涂鸦板Android编程实现在Bitmap上涂鸦效果Android 使用Path实现涂鸦功能


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯