广告
返回顶部
首页 > 资讯 > 精选 >Android中怎么自定义组件卫星菜单
  • 525
分享到

Android中怎么自定义组件卫星菜单

android 2023-05-31 00:05:59 525人浏览 泡泡鱼
摘要

Android中怎么自定义组件卫星菜单,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。首先如果要想自定义组件 那么第一件事就是赋予自定义组件的属性,从效果图上看出,该组件可以

Android中怎么自定义组件卫星菜单,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

首先如果要想自定义组件

那么第一件事就是赋予自定义组件的属性,从效果图上看出,该组件可以存在屏幕的各个角落点,那么位置是其属性之一。

既然是卫星菜单,那么主按钮和其附属的小按钮之间的围绕半径也应该作为其参数之一。

右图得出,该组件包含很多按钮,主按钮和附属按钮,那么这个组件应该继承 ViewGroup。

一、定义卫星菜单的属性在 values 包下建立 attr 的 XML 文件,赋予组件位置属性,和半径属性。

<?xml version="1.0" encoding="utf-8"?><resources>  <!-- 位置属性-->  <attr name="position">    <enum name="left_top" value="0" />    <enum name="left_bottom" value="1" />    <enum name="right_top" value="2" />    <enum name="right_bottom" value="3" />  </attr>  <!-- 尺寸属性dp如果使用px可能会造成屏幕适配问题-->  <attr name="radius" fORMat="dimension" />  <!-- 自定义属性-->  <declare-styleable name="ArcMenu">    <attr name="position" />    <attr name="radius" />  </declare-styleable></resources>

二、编写自定义组件

