Android自定义VIew实现卫星菜单效果浅析

Android自定义VIew实现卫星菜单效果浅析,第1张

概述 一概述:最近一直致力于Android自定义VIew的学习,主要在看《android群英传》,还有CSDN博客鸿洋大神和wing大神的一些文章,写的很详细,自己心血来潮,学着写了个实现了类似卫星效果的一个自定义的View,分享

 一 概述:

最近一直致力于AndroID自定义view的学习,主要在看《androID群英传》,还有CSDN博客鸿洋大神和wing大神的一些文章,写的很详细,自己心血来潮,学着写了个实现了类似卫星效果的一个自定义的VIEw,分享到博客上,望各位指点一二。写的比较粗糙,见谅。(因为是在linux系统下写的,效果图我直接用手机拍的,难看,大家讲究下就看个效果,勿喷)。

先来看个效果图,有点不忍直视:

自定义view准备:

(1)创建继承自VIEw的类;

(2)重写构造函数;

(3)定义属性。

(4)重写onMeasure(),onLayout()方法。

好了,废话不说了,准备上菜。

二 相关实现

首先是自定义的VIEw,重写构造函数,我这里是直接继承的VIEwGroup,贴上代码:

public MoonVIEw(Context context) { this(context,null); } public MoonVIEw(Context context,AttributeSet attrs) { this(context,attrs,0); } public MoonVIEw(Context context,AttributeSet attrs,int defStyleAttr) { super(context,defStyleAttr); }

这里需要读取自定义的属性,所以调用含三个参数的构造函数。

自定义的属性,我这里知定义了两个,一个是菜单弧形的半径,还有个是菜单在屏幕的位置,这里可以设置在左上角,左下角,右上角,右下角。代码如下:

<?xml version="1.0" enCoding="utf-8"?> <resources> <declare-styleable name="MoonAttrs"> <attr name="mRadius" format="integer"></attr><!--菜单圆形半径--> <attr name="mposition"><!--卫星菜单屏幕所在位置--> <enum name="lefttop" value="-2"></enum><!--左上角--> <enum name="leftBottom" value="-1"></enum><!--左下角--> <enum name="righttop" value="-3"></enum><!--右上角--> <enum name="rightBottom" value="-4"></enum><!--右下角--> </attr> </declare-styleable> </resources>

然后在布局文件里面引用自定义的VIEw,配置属性:

<?xml version="1.0" enCoding="utf-8"?> <com.example.liujibin.testmyvIEw3.myVIEw.MoonVIEw xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:custom="http://schemas.androID.com/apk/res/com.example.liujibin.testmyvIEw3" androID:orIEntation="vertical" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" custom:mRadius="400" custom:mposition="rightBottom" > <ImageVIEw androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:background="@mipmap/sAPI_icon_add_account"/> <ImageVIEw androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:background="@mipmap/sAPI_icon_add_account"/> <ImageVIEw androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:background="@mipmap/sAPI_icon_add_account"/> <ImageVIEw androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:background="@mipmap/sAPI_icon_add_account"/> <ImageVIEw androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:background="@mipmap/sAPI_icon_add_account"/> <ImageVIEw androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:background="@mipmap/sAPI_icon_add_account"/> </com.example.liujibin.testmyvIEw3.myVIEw.MoonVIEw>

最后我们需要在自定义的VIEw类中的构造函数里,获取相关的属性值:

public MoonVIEw(Context context,defStyleAttr); //获取相关属性 TypedArray ta = context.gettheme().obtainStyledAttributes(attrs,R.styleable.MoonAttrs,defStyleAttr,0); mRaius = ta.getInt(R.styleable.MoonAttrs_mRadius,500); position = ta.getInt(R.styleable.MoonAttrs_mposition,-1); }

做完以上的准备工作,我们就可以对组件进行测量,布局。

