Android自定义控件:优酷菜单

常用控件回顾

  1. 按钮控件(ButtonImageButton)
    ImageButton继承自ImageView,只显示图片;Button继承自TextView,用于显示文字。
  2. 进度条Progressbar
    继承自View,显示正在运行的状态。有两种显示形式:环形和水平。通过style属性来改变样式。在这里插入图片描述
  3. 单选按钮(RadioButton)和复选按钮(CheckBox)
    都继承自CompoundButton,都只有选中和未选中两种状态,可以通过checked属性来设置。不同的是,在一个RadioGroup中只能有一个RadioButton处于选中状态,CheckBox则可以有多个按钮被选中。
  4. 状态开关按钮(ToggleButton)
    继承自CompoundButton,状态只能是选中和未选中,并且需要为不同的状态设置不同的显示文本。
  5. 时钟控件(AnalogClock)和(DigitalClock)
    AnalogClock继承自View,用于显示模拟时钟,只显示时针和分针;DigitalClock继承自TextView,用于显示数字时钟可精确到秒。

布局文件实现

  1. 效果展示

Android自定义View实现优酷菜单效果展示


2. activity_youkumenu.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/three"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_width="320dp"
        android:layout_height="160dp"
        android:background="@drawable/three">

        <ImageView
            android:id="@+id/img1"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/jiehuan"
            android:tint="#ffffff"
            android:layout_alignParentBottom="true"
            android:layout_marginLeft="15dp"
            android:layout_marginBottom="5dp"/>

        <ImageView
            android:id="@+id/img2"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/cheliangdangan"
            android:tint="#ffffff"
            android:layout_above="@id/img1"
            android:layout_marginBottom="20dp"
            android:layout_marginLeft="40dp"/>

        <ImageView
            android:id="@+id/img3"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/cheliangliebiao"
            android:tint="#ffffff"
            android:layout_above="@id/img2"
            android:layout_marginBottom="20dp"
            android:layout_marginLeft="80dp"/>

        <ImageView
            android:id="@+id/img4"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/cheliangxinxi"
            android:tint="#ffffff"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="10dp"/>

        <ImageView
            android:id="@+id/img7"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/cheliangyiban"
            android:tint="#ffffff"
            android:layout_alignParentRight="true"
            android:layout_alignParentBottom="true"
            android:layout_marginRight="10dp"
            android:layout_marginBottom="5dp"/>

        <ImageView
            android:id="@+id/img6"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/weixiu"
            android:tint="#ffffff"
            android:layout_above="@id/img7"
            android:layout_marginBottom="20dp"
            android:layout_marginRight="30dp"
            android:layout_alignParentRight="true"/>

        <ImageView
            android:id="@+id/img5"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/zuche"
            android:tint="#ffffff"
            android:layout_above="@id/img6"
            android:layout_marginBottom="20dp"
            android:layout_marginRight="80dp"
            android:layout_alignParentRight="true" />


    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/two"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_width="220dp"
        android:layout_height="110dp"
        android:background="@drawable/two">

        <ImageView
            android:src="@drawable/baoyang"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="15dp"/>

        <ImageView
            android:id="@+id/menu"
            android:src="@drawable/chakan"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="10dp"/>

        <ImageView
            android:src="@drawable/cheliang"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_marginRight="15dp"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="20dp"/>
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/one"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_width="120dp"
        android:layout_height="60dp"
        android:background="@drawable/one">

        <ImageView
            android:id="@+id/home"
            android:src="@drawable/xinzeng"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="25dp"/>
    </RelativeLayout>

</RelativeLayout>

  1. 效果图展示
    在这里插入图片描述

代码处理逻辑

1.YouKuMenu.java

package com.swpuiot.test;

import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class YouKuMenu extends AppCompatActivity {

    private ImageView home,menu;
    private RelativeLayout one,two,three;

    //是否显示第三个圆环
    private boolean isShow3 = true;
    //是否显示第二个圆环
    private boolean isShow2 = true;
    //是否显示第一个圆环
    private boolean isShow1 = true;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_youkumenu);

        initView();

        //设置点击事件
        MyOnclickListener myOnclickListener = new MyOnclickListener();
        home.setOnClickListener(myOnclickListener);
        menu.setOnClickListener(myOnclickListener);
    }

    class MyOnclickListener implements View.OnClickListener{

        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.home:
                    //如果三级菜单和二级菜单是显示的,都设置隐藏
                    if(isShow2){
                        //隐藏二级菜单
                        isShow2 = false;
                        Tools.hideView(two,0);

                        if(isShow3){
                            //隐藏三级菜单
                            isShow3 = false;
                            Tools.hideView(three, 200);
                        }
                    }else {
                        //如果都是隐藏,显示二级菜单
                        isShow2 = true;
                        Tools.showView(two,0);
                    }
                    break;
                case R.id.menu:
                    if(isShow3){
                        //隐藏
                        isShow3 = false;
                        Tools.hideView(three,0);
                    }else{
                        //显示
                        isShow3 = true;
                        Tools.showView(three,0);
                    }
                    break;
            }
        }
    }

    private void initView() {
        home = findViewById(R.id.home);
        menu = findViewById(R.id.menu);
        one = findViewById(R.id.one);
        two = findViewById(R.id.two);
        three = findViewById(R.id.three);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode == KeyEvent.KEYCODE_MENU){
            //如果一级,二级,三级菜单是显示的,就全部隐藏
            if(isShow1){
                isShow1 = false;
                Tools.hideView(one,0);
                if(isShow2){
                    //隐藏二级菜单
                    isShow2 = false;
                    Tools.hideView(two,200);
                    if(isShow3){
                        //隐藏三级菜单
                        isShow3 = false;
                        Tools.hideView(three,400);
                    }
                }
            }else{
                //如果一级,二级菜单隐藏,就显示
                //显示一级菜单
                isShow1 = true;
                Tools.showView(one,0);
                //显示二级菜单
                isShow2 = true;
                Tools.showView(two,200);
            }
        }
        return super.onKeyDown(keyCode, event);
    }
}
  1. Tools.java
