Android Path菜单的简单实现

文章详细描述了一个名为PathMenuView的自定义视图组件,它可以根据预设位置动态展示或隐藏菜单,通过ImageView和动画实现菜单的左上、右上、右下和左下四种布局方式。
摘要由CSDN通过智能技术生成
  1. */

  2. private boolean bMenuShow;

  3. private static int  xOffset     = 15;

  4. private static int  yOffset     = -13;

  5. /**

  6. * 菜单的资源个数.

  7. */

  8. private int[] menuResIds = {R.drawable.composer_camera,R.drawable.composer_music,

  9. R.drawable.composer_sleep,R.drawable.composer_music,R.drawable.composer_place};

  10. public PathMenuView(Context context){

  11. super(context);

  12. setupViews();

  13. }

  14. public PathMenuView(Context context, AttributeSet attrs) {

  15. super(context, attrs);

  16. TypedArray a = context.obtainStyledAttributes(attrs,

  17. R.styleable.PathMenuView);

  18. position = a.getInt(R.styleable.PathMenuView_position,3);

  19. a.recycle();

  20. setupViews();

  21. }

  22. private void setupViews(){

  23. mContext = getContext();

  24. mHEIGHT = mContext.getResources().getDisplayMetrics().heightPixels;

  25. mWIDTH = mContext.getResources().getDisplayMetrics().widthPixels;

  26. mDensity = mContext.getResources().getDisplayMetrics().density;

  27. xOffset = (int) (10.667 * mDensity);

  28. yOffset = (int) (8.667 * mDensity);

  29. mHome = new ImageView(mContext);

  30. mHome.setImageResource(R.drawable.composer_button);

  31. mHome.setOnClickListener(listener);

  32. addView(mHome);

  33. LayoutParams mHomeparams = (FrameLayout.LayoutParams)mHome.getLayoutParams();

  34. mHomeparams.width = LayoutParams.WRAP_CONTENT;

  35. mHomeparams.height = LayoutParams.WRAP_CONTENT;

  36. switch (position) {

  37. case LEFT_TOP:

  38. mHomeparams.gravity = Gravity.LEFT | Gravity.TOP;

  39. for (int i = 0; i < menuResIds.length; i++) {

  40. int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);

  41. int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2);

  42. ImageView imageView = new ImageView(mContext);

  43. imageView.setImageResource(menuResIds[i]);

  44. addView(imageView);

  45. LayoutParams params = (FrameLayout.LayoutParams) imageView

  46. .getLayoutParams();

  47. params.width = LayoutParams.WRAP_CONTENT;

  48. params.height = LayoutParams.WRAP_CONTENT;

  49. params.leftMargin = mWIDTH / 2

  50. - ((menuResIds.length - i - 1) * width_padding);

  51. params.topMargin = mHEIGHT / 2 - i * height_padding;

  52. params.gravity = Gravity.LEFT | Gravity.TOP;

  53. imageView.setLayoutParams(params);

  54. }

  55. break;

  56. case RIGHT_TOP:

  57. mHomeparams.gravity = Gravity.RIGHT | Gravity.TOP;

  58. for (int i = 0; i < menuResIds.length; i++) {

  59. int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);

  60. int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2);

  61. ImageView imageView = new ImageView(mContext);

  62. imageView.setImageResource(menuResIds[i]);

  63. addView(imageView);

  64. LayoutParams params = (FrameLayout.LayoutParams) imageView

  65. .getLayoutParams();

  66. params.width = LayoutParams.WRAP_CONTENT;

  67. params.height = LayoutParams.WRAP_CONTENT;

  68. params.rightMargin = mWIDTH / 2

  69. - ((menuResIds.length - i - 1) * width_padding);

  70. params.topMargin = mHEIGHT / 2 - i * height_padding;

  71. params.gravity = Gravity.RIGHT | Gravity.TOP;

  72. imageView.setLayoutParams(params);

  73. }

  74. break;

  75. case RIGHT_BOTTOM:

  76. mHomeparams.gravity = Gravity.RIGHT | Gravity.BOTTOM;

  77. for (int i = 0; i < menuResIds.length; i++) {

  78. int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);

  79. int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2);

  80. ImageView imageView = new ImageView(mContext);

  81. imageView.setImageResource(menuResIds[i]);

  82. addView(imageView);

  83. LayoutParams params = (FrameLayout.LayoutParams) imageView

  84. .getLayoutParams();

  85. params.width = LayoutParams.WRAP_CONTENT;

  86. params.height = LayoutParams.WRAP_CONTENT;

  87. params.rightMargin = mWIDTH / 2

  88. - ((menuResIds.length - i - 1) * width_padding);

  89. params.bottomMargin = mHEIGHT / 2 - i * height_padding;

  90. params.gravity = Gravity.RIGHT | Gravity.BOTTOM;

  91. imageView.setLayoutParams(params);

  92. }

  93. break;

  94. case LEFT_BOTTOM:

  95. mHomeparams.gravity = Gravity.LEFT | Gravity.BOTTOM;

  96. for(int i = 0; i < menuResIds.length; i++){

  97. int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);

  98. int height_padding = mHEIGHT / ((menuResIds.length -1) * 2);

  99. ImageView imageView = new ImageView(mContext);

  100. imageView.setImageResource(menuResIds[i]);

  101. addView(imageView);

  102. LayoutParams params = (FrameLayout.LayoutParams)imageView.getLayoutParams();

  103. params.width = LayoutParams.WRAP_CONTENT;

  104. params.height = LayoutParams.WRAP_CONTENT;

  105. params.leftMargin = mWIDTH / 2 - ((menuResIds.length - i - 1) * width_padding);

  106. params.bottomMargin = mHEIGHT / 2 - i * height_padding;

  107. params.gravity = Gravity.LEFT | Gravity.BOTTOM;

  108. imageView.setLayoutParams(params);

  109. }

  110. break;

  111. default:

  112. break;

  113. }

  114. mHome.setLayoutParams(mHomeparams);

  115. }

  116. private OnClickListener listener = new OnClickListener() {

  117. public void onClick(View v) {

  118. if (!bMenuShow) {

  119. startAnimationIn(PathMenuView.this, 300);

  120. } else {

  121. startAnimationOut(PathMenuView.this, 300);

  122. }

  123. bMenuShow = !bMenuShow;

  124. }

  125. };

  126. /**

  127. * 菜单隐藏动画.

  128. *

  129. * @param group

  130. * @param duration

  131. */

  132. private void startAnimationIn(ViewGroup group, int duration) {

  133. for (int i = 1; i < group.getChildCount(); i++) {

  134. ImageView imageview = (ImageView) group.getChildAt(i);

  135. imageview.setVisibility(0);

  136. MarginLayoutParams mlp = (MarginLayoutParams) imageview

  137. .getLayoutParams();

  138. Animation animation = null;

  139. switch (position) {

  140. case LEFT_TOP:

  141. animation = new TranslateAnimation(0F,-mlp.leftMargin+xOffset,0F,-mlp.topMargin + yOffset);

  142. break;

  143. case RIGHT_TOP:

  144. animation = new TranslateAnimation(mlp.rightMargin - xOffset,0F,-mlp.topMargin + yOffset,0F);

  145. break;

  146. case LEFT_BOTTOM:

  147. animation = new TranslateAnimation(0F, -mlp.leftMargin+ xOffset, 0F, -yOffset + mlp.bottomMargin);

  148. break;

  149. case RIGHT_BOTTOM:

  150. animation = new TranslateAnimation(mlp.rightMargin-xOffset,0F,-yOffset + mlp.bottomMargin, 0F);

  151. break;

  152. default:

  153. break;

  154. }

  155. animation.setFillAfter(true);

  156. animation.setDuration(duration);

  157. animation.setStartOffset((i * 100) / (-1 + group.getChildCount()));

  158. animation.setInterpolator(new OvershootInterpolator(2F));

  159. imageview.startAnimation(animation);

  160. }

  161. }

  162. /**

  163. * 菜单显示动画.

  164. *

  165. * @param group

  166. * @param duration

  167. */

  168. private void startAnimationOut(ViewGroup group,int duration){

  169. for (int i = 1; i < group.getChildCount(); i++) {

  170. final ImageView imageview = (ImageView) group

  171. .getChildAt(i);

  172. MarginLayoutParams mlp = (MarginLayoutParams) imageview.getLayoutParams();

  173. Animation animation = null;

  174. switch (position) {

  175. case LEFT_TOP:

  176. animation = new TranslateAnimation(-mlp.leftMargin+xOffset,0F,-mlp.topMargin + yOffset,0F);

  177. break;

  178. case RIGHT_TOP:

  179. animation = new TranslateAnimation(0F,mlp.rightMargin - xOffset,0F,-mlp.topMargin + yOffset);

  180. break;

  181. case LEFT_BOTTOM:

  182. animation = new TranslateAnimation(-mlp.leftMargin+xOffset,0F, -yOffset + mlp.bottomMargin,0F);

  183. break;

  184. case RIGHT_BOTTOM:

  185. animation = new TranslateAnimation(0F,mlp.rightMargin-xOffset, 0F,-yOffset + mlp.bottomMargin);

  186. break;

  187. default:

  188. break;

  189. }

  190. animation.setFillAfter(true);animation.setDuration(duration);

  191. animation.setStartOffset(((group.getChildCount()-i) * 100)

  192. / (-1 + group.getChildCount()));

  193. animation.setInterpolator(new AnticipateInterpolator(2F));

  194. imageview.startAnimation(animation);

  195. }

  196. }

  197. }

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

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