@OverrIDe protected voID onMeasure(int wIDthMeasureSpec,int heightmeasureSpec) { super.onMeasure(wIDthMeasureSpec,heightmeasureSpec); count = getChildCount()-1; angle = 90/(count-1); int count = getChildCount(); for(int i =0;i< count;i++){ measureChild(getChildAt(i),wIDthMeasureSpec,heightmeasureSpec); } }

count获取按钮的数量,有一个是中心点,不参与计算,angle是每个按钮离基准线的角度,这里以90度为准,固定在这个范围里面均匀分配。

首先先把中心点固定好位置:

@OverrIDe protected voID onLayout(boolean b,int i,int i1,int i2,int i3) { if(isChanged){ layoutBottom(); } } private voID layoutBottom(){ VIEw vIEw = getChildAt(0); switch (position){ case -1: btml = 0; btmt = getMeasuredHeight() - vIEw.getMeasuredHeight(); btmr = vIEw.getMeasureDWIDth(); btmb = getMeasuredHeight(); break; case -2: btml = 0; btmt = 0; btmr = vIEw.getMeasureDWIDth(); btmb = vIEw.getMeasuredHeight(); break; case -3: btml = getMeasureDWIDth() - vIEw.getMeasureDWIDth(); btmt = 0; btmr = getMeasureDWIDth(); btmb = vIEw.getMeasuredHeight(); break; case -4: btml = getMeasureDWIDth() - vIEw.getMeasureDWIDth(); btmt = getMeasuredHeight() - vIEw.getMeasuredHeight(); btmr = getMeasureDWIDth(); btmb = getMeasuredHeight(); break; } btmWIDth = vIEw.getMeasureDWIDth(); btmHeight = vIEw.getMeasuredHeight(); vIEw.setonClickListener(this); vIEw.layout(btml,btmt,btmr,btmb); }

position的值看属性就明白了,对中心点进行固定位置。并且注册点击事件。

现在开始给剩下的按钮布局,并隐藏按钮:

@OverrIDe protected voID onLayout(boolean b,int i3) { if(isChanged){ layoutBottom(); int count = getChildCount(); for(int k = 0;k < count - 1;k++){ VIEw vIEw = getChildAt(k+1); int chilDWIDth = vIEw.getMeasureDWIDth(); int childHeight = vIEw.getMeasuredHeight(); int childX = (int)(mRaius*(Math.sin(angle*(k)*Math.PI/180))); int childY = (int)(mRaius*(Math.cos(angle*(k)*Math.PI/180))); int left = 0; int top = 0; int right = 0; int bottom = 0; switch(position){ case -1: left = childX+btmWIDth/2-chilDWIDth/2; top =getMeasuredHeight() - (childY+childHeight/2+btmHeight/2); right = childX+btmWIDth/2+chilDWIDth/2; bottom =getMeasuredHeight() - (childY + btmHeight/2) + childHeight/2; break; case -2: left = childX+btmWIDth/2-chilDWIDth/2; top =childY-childHeight/2+btmHeight/2; right = childX+btmWIDth/2+chilDWIDth/2; bottom = childY + btmHeight/2 + childHeight/2; break; case -3: left = getMeasureDWIDth() - (childX+btmWIDth/2+chilDWIDth/2); top =childY-childHeight/2+btmHeight/2; right = getMeasureDWIDth() - (childX+btmWIDth/2+chilDWIDth/2)+chilDWIDth; bottom = childY + btmHeight/2 + childHeight/2; break; case -4: left = getMeasureDWIDth() - (childX+btmWIDth/2+chilDWIDth/2); top =getMeasuredHeight() - (childY+childHeight/2+btmHeight/2); right = getMeasureDWIDth() - (childX+btmWIDth/2+chilDWIDth/2)+chilDWIDth; bottom =getMeasuredHeight() - (childY + btmHeight/2) + childHeight/2; break; } vIEw.layout(left,top,right,bottom); vIEw.setVisibility(VIEw.GONE); } } }

