Android之仿优酷圆形菜单

本文详细介绍了如何设计并实现一个带有动画效果的圆形菜单。该菜单包含三个层级,通过不同的按钮控制显示与隐藏状态,并利用旋转动画实现了菜单的展开与收起。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先来看看这个圆形菜单的效果咯~


然后分析一下:

这个圆形菜单可以分为3个菜单~

1.一级菜单:即最里面的那个菜单

2.二级菜单:即最中间的那个菜单

3.三级菜单:即最外面的那个菜单

布局的话使用相对布局来控制这三个菜单的相对位置~

这个圆形菜单的功能就是一级菜单可以控制二级和三级菜单,

二级菜单可以控制三级菜单(从图片上可以看出是中间的按钮控制的)

那先看布局文件吧,采用三个相对布局,即每个菜单是一个相对布局

activity_main:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <!-- 三级菜单 -->
    <RelativeLayout 
        android:id="@+id/level3"
        android:layout_width="220dp"
        android:layout_height="110dp"
        android:background="@drawable/level3"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true">
        <ImageView 
            android:id="@+id/cha1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/channel1"
            android:layout_alignParentBottom="true"
            android:layout_marginLeft="5dp"/>
        <ImageView 
            android:id="@+id/cha2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/channel2"
            android:layout_above="@id/cha1"
            android:layout_marginBottom="6dp"
            android:layout_marginLeft="25dp"/>
        <ImageView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/channel3"
            android:layout_above="@id/cha2"
            android:layout_marginLeft="60dp"/>
        <ImageView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/channel4"
            android:layout_centerHorizontal="true"/>
        
         <ImageView 
            android:id="@+id/cha7"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/channel7"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_marginRight="5dp"/>
        <ImageView 
            android:id="@+id/cha6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/channel6"
            android:layout_above="@id/cha7"
            android:layout_marginBottom="6dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="25dp"/>
        <ImageView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/channel5"
            android:layout_above="@id/cha6"
            android:layout_marginRight="60dp"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>

    <!-- 二级菜单 -->
    <RelativeLayout 
        android:id="@+id/level2"
        android:layout_width="140dp"
        android:layout_height="70dp"
        android:background="@drawable/level2"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true">
        <ImageView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/icon_search"
            android:layout_alignParentBottom="true"
            android:layout_marginLeft="3dp"/>
        <ImageView 
            android:id="@+id/menu"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/icon_menu"
            android:layout_centerHorizontal="true"/>
         <ImageView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/icon_myyouku"
            android:layout_alignParentBottom="true"
            android:layout_marginRight="3dp"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    <!-- 一级菜单 -->
    <RelativeLayout 
        android:layout_width="80dp"
        android:layout_height="40dp"
        android:background="@drawable/level1"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true">
        <ImageView 
            android:id="@+id/home"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/icon_home"
            android:layout_centerInParent="true"/>
    </RelativeLayout>

</RelativeLayout>
布局文件写好,效果如图,只是现在是静态的而已,没有添加任何逻辑代码~



然后现在来分析下逻辑~先来看看home(即一级菜单中间那个按钮)

点击home按钮,会出现3种情况:

1.二级和三级都显示,那么就将二三级都隐藏掉

2.二三级都不显示,那么就只显示二级菜单

3.二级菜单显示但三级不显示,那么就将二级隐藏

当然我们要设置各标记位,来标记二级和三级的隐藏与显示~

那要如何隐藏和显示二级和三级菜单呢,我这里设置了动画来实现~

然后再看menu(即二级菜单中间的那个按钮)

点击menu按钮,会出现2种情况:

1.三级显示,就将三级隐藏

2.三级不显示,就将三级显示

MainActivity:

public class MainActivity extends Activity implements OnClickListener{

	private ImageView home;//一级菜单按钮
	private ImageView menu;//二级菜单按钮
	private boolean levea2Isplay=true,level3Isplay=true;
	private RelativeLayout level2,level3;
	
	private int animationCount=0;//记录有几个动画在执行
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		level2=(RelativeLayout) findViewById(R.id.level2);
		level3=(RelativeLayout) findViewById(R.id.level3);
		