[java]  view plain copy

  1. package com.tutor.path;

  2. import android.app.Activity;

  3. import android.os.Bundle;

  4. public class PathTestActivity extends Activity {

  5. @Override

  6. public void onCreate(Bundle savedInstanceState) {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

尾声

开发是需要一定的基础的,我是08年开始进入Android这行的,在这期间经历了Android的鼎盛时期,和所谓的Android”凉了“。中间当然也有着,不可说的心酸,看着身边朋友,同事一个个转前端,换行业,其实当时我的心也有过犹豫,但是我还是坚持下来了,这次的疫情就是一个好的机会,大浪淘沙,优胜劣汰。再等等,说不定下一个黄金浪潮就被你等到了。

  • 330页 PDF Android核心笔记

  • 几十套阿里 、字节跳动、腾讯、华为、美团等公司2020年的面试题

  • PDF和思维脑图,包含知识脉络 + 诸多细节

  • Android进阶系统学习视频

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

一个个转前端,换行业,其实当时我的心也有过犹豫,但是我还是坚持下来了,这次的疫情就是一个好的机会,大浪淘沙,优胜劣汰。再等等,说不定下一个黄金浪潮就被你等到了。

  • 330页 PDF Android核心笔记

[外链图片转存中…(img-1WG8PjVd-1712500173502)]

  • 几十套阿里 、字节跳动、腾讯、华为、美团等公司2020年的面试题

[外链图片转存中…(img-qHKfEAOH-1712500173503)]

[外链图片转存中…(img-i2XyxZpD-1712500173503)]

  • PDF和思维脑图,包含知识脉络 + 诸多细节

[外链图片转存中…(img-LRwEb199-1712500173503)]

  • Android进阶系统学习视频

[外链图片转存中…(img-lnyR1l9p-1712500173503)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值