步骤:一:自定义ViewGroup

1、自定义属性

a、attr.xml

b、在布局文件中使用activity_main.xml

c、在自定义控件中进行读取

2、onMeasure

3、onLayout

4、设置主按钮的旋转动画

为menuItem添加平移动画和旋转动画

实现menuItem的点击事件

MainActivity.java

public class MainActivity extends AppCompatActivity {private ListView listView;private List<String> mData;private ArrayAdapter mAdapter;private ArcMenuActivity mArc;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);listView = (ListView) findViewById(R.id.listview);mArc = (ArcMenuActivity) findViewById(R.id.view_arc);addData();mAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, mData);listView.setAdapter(mAdapter);listView.setOnScrollListener(new AbsListView.OnScrollListener() {@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {if (mArc.isOpen()) {mArc.toggleMenu(200);}}});mArc.setOnMenuItemClickListener(new ArcMenuActivity.onMenuItemClickListener() {@Overridepublic void onItemClick(View view, int position) {Toast.makeText(MainActivity.this,position+" : "+view.getTag(),Toast.LENGTH_SHORT).show();}});}private void addData() {mData = new ArrayList<String>();for (int i = 'A'; i <= 'z'; i++) {mData.add((char) i + "");}}}

ArcMenuActivity.java

/*** 自定义的ViewGroup,在activity_main.xml里面调用*/
public class ArcMenuActivity extends ViewGroup {private static final int POS_LEFT_TOP = 0;private static final int POS_RIGHT_TOP = 1;private static final int POS_LEFT_BOTTOM = 2;private static final int POS_RIGHT_BOTTOM = 3;private Position mPosition = Position.RIGHT_BOTTOM;private Status mCurrentStatus = Status.CLOSE;private onMenuItemClickListener onMenuItemClick;private View mCButton;       //主菜单按钮private int mRadius;         //卫星半径//卫星菜单位置枚举类public enum Position {LEFT_TOP, RIGHT_TOP, LEFT_BOTTOM, RIGHT_BOTTOM}//主菜单的状态public enum Status {OPEN, CLOSE}//定义一个点击点击子菜单项的回调接口public interface onMenuItemClickListener {void onItemClick(View view, int position);}//自定义的点击方法public void setOnMenuItemClickListener(onMenuItemClickListener onMenuItemClick) {this.onMenuItemClick = onMenuItemClick;}public ArcMenuActivity(Context context) {
//        super(context);this(context, null);}public ArcMenuActivity(Context context, AttributeSet attrs) {
//        super(context, attrs);this(context, attrs, 0);}public ArcMenuActivity(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//获取自定义属性的值TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArcMenu, defStyleAttr, 0);//getInt()方法//参数1:所需要赋予给pos的值// 参数2:如果参数1无值,则取该值,就是custom:position="right_bottom"没有定义时int pos = ta.getInt(R.styleable.ArcMenu_position, POS_RIGHT_BOTTOM);switch (pos) {case POS_LEFT_TOP:mPosition = Position.LEFT_TOP;break;case POS_LEFT_BOTTOM:mPosition = Position.LEFT_BOTTOM;break;case POS_RIGHT_TOP:mPosition = Position.RIGHT_TOP;break;case POS_RIGHT_BOTTOM:mPosition = Position.RIGHT_BOTTOM;break;}//半径的默认值mRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());//getDimension()方法//参数1:所需要赋予给radius的值// 参数2:如果参数1无值,则取该值,就是custom:radius="100"没有定义时mRadius = (int) ta.getDimension(R.styleable.ArcMenu_radius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics()));//radius输出的值为pxLog.v("TGA", "position = " + mPosition + ",radius = " + mRadius);ta.recycle();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//获取activity_main.xml里面的View控件的个数// <my.com.example.x550v.view.ArcMenuActivity/>里面的int count = getChildCount();//测量childfor (int i = 0; i < count; i++) {//xml文件里面控件的位置,宽,高
            measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);}super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {if (changed) {//主菜单按钮
            layoutCButton();//子菜单按钮
            subItemButton();}}//定义主菜单按钮private void layoutCButton() {//或者使用findViewById()的方法mCButton = getChildAt(0); //获取第一个xml文件里面的第一个View控件mCButton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//主菜单动画//这里得使用getContext()来获取contextAnimation animation = AnimationUtils.loadAnimation(getContext(), R.anim.anim);//如果使用setAnimation()只会转一次
                mCButton.startAnimation(animation);//子菜单动画toggleMenu(200);}});//l为主菜单距离父布局的左边距离,t为主菜单距离父布局的顶边距离int l = 0, t = 0;//获取主按钮的宽和高int width = mCButton.getMeasuredWidth();int height = mCButton.getMeasuredHeight();switch (mPosition) {case LEFT_TOP://0,0表示坐上角的位置l = 0;t = 0;break;case RIGHT_TOP:l = getMeasuredWidth() - width;   //getMeasuredWidth()取得容器的宽度t = 0;break;case LEFT_BOTTOM:l = 0;t = getMeasuredHeight() - height; //getMeasuredHeight()取得容器的高度break;case RIGHT_BOTTOM:l = getMeasuredWidth() - width;t = getMeasuredHeight() - height;break;}mCButton.layout(l, t, l + width, t + height);}//定义子菜单按钮public void subItemButton() {//获取activity_main.xml里面的View控件的个数// <my.com.example.x550v.view.ArcMenuActivity/>里面的int count = getChildCount();for (int i = 0; i < count - 1; i++) { //去掉主菜单按钮的一个View child = getChildAt(i + 1);   //从第一个子菜单开始获取,而不是主菜单//开始时设置子菜单为隐藏
            child.setVisibility(GONE);//当子菜单为左上角时,cl为子菜单距离父布局的左边距离,ct为子菜单距离父布局的顶边距离//当子菜单为右上角时,cl为子菜单距离父布局的右边距离,ct为子菜单距离父布局的顶边距离//当子菜单为左下角时,cl为子菜单距离父布局的左边距离,ct为子菜单距离父布局的底边距离//当子菜单为右下角时,cl为子菜单距离父布局的右边距离,ct为子菜单距离父布局的底边距离//Math.PI的值为圆周率pai,角度为180度//Math.PI / 2 / (count - 2)是取出平均角,//*i是看子菜单拥有几个平均角int cl = (int) (mRadius * Math.sin(Math.PI / 2 / (count - 2) * i));
