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

作者:wolf艺术 时间:2022-09-23 22:44:43 

 一 概述:

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

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

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

自定义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, attrs, 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, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, 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 i, int i1, int i2, 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()),0,getMeasuredHeight()-top,0);
break;
case -2:
left = childX+btmWidth/2-childWidth/2;
top =childY-childHeight/2+btmHeight/2;
ta = new TranslateAnimation(-(left+childView.getMeasuredWidth()),0,-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,-top,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,getMeasuredHeight()-top,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()),0,getMeasuredHeight()-top);
break;
case -2:
left = childX+btmWidth/2-childWidth/2;
top =childY-childHeight/2+btmHeight/2;
ta = new TranslateAnimation(0,-(left+childView.getMeasuredWidth()),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()),0,-top);
break;
case -4:
left = getMeasuredWidth() - (childX+btmWidth/2+childWidth/2);
top =getMeasuredHeight() - (childY+childHeight/2+btmHeight/2);
ta = new TranslateAnimation(0,getMeasuredWidth()-(left+childView.getMeasuredWidth()),0,getMeasuredHeight()-top);
break;
}
ta.setDuration(500);
childView.setAnimation(ta);
childView.setVisibility(View.GONE);
}
isChanged = true;
}
}

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

四个角落效果如下:

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

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

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

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

以上所述是小编给大家介绍的Android自定义VIew实现卫星菜单效果浅析网站的支持!

来源:http://blog.csdn.net/wolf6699/article/details/53065752

标签:android,卫星,菜单,view
0
投稿

猜你喜欢

  • C#正则表达式Regex类的用法

    2022-06-07 13:44:58
  • Unity3D生成一段隧道网格的方法

    2022-02-22 23:46:27
  • 深入解析Android系统中应用程序前后台切换的实现要点

    2022-09-11 01:26:30
  • Android软键盘弹出时的界面控制方法

    2022-10-26 03:37:43
  • 详解如何在SpringBoot项目中使用统一返回结果

    2023-10-30 16:41:21
  • java使用@Transactional时常犯的N种错误

    2021-08-16 01:58:44
  • 基于C#实现的屏幕指定区域截屏代码

    2021-12-31 19:42:09
  • Android开发之DatePickerDialog、TimePickerDialog时间日期对话框用法示例

    2022-10-25 21:21:12
  • Java利用Easyexcel导出excel表格的示例代码

    2023-05-30 23:36:04
  • 一键清除maven仓库中下载失败的jar包的实现方法

    2023-08-13 03:43:59
  • C#实现的xml操作类完整实例

    2023-02-12 03:52:16
  • C#实现百度ping推送功能的方法

    2023-03-01 18:15:56
  • C#中的Explicit和Implicit详情

    2022-09-06 06:50:54
  • SpringBoot使用ApplicationEvent&Listener完成业务解耦

    2021-10-19 06:36:41
  • IDEA 2020.2 +Gradle 6.6.1 + Spring Boot 2.3.4 创建多模块项目的超详细教程

    2021-11-08 00:42:36
  • C#使用JArray和JObject封装JSON对象

    2022-10-15 16:56:16
  • Java线程状态变换过程代码解析

    2023-08-06 18:05:29
  • SpringBoot实现本地文件存储及预览过程

    2022-07-31 05:30:58
  • BaseJDBC和CRUDDAO的写法实例代码

    2022-09-03 14:13:33
  • java虚拟机深入学习之内存管理机制

    2023-07-03 21:15:40
  • asp之家 软件编程 m.aspxhome.com