		initView();
		
	}

	private void initView() {
		home=(ImageView) findViewById(R.id.home);
		menu=(ImageView) findViewById(R.id.menu);
		home.setOnClickListener(this);
		menu.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch (v.getId()) {
		case R.id.home:
			if(animationCount>0){
				return;
			}
			//点击home按钮的逻辑代码
			clickHome();
			break;
		case R.id.menu:
			if(animationCount>0){
				return;
			}
			clickMenu();
			break;
		default:
			break;
		}
			
	}
	private void clickMenu() {
		
		// TODO Auto-generated method stub
		//分情况考虑
		//1.三级显示,就将三级隐藏
		if(level3Isplay){
			hideMenu(level3,0);
			level3Isplay=false;
			return;
		}
		//2.三级不显示,就将三级显示
		if (!level3Isplay) {
			showMenu(level3);
			level3Isplay=true;
			return;
		}
	}

	private void clickHome() {
		// TODO Auto-generated method stub
		//分情况考虑
		//1.二级和三级都显示,那么就将二三级都隐藏掉
		if(levea2Isplay&&level3Isplay){
			//将二三级都隐藏掉,并且改变标记位
			hideMenu(level2,300);
			hideMenu(level3,500);
			levea2Isplay=false;
			level3Isplay=false;
			return;
		}
		//2.二三级都不显示,那么就只显示二级菜单
		if(!levea2Isplay&&!level3Isplay){
			//只显示二级菜单
			showMenu(level2);
			levea2Isplay=true;
			return;
		}
		//3.二级菜单显示但三级不显示,那么就将二级隐藏
		if (levea2Isplay&&!level3Isplay) {
			//将二级隐藏
			hideMenu(level2,0);
			levea2Isplay=false;
			return;
		}
	}

	/**
	 * 隐藏菜单
	 */
	private void hideMenu(RelativeLayout view,long startOffset){
		//如果要隐藏菜单,就要让控件不可点
		//获取父容器有几个子控件
		int count=view.getChildCount();
		for(int i=0;i<count;i++){
			view.getChildAt(i).setEnabled(false);
		}
		//view.setVisibility(View.GONE);
		//用动画来隐藏
		//旋转
		RotateAnimation animation=new RotateAnimation
				(0, -180,
						Animation.RELATIVE_TO_SELF, 0.5f, 
						Animation.RELATIVE_TO_SELF, 1.0f);
		animation.setAnimationListener(new AnimationListener() {
			
			@Override
			public void onAnimationStart(Animation animation) {
				// TODO Auto-generated method stub
				animationCount++;
			}
			
			@Override
			public void onAnimationRepeat(Animation animation) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onAnimationEnd(Animation animation) {
				// TODO Auto-generated method stub
				animationCount--;
			}
		});
		//设置动画的持续时间
		animation.setDuration(500);
		//设置菜单停留在动画结束的位置上
		animation.setFillAfter(true);
		//设置动画的延迟执行
		animation.setStartOffset(1000);
		view.startAnimation(animation);
		
	}
	
	/**
	 * 显示菜单
	 */
	private void showMenu(RelativeLayout view){
		
		int count=view.getChildCount();
		for(int i=0;i<count;i++){
			view.getChildAt(i).setEnabled(true);
		}
		//view.setVisibility(View.VISIBLE);
		//用动画来显示
				//旋转
				RotateAnimation animation=new RotateAnimation
						(-180, 0,
								Animation.RELATIVE_TO_SELF, 0.5f, 
								Animation.RELATIVE_TO_SELF, 1.0f);
				animation.setAnimationListener(new AnimationListener() {
					
					@Override
					public void onAnimationStart(Animation animation) {
						// TODO Auto-generated method stub
						animationCount++;
					}
					
					@Override
					public void onAnimationRepeat(Animation animation) {
						// TODO Auto-generated method stub
						
					}
					
					@Override
					public void onAnimationEnd(Animation animation) {
						// TODO Auto-generated method stub
						animationCount--;
					}
				});
				//设置动画的持续时间
				animation.setDuration(500);
				//设置菜单停留在动画结束的位置上
				animation.setFillAfter(true);
				//设置动画的延迟执行
				animation.setStartOffset(1000);
				view.startAnimation(animation);
	}

}
代码到这里就写完了~

源码:源码下载




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值