//            Log.v("TAG","cl = "+cl);int ct = (int) (mRadius * Math.cos(Math.PI / 2 / (count - 2) * i));//获取子菜单View的宽和高int cWidth = child.getMeasuredWidth();int cHeight = child.getMeasuredHeight();//如果子菜单在左下,右下if (mPosition == Position.LEFT_BOTTOM || mPosition == Position.RIGHT_BOTTOM) {ct = getMeasuredHeight() - cHeight - ct;Log.v("TAG","getMeasuredHeight()"+getMeasuredHeight());}//如果子菜单在右上,右下if (mPosition == Position.RIGHT_TOP || mPosition == Position.RIGHT_BOTTOM) {cl = getMeasuredWidth() - cWidth - cl;}child.layout(cl, ct, cl + cWidth, ct + cHeight);}}//定义点击主菜单后子菜单出现动画public void toggleMenu(int duration) {int count = getChildCount();for (int i = 0; i < count - 1; i++) {final View childView = getChildAt(i + 1);childView.setVisibility(View.VISIBLE);//end 0,0//startint cl = (int) (mRadius * Math.sin(Math.PI / 2 / (count - 2) * i));int ct = (int) (mRadius * Math.cos(Math.PI / 2 / (count - 2) * i));int xFlag = 1;int yFlag = 1;if (mPosition == Position.LEFT_TOP || mPosition == Position.LEFT_BOTTOM) {xFlag = -1;}if (mPosition == Position.LEFT_TOP || mPosition == Position.RIGHT_TOP) {yFlag = -1;}final AnimationSet animationSet = new AnimationSet(true);//位移动画Animation tranAnim = null;//如果为关闭状态,点击后会散开if (mCurrentStatus == Status.CLOSE) {//子菜单一开始就是扇形排布,其坐标为(0,0)tranAnim = new TranslateAnimation(xFlag * cl, 0, yFlag * ct, 0);childView.setClickable(true);childView.setFocusable(true);}//否则为打开状态,点击后会收缩else {tranAnim = new TranslateAnimation(0, xFlag * cl, 0, yFlag * ct);childView.setClickable(false);childView.setFocusable(false);}tranAnim.setFillAfter(true);tranAnim.setDuration(duration);tranAnim.setStartOffset((i * 100) / count); //越是后面的子菜单,延迟越多tranAnim.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {if (mCurrentStatus == Status.CLOSE) {childView.setVisibility(GONE);}}@Overridepublic void onAnimationRepeat(Animation animation) {}});//旋转动画RotateAnimation rotateAnim = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);rotateAnim.setFillAfter(true);rotateAnim.setDuration(duration);//先旋转,再位移//先位移,再旋转更炫
//            animationSet.addAnimation(tranAnim);
            animationSet.addAnimation(rotateAnim);animationSet.addAnimation(tranAnim);childView.startAnimation(animationSet);final int pos = i + 1;//子菜单的点击监听childView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (onMenuItemClick != null) {onMenuItemClick.onItemClick(childView, pos);}menuItemAnim(pos - 1);  //子菜单点击动画
                    changeStatus();}});}//切换菜单状态,在for()循环之外
        changeStatus();}//切换菜单状态private void changeStatus() {mCurrentStatus = (mCurrentStatus == Status.CLOSE ? Status.OPEN : Status.CLOSE);}//添加子菜单点击动画private void menuItemAnim(int pos) {for (int i = 0; i < getChildCount() - 1; i++) {View childView = getChildAt(i + 1);if (i == pos) {childView.startAnimation(scaleBigAnimation(300));} else {childView.startAnimation(scaleSmallAnimation(300));}childView.setClickable(false);childView.setFocusable(false);}}//子菜单变大,变小动画private Animation scaleBigAnimation(int duration) {AnimationSet set = new AnimationSet(true);Animation scaleAnim = new ScaleAnimation(1, 2, 1, 2, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);Animation alphaAnim = new AlphaAnimation(1, 0);set.setDuration(duration);set.addAnimation(scaleAnim);set.addAnimation(alphaAnim);set.setFillAfter(true);return set;}private Animation scaleSmallAnimation(int duration) {AnimationSet set = new AnimationSet(true);Animation scaleAnim = new ScaleAnimation(1, 0, 1, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);Animation alphaAnim = new AlphaAnimation(1, 0);set.setDuration(duration);set.addAnimation(scaleAnim);set.addAnimation(alphaAnim);set.setFillAfter(true);return set;}public boolean isOpen(){return mCurrentStatus == Status.OPEN;}}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:custom="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ListViewandroid:id="@+id/listview"android:layout_width="match_parent"android:layout_height="match_parent"/><my.com.example.x550v.view.ArcMenuActivityandroid:id="@+id/view.arc"android:layout_width="match_parent"android:layout_height="match_parent"custom:position="right_bottom"custom:radius="200dp"><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/composer_button"><ImageViewandroid:id="@+id/iv_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:src="@drawable/composer_icn_plus" /></RelativeLayout><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/composer_camera"android:tag="Camera" /><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/composer_music"android:tag="Music" /><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/composer_place"android:tag="Place" /><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/composer_sleep"android:tag="Sleep" /><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/composer_thought"android:tag="Thought" /><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/composer_with"android:tag="With" /></my.com.example.x550v.view.ArcMenuActivity></RelativeLayout>