现在我们实现点击事件:

@OverrIDe public voID onClick(VIEw vIEw) { if(isChanged){ int count = getChildCount(); for(int i = 0;i < count - 1;i++){ VIEw childVIEw = getChildAt(i+1); int childX = (int)(mRaius*(Math.sin(angle*(i)*Math.PI/180))); int childY = (int)(mRaius*(Math.cos(angle*(i)*Math.PI/180))); int chilDWIDth = vIEw.getMeasureDWIDth(); int childHeight = vIEw.getMeasuredHeight(); int left = 0; int top = 0; TranslateAnimation ta = null; switch(position){ case -1: left = childX+btmWIDth/2-chilDWIDth/2; top =getMeasuredHeight() - (childY+childHeight/2+btmHeight/2); ta = new TranslateAnimation(-(left+childVIEw.getMeasureDWIDth()),getMeasuredHeight()-top,0); break; case -2: left = childX+btmWIDth/2-chilDWIDth/2; top =childY-childHeight/2+btmHeight/2; ta = new TranslateAnimation(-(left+childVIEw.getMeasureDWIDth()),-top,0); break; case -3: left = getMeasureDWIDth() - (childX+btmWIDth/2+chilDWIDth/2); top =childY-childHeight/2+btmHeight/2; ta = new TranslateAnimation(getMeasureDWIDth()-(left+childVIEw.getMeasureDWIDth()),0); break; case -4: left = getMeasureDWIDth() - (childX+btmWIDth/2+chilDWIDth/2); top =getMeasuredHeight() - (childY+childHeight/2+btmHeight/2); ta = new TranslateAnimation(getMeasureDWIDth()-(left+childVIEw.getMeasureDWIDth()),0); break; } ta.setDuration(500); childVIEw.setAnimation(ta); childVIEw.setVisibility(VIEw.VISIBLE); } isChanged = false; }else{ int count = getChildCount(); for(int i = 0;i < count - 1;i++){ VIEw childVIEw = getChildAt(i+1); int childX = (int)(mRaius*(Math.sin(angle*(i)*Math.PI/180))); int childY = (int)(mRaius*(Math.cos(angle*(i)*Math.PI/180))); int chilDWIDth = vIEw.getMeasureDWIDth(); int childHeight = vIEw.getMeasuredHeight(); int left = 0; int top = 0; TranslateAnimation ta = null; switch(position){ case -1: left = childX+btmWIDth/2-chilDWIDth/2; top =getMeasuredHeight() - (childY+childHeight/2+btmHeight/2); ta = new TranslateAnimation(0,-(left+childVIEw.getMeasureDWIDth()),getMeasuredHeight()-top); break; case -2: left = childX+btmWIDth/2-chilDWIDth/2; top =childY-childHeight/2+btmHeight/2; ta = new TranslateAnimation(0,-top); break; case -3: left = getMeasureDWIDth() - (childX+btmWIDth/2+chilDWIDth/2); top =childY-childHeight/2+btmHeight/2; ta = new TranslateAnimation(0,getMeasureDWIDth()-(left+childVIEw.getMeasureDWIDth()),-top); break; case -4: left = getMeasureDWIDth() - (childX+btmWIDth/2+chilDWIDth/2); top =getMeasuredHeight() - (childY+childHeight/2+btmHeight/2); ta = new TranslateAnimation(0,getMeasuredHeight()-top); break; } ta.setDuration(500); childVIEw.setAnimation(ta); childVIEw.setVisibility(VIEw.GONE); } isChanged = true; } }

设置点击显示以及隐藏,并且带飘动的动画效果。

四个角落效果如下:






以上所述是小编给大家介绍的AndroID自定义view实现卫星菜单效果浅析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!

总结

以上是内存溢出为你收集整理的Android自定义VIew实现卫星菜单效果浅析全部内容,希望文章能够帮你解决Android自定义VIew实现卫星菜单效果浅析所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1147802.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存