自定义ViewGroup——卫星式菜单的实现

public class MoonMenu extends ViewGroup {
    private int cl = 0, ct = 0;
    private Position position;
    private int childCount;
    private boolean isMenuClose = true;
    private View centerButton;
    private boolean isOnce;

    public MoonMenu(Context context) {
        this(context, null);
    }

    public MoonMenu(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MoonMenu(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MoonMenu,
                defStyleAttr, 0);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);
            if (attr == R.styleable.MoonMenu_menu_position) {
                int value = a.getInt(attr, 0);
                switch (value) {
                    case 0:
                        position = Position.LEFT_TOP;
                        break;
                    case 1:
                        position = Position.RIGHT_TOP;
                        break;
                    case 2:
                        position = Position.LEFT_BOTTOM;
                        break;
                    case 3:
                        position = Position.RIGHT_BOTTOM;
                        break;
                }
            }
        }
        a.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //避免多次加载
        if (isOnce) {
            childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
                View childView = getChildAt(i);
                int width = childView.getMeasuredWidth();
                int height = childView.getMeasuredHeight();
                switch (position) {
                    case LEFT_TOP:
                        cl = 0;
                        ct = 0;
                        break;
                    case RIGHT_TOP:
                        cl = getMeasuredWidth() - width;
                        ct = 0;
                        break;
                    case LEFT_BOTTOM:
                        cl = 0;
                        ct = getMeasuredHeight() - height;
                        break;
                    case RIGHT_BOTTOM:
                        cl = getMeasuredWidth() - width;
                        ct = getMeasuredHeight() - height;
                        break;
                }
                childView.layout(cl, ct, cl + width, ct + height);
            }

            //主菜单按钮,布局里的最后一个View
            centerButton = getChildAt(childCount - 1);
            centerButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    RotateAnimation rotate;
                    if (isMenuClose) {
                        rotate = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f,
                                Animation.RELATIVE_TO_SELF, 0.5f);
                    } else {
                        rotate = new RotateAnimation(0f, -360f, Animation.RELATIVE_TO_SELF, 0.5f,
                                Animation.RELATIVE_TO_SELF, 0.5f);
                    }

                    rotate.setDuration(300);
                    rotate.setFillAfter(true);
                    centerButton.startAnimation(rotate);
                    menuAnim();
                    isMenuClose = !isMenuClose;
                }
            });
            isOnce = false;
        }
    }

    //子按钮展开动画
    private void menuAnim() {
        int moveDuration = 100;
        int delay = 50;
        int radius = (int) (getMeasuredWidth() * (1f / 3 + (childCount - 4) / 10f));
        for (int i = 0; i < childCount - 1; i++) {
            double angle = ((Math.PI / 2) / (childCount - 2) * i);
            final View child = getChildAt(i);
            int x = (position == Position.LEFT_BOTTOM || position == Position.LEFT_TOP) ? (int) (radius * Math.cos(angle)) : cl - (int) (radius * Math.cos(angle));
            int y = (position == Position.LEFT_TOP || position == Position.RIGHT_TOP) ? (int) (radius * Math.sin(angle)) : ct - (int) (radius * Math.sin(angle));
            final ObjectAnimator moveX;
            final ObjectAnimator moveY;
            ObjectAnimator alpha;
            if (isMenuClose) {
                moveX = ObjectAnimator.ofFloat(child, "x", cl, x);
                moveY = ObjectAnimator.ofFloat(child, "y", ct, y);
                child.setClickable(true);
                alpha = ObjectAnimator.ofFloat(child, "alpha", 0, 1);
            } else {
                moveX = ObjectAnimator.ofFloat(child, "x", x, cl);
                moveY = ObjectAnimator.ofFloat(child, "y", y, ct);
                alpha = ObjectAnimator.ofFloat(child, "alpha", 1, 0);
            }
            moveX.setInterpolator(new DecelerateInterpolator());
            moveY.setInterpolator(new DecelerateInterpolator());
            moveX.setStartDelay(delay * i);
            moveY.setStartDelay(delay * i);
            moveX.setDuration(moveDuration);
            moveY.setDuration(moveDuration);
            moveX.start();
            moveY.start();
            alpha.setStartDelay(delay * i);
            alpha.start();
            moveX.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    child.setVisibility(View.VISIBLE);
                }

                @Override
                public void onAnimationEnd(Animator animation) { /*前面设置为VISIBLE后有一个子按钮人不能显示,未找到原因。 在此处设置后能却能显示,知道原因的朋友请告知博主。*/
                    child.setVisibility(View.VISIBLE);
                }

                @Override
                public void onAnimationCancel(Animator animation) {
                }

                @Override
                public void onAnimationRepeat(Animator animation) {
                }
            });
            final int index = i;
            final int cx = x;
            final int cy = y;
            child.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    thisMenuItemAnim(index, cx, cy);
                    otherMenuItemAnim(index);
                    isMenuClose = true;
                    Toast.makeText(getContext(), "you click", Toast.LENGTH_SHORT).show();
                    Log.d("TAG", "click");
                }
            });
        }
    }

    //用户点击的子菜单的显示动画
    private void thisMenuItemAnim(int index, int cx, int cy) {
        final View thisMenuItem = getChildAt(index);
        Animation alphaAnim = new AlphaAnimation(1, 0);
        //ScaleAnimation的后两个参数,即缩放中心的xy坐标,所处坐标系原点是这个View本身的左上角
        Animation scaleAnim = new ScaleAnimation(1f, 4f, 1f, 4f, cx - cl + thisMenuItem.getMeasuredWidth() / 2, cy - ct + thisMenuItem.getMeasuredHeight() / 2);
        scaleAnim.setFillAfter(false);
        alphaAnim.setFillAfter(false);
        AnimationSet animationSet = new AnimationSet(true);
        animationSet.addAnimation(alphaAnim);
        animationSet.addAnimation(scaleAnim);
        animationSet.setDuration(200);
        thisMenuItem.startAnimation(animationSet);
        animationSet.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                thisMenuItem.setVisibility(View.GONE);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        thisMenuItem.setClickable(false);
    }

    //其他未点击的子菜单的自动消失动画
    private void otherMenuItemAnim(int index) {
        for (int i = 0; i < childCount - 1; i++) {
            final View otherMenuItem = getChildAt(i);
            if (i != index) {
                Animation alphaAnim = new AlphaAnimation(1, 0);
                alphaAnim.setDuration(200);
                alphaAnim.setFillAfter(false);
                otherMenuItem.startAnimation(alphaAnim);
                alphaAnim.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {
                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        otherMenuItem.setVisibility(View.GONE);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {
                    }
                });
                otherMenuItem.setClickable(false);
            }
        }
    }

    public enum Position {
        LEFT_TOP, RIGHT_TOP, RIGHT_BOTTOM, LEFT_BOTTOM
    }
}


其中的自定义属性,在 values 文件夹下新建 attrs.xml 。

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="menu_position" format="integer" >
        <enum name="left_top" value="0" />
        <enum name="right_top" value="1" />
        <enum name="right_bottom" value="2" />
        <enum name="left_bottom" value="3" />
    </attr>

    <declare-styleable name="MoonMenu">
        <attr name="menu_position" />
    </declare-styleable>
</resources>

效果如图




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值