attr.xml

<resources><attr name="position"><enum name="left_top" value="0" /><enum name="right_top" value="1" /><enum name="left_bottom" value="2" /><enum name="right_bottom" value="3" /></attr><attr name="radius" format="dimension" /><declare-styleable name="ArcMenu"><attr name="position" /><attr name="radius" /></declare-styleable></resources>

anim.xml

<setxmlns:android="http://schemas.android.com/apk/res/android"><rotateandroid:duration="500"android:fromDegrees="0"android:toDegrees="360"android:pivotX="50%"android:pivotY="50%"android:fillAfter="true"/>
</set>

运行效果:

转载于:https://www.cnblogs.com/tianhengblogs/p/5263186.html

Android 实现卫星菜单相关推荐

  1. android 开发卫星菜单,android之类似卫星菜单,来自定义ViewGroup。。。。。

    这是一个继承ViewGroup的自定义控件,对于高手来说比较简单,但对于我们这样的小白,确实是一个不错的demo 定义继承ViewGroup的自定义View  ,需要实现它的两个基本方法, onMea ...

  2. android 实现自定义卫星菜单

    看了hyman老师的视频,听起来有点迷糊,所以就想把实现卫星菜单的实现总结一下.长话短说,下面总结一下: 一.自定义ViewGroup 1).自定义属性文件 属性的定义: <attr name= ...

  3. android 弹出菜单环形,『Android自定义View实战』实现一个小清新的弹出式圆环菜单...

    前言 Android表现快捷菜单的形式有很多种,比如使用PopupWindow弹出来的小弹窗,类似QQ的侧拉功能菜单,以及之前讲过的弧形菜单( Android 自定义弧形旋转菜单栏--卫星菜单),这次 ...

  4. android用户界面之菜单(Menu)教程实例汇总

    一.Menu的基本介绍 1.从头学Android之Menu选项菜单  http://www.apkbus.com/android-13930-1-1.html  2.Android 界面之Menu菜单 ...

  5. Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9671609 记得在很早之前,我写了一篇关于Android滑动菜单的文章,其中有一个 ...

  6. android的选项菜单,Android界面菜单(2)—选项菜单

    选项菜单 Android 4.0 系统中,Activity在创建时便会调用 onCreateOptionMenu() 函数初始化自身的菜单系统.在Activity的整个生命周期中,选项菜单是一直被重复 ...

  7. android 按钮 菜单,(期末要考啊)Android的menu(菜单)按钮的使用

    (期末要考啊)Android的menu(菜单)按钮的使用 安卓 Android的菜单按钮 使用xml的方式创建菜单项在res下的menu目录下新建一个main.xml文件,以menu为根节点,添加一个 ...

  8. android 动态修改菜单,如何在Android的“选项”菜单上更改MenuItem?

    如何在Android的"选项"菜单上更改MenuItem? 我的Activity上有一个选项菜单,带有mymenu.xml"开始". 选择此3000128611 ...

  9. android自定义侧滑菜单代码,原生Android 侧滑菜单实践(部分)

    此为第一个制作侧滑菜单的实践 . 此部分仅仅为部分实践: 仅缺menu的字符串布局,以及需要修改的MainActivity.java文件,也是需要主要修改的地方. 从使用MD设计-进行侧滑菜单的制作( ...

最新文章

  1. 爱奇艺火爆的背后,个性化推荐排序是如何配合的?
  2. torch topk
  3. 电脑屏幕保护怎么取消_怎么监控员工电脑?老板如何知道员工上班在干什么?...
  4. 自定义的Sort对象
  5. 区块链宠物社区Pawtocol与去中心化社交网络memeunity达成合作
  6. SAP License:物料账错误描述与解决办法
  7. Kafka 的生产者优秀架构设计
  8. Ubuntu上安装GCC编译器
  9. u8系统怎么进服务器取数,u8服务器如何连接数据库
  10. [转]如何学好windows c++编程 学习精髓(收集,整理)
  11. MySQL的安装与配置——详细教程
  12. java calendar星期几_java使用Calendar类判断今天是星期几
  13. java jit_Java的JIT
  14. SCAU 2018新生赛 初出茅庐 全题解
  15. 大数据时代:大数据发展必备三个条件
  16. Excel 中的协方差阵
  17. 盘点抖音上的整蛊程序,会了这些谁还敢跟你玩?小心没朋友啦
  18. 用MATLAB读取.nc文件,并绘图
  19. conrestoneSVN的登录,使用自行解决,嘻嘻
  20. iphone4s改装 linux,iPhone4S降级教程(支持iOS5.1.1)可实现完美越狱

热门文章

  1. mybatisplus报的mysql错误归纳
  2. 请用旧版的 Scala-2.11 搭配 Spark-2.4.8 / hadoop-2.7
  3. VirtualBox扩容失败-Progress state: VBOX_E_NOT_SUPPORTED
  4. Golang服务端开发及微服务架构
  5. Kubernetes的client-go库介绍
  6. Android图表引擎AChartEngine - 简介
  7. 【java学习之路】(java框架)007.IoC和DI注解开发
  8. mysql replication 延时_MySQL:延迟的主从复制 ( Delayed Replication )
  9. 查询Linux的公网及内网IP
  10. hive 中String对长度没有限制