package com.swpuiot.test;

import android.animation.ObjectAnimator;
import android.view.View;
import android.view.animation.RotateAnimation;

/**
 * 显示和隐藏指定控件
 */

class Tools {

    public static void hideView(View view, long startOffset) {
        //方法一:视图动画
        RotateAnimation ra = new RotateAnimation(0, 180, view.getWidth()/2, view.getHeight());
        //设置动画播放持续的时间
        ra.setDuration(500);
        //动画停留在播放完成的状态
        ra.setFillAfter(true);
        //延迟多久后播放动画
        ra.setStartOffset(startOffset);
        view.startAnimation(ra);
    }

    public static void showView(View view, long startOffset) {
        //方法一:视图动画
        RotateAnimation ra = new RotateAnimation(180, 360, view.getWidth()/2, view.getHeight());
        //设置动画播放持续的时间
        ra.setDuration(500);
        //动画停留在播放完成的状态
        ra.setFillAfter(true);
        ra.setStartOffset(startOffset);
        view.startAnimation(ra);
        }
    }
}

解决bug的两种方法(ViewGroup和属性动画)

使用上面的Tools.java文件,我们会发现当点击物理按键menu时,一级、二级、三级菜单旋转180°隐藏之后点击隐藏掉的控件位置时仍然可以对控件进行操作,这是bug。

  1. 方法一:视图动画。使用ViewGroup,因为ViewGoup能够对子控件进行操作,而View则不能实现对子控件的操作。修改代码如下:
package com.swpuiot.test;

import android.animation.ObjectAnimator;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.RotateAnimation;

/**
 * 显示和隐藏指定控件
 */

class Tools {

    public static void hideView(ViewGroup view, long startOffset) {
        //方法一:视图动画
        RotateAnimation ra = new RotateAnimation(0, 180, view.getWidth()/2, view.getHeight());
        //设置动画播放持续的时间
        ra.setDuration(500);
        //动画停留在播放完成的状态
        ra.setFillAfter(true);
        //延迟多久后播放动画
        ra.setStartOffset(startOffset);
        view.startAnimation(ra);

        //设置不可点击
        for (int i = 0; i < view.getChildCount(); i++) {
            View children = view.getChildAt(i);
            children.setEnabled(false);
        }

    }

    public static void showView(ViewGroup view, long startOffset) {
        //方法一:视图动画
        RotateAnimation ra = new RotateAnimation(180, 360, view.getWidth()/2, view.getHeight());
        //设置动画播放持续的时间
        ra.setDuration(500);
        //动画停留在播放完成的状态
        ra.setFillAfter(true);
        ra.setStartOffset(startOffset);
        view.startAnimation(ra);

        //设置可点击
        for (int i = 0; i < view.getChildCount(); i++) {
            View children = view.getChildAt(i);
            children.setEnabled(true);
        }
    }
}
  1. 使用属性动画:
package com.swpuiot.test;

import android.animation.ObjectAnimator;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.RotateAnimation;

/**
 * 显示和隐藏指定控件
 */

class Tools {

    public static void hideView(ViewGroup view, long startOffset) {
        //方法二:视图动画 --> 属性动画
        ObjectAnimator animator = new ObjectAnimator();
        animator.ofFloat(view,"rotation",0,180);
        animator.setDuration(500);
        animator.setStartDelay(startOffset);
        animator.start();

        view.setPivotX(view.getWidth()/2);
        view.setPivotY(view.getHeight());

    }

    public static void showView(ViewGroup view, long startOffset) {
        //方法二:视图动画 --> 属性动画
        ObjectAnimator animator = new ObjectAnimator();
        animator.ofFloat(view,"rotation",180,360);
        animator.setDuration(500);
        animator.setStartDelay(startOffset);
        animator.start();

        view.setPivotX(view.getWidth()/2);
        view.setPivotY(view.getHeight());
    }
}

说在最后面,在案例中所用到的图片均是在网上随意找的图片,所以大家可以自行准备一些图标进行试验。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值