弧形菜单(Android)
弧形菜单(Android)
前言:公司需求,自己写的一个弧形菜单!
效果:

开发环境:AndroidStudio2.2.1+gradle-2.14.1
涉及知识:1.自定义控件,2.事件分发等
部分代码:
public class HomePageMenuLayout extends ViewGroup {
private Context context;
// 菜单项的文本
private String[] mItemTexts = null;
private int StatusHeight;//状态栏高度
public HomePageMenuLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
StatusHeight = ScreenUtils.getStatusHeight(context);
}
/**
* 设置布局的宽高,并策略menu item宽高
*/
int resWidth = 0;
int resHeight = 0;
int mRadius = 0;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//布局宽高尺寸设置为屏幕尺寸
//设置该布局的大小
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
/**
* 根据传入的参数,分别获取测量模式和测量值
*/
int width = MeasureSpec.getSize(widthMeasureSpec);
resHeight = MeasureSpec.getSize(heightMeasureSpec);
resWidth = MeasureSpec.getSize(widthMeasureSpec);
// 获得半径
mRadius = (int) (resHeight / 2 - 2 * StatusHeight);
//设置item尺寸
int childSize = (int) (mRadius * 1 / 2);
// menu item测量模式--精确模式
int childMode = MeasureSpec.EXACTLY;
for (int i = 0; i < getChildCount(); i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
// 计算menu item的尺寸;以及和设置好的模式,去对item进行测量
int makeMeasureSpec = -1;
makeMeasureSpec = MeasureSpec.makeMeasureSpec(childSize, childMode);
child.measure(makeMeasureSpec, makeMeasureSpec);
}
}
/**
* item布局的角度
*/
private int[] widthall = null;
/**
* 设置Item的位置:第一个参数1:该参数指出当前ViewGroup的尺寸或者位置是否发生了改变
* 2.当期绘图光标横坐标位置
* 3.当前绘图光标纵坐标位置
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left, top;
int cWidth = (int) (mRadius * 1 / 2);
final int childCount = getChildCount();
// 计算,中心点到menu item中心的距离
float tmp = mRadius - cWidth / 2;
// 遍历去设置menuitem的位置
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
left = (int) (mRadius * Math.cos(Math.toRadians(widthall[i]))) - 65;
top = (int) (mRadius - (resHeight / 2 - 2 * StatusHeight) * Math.sin(Math.toRadians(widthall[i])) - StatusHeight);
child.layout(left, top, left + cWidth, top + cWidth);
}
}
public interface OnMenuItemClickListener {
void itemClick(View view, int pos);
}
public void setOnMenuItemClickListener(
OnMenuItemClickListener mOnMenuItemClickListener) {
this.mOnMenuItemClickListener = mOnMenuItemClickListener;
}
// 菜单的个数
private int mMenuItemCount;
/**
* 设置菜单条目的图标和文本
*/
public void setMenuItemIconsAndTexts(String[] mItemTexts) {
this.mItemTexts = mItemTexts;
this.mMenuItemCount = mItemTexts.length;
resultAngle();
addMenuItems();
}
private void resultAngle() {
switch (this.mMenuItemCount) {
case 3:
widthall = Constants.ITEM3;
break;
case 4:
widthall = Constants.ITEM4;
break;
case 5:
widthall = Constants.ITEM5;
break;
case 6:
widthall = Constants.ITEM6;
break;
case 7:
widthall = Constants.ITEM7;
break;
case 8:
widthall = Constants.ITEM8;
break;
case 9:
widthall = Constants.ITEM9;
break;
case 10:
widthall = Constants.ITEM10;
break;
default:
break;
}
}
/**
* 设置菜单条目的图标和文本
*/
public void setMenuItemIconsAndTexts() {
addMenuItems();
}
private int mMenuItemLayoutId = R.layout.homepage_item_layout;
/**
* MenuItem的点击事件接口
*/
private OnMenuItemClickListener mOnMenuItemClickListener;
private float yPosition = 0;
/**
* 添加菜单项
*/
private void addMenuItems() {
LayoutInflater mInflater = LayoutInflater.from(getContext());
/**
* 根据用户设置的参数,初始化view
*/
for (int i = 0; i < mMenuItemCount; i++) {
final int j = i;
View view = mInflater.inflate(mMenuItemLayoutId, this, false);
final ImageView iv = (ImageView) view
.findViewById(R.id.homepage_pager1_item_img);
final TextView tv = (TextView) view
.findViewById(R.id.homepage_pager1_item_tv);
if (iv != null) {
iv.setImageResource(R.mipmap.menu_ture);
}
if (tv != null) {
tv.setText(mItemTexts[i]);
}
view.findViewById(R.id.homepage_item_layout).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {}
});
view.findViewById(R.id.homepage_item_layout).setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
yPosition = event.getY();//获取按下的位置
iv.setImageResource(R.mipmap.menu);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
iv.setImageResource(R.mipmap.menu_ture);
float displacement = Math.abs(yPosition - event.getY());
//精确按下的位置做出响应
if (mOnMenuItemClickListener != null&&displacement<25) {
mOnMenuItemClickListener.itemClick(v,j);
}
} else if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_POINTER_UP) {
iv.setImageResource(R.mipmap.menu_ture);
}
return true;
}
});
addView(view);
}
}
}
弧形菜单(Android)的更多相关文章
- Android 自定义View修炼-Android 实现自定义的卫星式菜单(弧形菜单)View
一.总述 Android 实现卫星式菜单也叫弧形菜单的主要要做的工作如下:1.动画的处理2.自定义ViewGroup来实现卫星式菜单View (1)自定义属性 a. 在attrs.xml中 ...
- 原生js写的一个弧形菜单插件
弧形菜单是一种半弧式或者全弧形菜单,是一种不同于传统横向或者竖向菜单形式的菜单.最近在网上看到好多人写出了这种效果,于是也尝试自己写了一个. 实现方式:原生态js 主要结构: 1.参数合并 var d ...
- 弧形菜单2(动画渐入)Kotlin开发(附带java源码)
弧形菜单2(动画渐入+Kotlin开发) 前言:基于AndroidStudio的采用Kotlin语言开发的动画渐入的弧形菜单...... 效果: 开发环境:AndroidStudio2.2.1+gra ...
- 菜单(Menu)的三中创建方式——Android开发之路2
菜单的三种创建方式 一.OptionsMenu---选项菜单 Android应用中的菜单默认是隐藏的,只有当用户点击手机上的MENU键,系统才会显示菜单.这种菜单叫做选项菜单(Options Menu ...
- Android侧滑菜单代码实现
前两天学习了hyman老师讲的Android侧滑菜单的实现,经过自己的整理分享出来给大家学习一下 现在很多APP都有菜单侧滑的功能,本篇文章主要讲解使用自定义的HorizontalScrollView ...
- android上下文菜单
XML: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmln ...
- Android课程---进度条及菜单的学习
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- Android学习笔记之树形菜单的应用...
PS:终于考完试了,总算是解脱了...可以正式上手项目开发了.... 学习内容: 1.掌握如何使用树形菜单... 对知识点进行一下补充...居然忘记了去学习树形菜单...不过在这里补上... Ex ...
- Android 菜单(OptionMenu)
菜单是用户界面中最常见的元素之一,使用非常频繁,在Android中,菜单被分为如下三种,选项菜单(OptionsMenu).上下文菜单(ContextMenu)和子菜单(SubMenu). 一.概述 ...
随机推荐
- 高阶篇:4.2)DFMEA设计失效模式和失效后果分析-总章
本章目的:了解FMEA和DFMEA的概念. 1.什么是FMEA(what) 潜在的失效模式及后果分析(Potential Failure Mode and Effects Analysis,简称FME ...
- 关于如何爬虫妹子图网的源码分析 c#实现
网上也出现一些抓取妹子图的python 代码,今天我们用c#实现爬虫过程. 请看我的网站: www.di81.com private void www_94xmn_Com(string url, st ...
- 求两个数a、b的最大公约数
//求两个数a.b的最大公约数 function gcd(a,b){ return b===0?a:gcd(b,a%b) }
- SPI裸机驱动程序设计
1. SPI(Serial Peripheral Interface)串行外设接口,是一种高速的.全双工.同步的通信总线.采用主从模式(Master Slave)架构,支持多个slave,一般仅支持单 ...
- python定义的一个简单的shell函数的代码
把写代码过程中经常用到的一些代码段做个记录,如下代码段是关于python定义的一个简单的shell函数的代码. pipe = subprocess.Popen(cmd, stdout=subproce ...
- centos安装postgresql-rpm
rpm -ivh pgdg-centos93-9.3-3.noarch.rpm确认,回车,
- Access computer files on iPad without using iTunes.
going to my CSDN blog ---> https://blog.csdn.net/qq_37746801/article/details/89708103
- nginx基础学习第二篇:nginx内置变量的使用
ngx_http_core模块提供的内置变量有很多,常见的有 $uri,用来获取当前请求的uri,不含请求参数. $request_uri,用来获取请求最原始的uri,包含请求参数,且未解码. $re ...
- Train Problem II(卡特兰数 组合数学)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1023 Train Problem II Time Limit: 2000/1000 MS (Java/ ...
- sql根据表中数量字段自动复制记录行
客户需要将表中统计好的数据还原成统计前的原始记录 例如: ID Name QTYCount100 Name1 1101 Name2 2102 Name3 3103 Name4 4104 Name5 5 ...