package com.lanou.dllo.arcmenudemo.arcmenu;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.View;import android.view.ViewGroup;import android.view.animation.AlphaAnimation;import android.view.animation.Animation;import android.view.animation.AnimationSet;import android.view.animation.RotateAnimation;import android.view.animation.ScaleAnimation;import android.view.animation.TranslateAnimation;import com.lanou.dllo.arcmenudemo.R;public class ArcMenu extends ViewGroup implements View.OnClickListener {  //设置常量,标识成枚举  private static final int POS_LEFT_TOP = 0;  private static final int POS_LEFT_BOTTOM = 1;  private static final int POS_RIGHT_TOP = 2;  private static final int POS_RIGHT_BOTTOM = 3;  //以下5个成员变量是所需要的.  //声明两个属性 位置 还有半径  private Position mPosition = Position.RIGHT_BOTTOM;  private int mRadius;    private Status mCurrentStatus = Status.CLOSE;    private View mCButton;  //子菜单的回调按钮  private OnMenuItemClickListener mMenuItemClickListener;    public enum Position {    LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM  }  public enum Status {    OPEN, CLOSE  }    public interface OnMenuItemClickListener {    void onClick(View view, int pos);  }  //3个构造方法,相互传递.  //注意别写错误.  public ArcMenu(Context context) {    this(context, null);  }  public ArcMenu(Context context, AttributeSet attrs) {    this(context, attrs, 0);  }  public ArcMenu(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    //TypedValue.applyDimension是转变标准尺寸的方法 参数一:单位  参数二:默认值 参数三:可以获取当前屏幕的分辨率信息.    mRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP        , 100, getResources().getDisplayMetrics());    //获取自定义属性的值    //参数1:attrs AttributeSet是节点的属性集合    //参数2:attrs的一个数组集    //参数3:指向当前theme 某个item 描述的style 该style指定了一些默认值为这个TypedArray    //参数4;当defStyleAttr 找不到或者为0, 可以直接指定某个style    TypedArray a = context.getTheme().obtainStyledAttributes(attrs,        R.styleable.ArcMenu, defStyleAttr, 0);    int pos = a.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) a.getDimension(R.styleable.ArcMenu_radius,        TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP            , 100, getResources().getDisplayMetrics()));    Log.d("TAG", "Position = " + mPosition + ", radius" + mRadius);    //使用完必须回收.    a.recycle();  }  public void setOnMenuItemClickListener(OnMenuItemClickListener mMenuItemClickListener) {    this.mMenuItemClickListener = mMenuItemClickListener;  }    @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    int count = getChildCount();    for (int i = 0; i < count; i++) {      //测量child的各个属性.      measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);    }    super.onMeasure(widthMeasureSpec, heightMeasureSpec);  }  @Override  protected void onLayout(boolean changed, int l, int t, int r, int b) {    if (changed) {      layoutCButton();      //获得容器内组件的个数,并且包括这个主的组件(大按钮)      int count = getChildCount();      for (int i = 0; i < count - 1; i++) {        //这里直接获取第一个,是因为getChildAt(0)是红色的按钮.        View child = getChildAt(i + 1);        //正常来说,如果设置按钮动画,移动出去后,是不能点击的,这里给按钮设置一个隐藏的属性.等卫星菜单飞过去,在让它们显示出来.        child.setVisibility(View.GoNE);                //测量每个子卫星组件的在屏幕上面的坐标距离        //这里count-2,是因为count包含了主按钮        //每个组件的坐标为(cl,ct);        int cl = (int) (mRadius * Math.sin(Math.PI / 2 / (count - 2) * i));        int ct = (int) (mRadius * Math.cos(Math.PI / 2 / (count - 2) * i));        int cWidth = child.getMeasuredWidth();        int cHeight = child.getMeasuredHeight();        //如果卫星菜单存在于底部,那么坐标位置的计算方法,就完全相反.                if (mPosition == Position.LEFT_BOTTOM || mPosition == Position.RIGHT_BOTTOM) {          ct = getMeasuredHeight() - cHeight - ct;        }                if (mPosition == Position.RIGHT_TOP || mPosition == Position.RIGHT_BOTTOM) {          cl = getMeasuredWidth() - cWidth - cl;        }        //子布局的测量坐标;        child.layout(cl, ct, cl + cWidth, ct + cHeight);      }    }  }    private void layoutCButton() {    // 给主按钮设置监听    mCButton = getChildAt(0);    mCButton.setOnClickListener(this);    //分别代表控件所处离左侧和上侧得距离    int l = 0;    int t = 0;    int width = mCButton.getMeasuredWidth();    int height = mCButton.getMeasuredHeight();        switch (mPosition) {      case LEFT_TOP:        l = 0;        t = 0;        break;      case LEFT_BOTTOM:        l = 0;        t = getMeasuredHeight() - height;        break;      case RIGHT_TOP:        l = getMeasuredWidth() - width;        t = 0;        break;      case RIGHT_BOTTOM:        l = getMeasuredWidth() - width;        t = getMeasuredHeight() - height;        break;    }    //layout的四个属性.分别代表主按钮在不同位置距离屏幕左侧和上侧    mCButton.layout(l, t, l + width, t + height);  }  @Override  public void onClick(View v) {    //主要确定mCButton的值    mCButton = findViewById(R.id.id_button);    if (mCButton == null) {      mCButton = getChildAt(0);    }    //旋转动画    rotateCButton(v, 0f, 360f, 300);    //判断菜单是否关闭,如果菜单关闭需要给菜单展开,如果菜单是展开的需要给菜单关闭.    toggleMenu(500);  }    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);      //平移 结束为止 0,0(以子菜单按钮当前位置,为坐标系.)      int 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;      }      //多个动画同时使用使用,用到AnimationSet      AnimationSet animset = new AnimationSet(true);      Animation tranAnim = null;      //to open 打开的情况下      if (mCurrentStatus == Status.CLOSE) {        tranAnim = new TranslateAnimation(xflag * cl, 0, yflag * ct, 0);        //当卫星菜单打开的时候,按钮就可以进行点击.        childView.setClickable(true);        childView.setFocusable(true);      } else {//to close        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() {        @Override        public void onAnimationStart(Animation animation) {        }        //在动画结束时,进行设置.        @Override        public void onAnimationEnd(Animation animation) {          if (mCurrentStatus == Status.CLOSE) {//            Log.d("动画结束状态",mCurrentStatus +"");            childView.setVisibility(View.GONE);          }        }        @Override        public void onAnimationRepeat(Animation animation) {        }      });      //设置旋转动画(转两圈)      RotateAnimation rotateAnim = new RotateAnimation(0, 720,          Animation.RELATIVE_TO_SELF, 0.5f,          Animation.RELATIVE_TO_SELF, 0.5f);      rotateAnim.setDuration(duration);      rotateAnim.setFillAfter(true);      //把两个动画放到动画集里面      //注意动画顺序.先增加旋转/在增加移动./      animset.addAnimation(rotateAnim);      animset.addAnimation(tranAnim);      childView.startAnimation(animset);      final int pos = i + 1;      //设置子菜单的点击事件      childView.setOnClickListener(new OnClickListener() {        @Override        public void onClick(View v) {          if (mMenuItemClickListener != null) {            mMenuItemClickListener.onClick(childView, pos);          }            menuItemAnim(pos - 1);            //切换菜单状态            changeStatus();        }      });    }        //切换菜单状态    changeStatus();  }    private void changeStatus() {    //在执行一个操作之后,如果按钮是打开的在次点击就会切换状态.    mCurrentStatus = (mCurrentStatus == Status.CLOSE ? Status.OPEN :        Status.CLOSE);    Log.d("动画结束状态", mCurrentStatus + "");  }  public boolean isOpen(){    return mCurrentStatus ==Status.OPEN;  }  //设置旋转动画绕自身旋转一圈 然后持续时间为300  private void rotateCButton(View v, float start, float end, int duration) {    RotateAnimation anim = new RotateAnimation(start, end, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);    anim.setDuration(duration);    //保持动画旋转后的状态.    anim.setFillAfter(true);    v.startAnimation(anim);  }    private void menuItemAnim(int pos) {    for (int i = 0; i < getChildCount() - 1; i++) {      View childView = getChildAt(i + 1);      //在判断条件下,写入动画      //当其中一个子菜单被点击后,自身变大并且消失      //其他子菜单则变小消失.      if (i == pos) {        childView.startAnimation(scaleBigAnim(300));      } else {        childView.startAnimation(scaleSmallAnim(300));      }      //当子菜单被点击之后,其他子菜单就要变成不可被点击和获得焦点的状态,      childView.setClickable(false);      childView.setFocusable(false);    }  }    private Animation scaleBigAnim(int duration) {    AnimationSet animationSet = new AnimationSet(true);    ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 4.0f, 1.0f, 4.0f,        Animation.RELATIVE_TO_SELF, 0.5f,        Animation.RELATIVE_TO_SELF, 0.5f);    AlphaAnimation alphaAnimation=new AlphaAnimation(1f,0.0f);    animationSet.addAnimation(scaleAnimation);    animationSet.addAnimation(alphaAnimation);    animationSet.setDuration(duration);    animationSet.setFillAfter(true);    return animationSet;  }  private Animation scaleSmallAnim(int duration) {    AnimationSet animationSet = new AnimationSet(true);    ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.0f, 1.0f, 0.0f,        Animation.RELATIVE_TO_SELF, 0.5f,        Animation.RELATIVE_TO_SELF, 0.5f);    AlphaAnimation alphaAnimation=new AlphaAnimation(1f,0.0f);    animationSet.addAnimation(scaleAnimation);    animationSet.addAnimation(alphaAnimation);    animationSet.setDuration(duration);    animationSet.setFillAfter(true);    return animationSet;  }}

以上就是 卫星菜单的编写,上面的注释量比较大。

这里需要注意的一点。卫星菜单在屏幕不同位置,他的动画平移值是不一样的。

如果实在不理解可以画图试试。

三、使用时注意赋予命名空间

<?xml version="1.0" encoding="utf-8"?><com.lanou.dllo.arcmenudemo.arcmenu.ArcMenu xmlns:android="Http://schemas.android.com/apk/res/android"  xmlns:app="http://schemas.android.com/apk/res-auto"  xmlns:arcmenu="http://schemas.android.com/apk/res/com.lanou.dllo.arcmenudemo"  xmlns:tools="http://schemas.android.com/tools"  android:id="@+id/id_menu"  android:layout_width="match_parent"  android:layout_height="match_parent"  arcmenu:position="left_top"  arcmenu:radius="140dp">    <!-- 主按钮-->    <RelativeLayout      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:background="@mipmap/composer_button">      <ImageView        android:id="@+id/id_button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:src="@mipmap/composer_icn_plus" />    </RelativeLayout>    <ImageView      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:src="@mipmap/composer_camera"      android:tag="Camera"/>    <ImageView      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:src="@mipmap/composer_music"      android:tag="Music"/>    <ImageView      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:src="@mipmap/composer_place"      android:tag="Place"/>    <ImageView      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:src="@mipmap/composer_sleep"      android:tag="Sleep"/>    <ImageView      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:src="@mipmap/composer_thought"      android:tag="Sun"/>    <ImageView      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:src="@mipmap/composer_with"      android:tag="People"/></com.lanou.dllo.arcmenudemo.arcmenu.ArcMenu>

关于Android中怎么自定义组件卫星菜单问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网精选频道了解更多相关知识。

--结束END--

本文标题: Android中怎么自定义组件卫星菜单

本文链接: https://www.lsjlt.com/news/222419.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android中怎么自定义组件卫星菜单
    Android中怎么自定义组件卫星菜单,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。首先如果要想自定义组件 那么第一件事就是赋予自定义组件的属性,从效果图上看出,该组件可以...
    99+
    2023-05-31
    android
  • Android实现自定义的卫星式菜单(弧形菜单)详解
    一、前言 Android 实现卫星式菜单也叫弧形菜单,主要要做的工作如下: 1.动画的处理 2.自定义ViewGroup来实现卫星式菜单View (1)自定义属性 &n...
    99+
    2022-06-06
    自定义 菜单 Android
  • Android自定义VIew实现卫星菜单效果浅析
     一 概述: 最近一直致力于Android自定义VIew的学习,主要在看《android群英传》,还有CSDN博客鸿洋大神和wing大神的一些文章,写的很详细,自己心...
    99+
    2022-06-06
    菜单 view Android
  • nodejs中怎么自定义菜单
    今天就跟大家聊聊有关nodejs中怎么自定义菜单,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1. 自定义菜单的介绍自定义菜单能够帮助公众号丰富界面...
    99+
    2022-10-19
  • Android自定义控件之仿优酷菜单
    去年的优酷HD版有过这样一种菜单,如下图: 应用打开之后,先是三个弧形的三级菜单,点击实体键menu之后,这三个菜单依次旋转退出,再点击实体键menu之后,一级菜单会旋转进入...
    99+
    2022-06-06
    菜单 Android
  • Android应用中怎么自定义一个菜单栏
    这期内容当中小编将会给大家带来有关Android应用中怎么自定义一个菜单栏,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。在android开发的过程中系统自带的菜单往往满足不了开发中的一些需求,比如说一排最...
    99+
    2023-05-31
    android roi
  • Android自定义控件实现底部菜单(上)
    今天我们封装一个底部的菜单栏,这个大多数的应用都会用到,因此我们来自定义,方便以后项目的使用。 该控件的实现将分上下篇来介绍,先来看一个菜单栏的子控件–MenuItemM,这个...
    99+
    2022-06-06
    菜单 Android
  • Android自定义控件实现底部菜单(下)
    在app中经常会用到底部菜单的控件,每次都需要写好多代码,今天我们用到了前几篇博客里的控件来进一步封装底部菜单。先看效果图: 主要包括以下功能: 1 设置icon以及点击之...
    99+
    2022-06-06
    菜单 Android
  • vue中自定义右键菜单插件怎么用
    今天小编给大家分享一下vue中自定义右键菜单插件怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。演示用法通过npm安装插...
    99+
    2023-06-29
  • Android自定义组件:1、什么是自定义组件、自定义组件的方式、定义自定义属性
    声明:本教程不收取任何费用,欢迎转载,尊重作者劳动成果,不得用于商业用途,侵权必究!!! 目录 一、前言 二、什么是自定义组件 三、自定义组件的方式 1、组合现有组件 2、在某...
    99+
    2022-06-06
    属性 自定义属性 Android
  • Android自定义控件简单实现侧滑菜单效果
    侧滑菜单在很多应用中都会见到,最近QQ5.0侧滑还玩了点花样~~对于侧滑菜单,一般大家都会自定义ViewGroup,然后隐藏菜单栏,当手指滑动时,通过Scroller或者不断的...
    99+
    2022-06-06
    菜单 Android
  • vue中自定义右键菜单插件
    前言: 作为一个刚刚入门前端的搬砖工作者,写博客只是为了能够记录自己因为业务使用过的一些插件,为了后续更好的使用和改造 本文分享了vue中自定义右键菜单插件的具体代码,供大家参考,具...
    99+
    2022-11-13
  • android怎么自定义组合控件
    要自定义一个组合控件,你可以按照以下步骤进行:1. 创建一个新的类,继承自现有的Android控件类,例如LinearLayout或...
    99+
    2023-08-09
    android
  • vue怎么自定义右键菜单
    今天小编给大家分享一下vue怎么自定义右键菜单的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。在需要添加右键的页面,绑定con...
    99+
    2023-06-29
  • Android中怎么通过自定义View 实现QQ侧滑菜单
    这期内容当中小编将会给大家带来有关Android中怎么通过自定义View 实现QQ侧滑菜单,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。布局代码<fierce_luk.com.sideslipvie...
    99+
    2023-05-30
    android view
  • Android自定义控件案例汇总1(菜单、popupwindow、viewpager)
    自定义控件是根据自己的需要自己来编写控件。安卓自带的控件有时候无法满足你的需求,这种时候,我们只能去自己去实现适合项目的控件。同时,安卓也允许你去继承已经存在的控件或者实现你自...
    99+
    2022-06-06
    菜单 popupwindow viewpager Android
  • Android实现Ant Design 自定义表单组件
    Ant Design 组件提供了Input,InputNumber,Radio,Select,uplod等表单组件,但实际开发中这是不能满足需求,同时我们希望可以继续使用Form提供的验证和提示等方法(使用起来确实很爽),这时需要...
    99+
    2023-05-31
    ant design 表单组件
  • Android控件View打造完美的自定义侧滑菜单
    一、概述   在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上咱们可以自己也写一个自定义的侧滑View控件,其实不难,...
    99+
    2022-06-06
    自定义 菜单 view Android
  • javascript中如何自定义右键菜单插件
    这篇文章将为大家详细讲解有关javascript中如何自定义右键菜单插件,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。具体内容如下1.使用方式js文件引入<scri...
    99+
    2022-10-19
  • antd form表单中怎么嵌套自定义组件
    本篇内容主要讲解“antd form表单中怎么嵌套自定义组件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“antd form表单中怎么嵌套自定义组件”吧!表单部分<Fo...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作