• Android自己定义控件系列一:Android怎样实现老版优酷client三级环形菜单



    转载请附上本文链接:http://blog.csdn.net/cyp331203/article/details/40423727


    先来看看效果:




    一眼看上去好像还挺炫的,感觉比較复杂。。。实际上并不难,以下我们来看看怎样实现:

    基本素材就是以下三个:






    我们先来看看布局文件怎么写,实际上这里这三张图片都差点儿相同,我们这里使用RelativeLayout,方便兴许小图标的增加,基本就是centerInParentaliagnParentBottom,仅仅是外圈小图标的安排要略微注意一下,这里我们左半边图标以最左边的一个图标为基准,右半边的图标以最右边的一个图标为基准,在这里各自是iv_channel1iv_channel7


    <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"
        tools:context="${relativePackage}.${activityClass}" >
    
    
        <RelativeLayout
            android:id="@+id/level1"
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:background="@drawable/level1" >
    
    
            <ImageView
                android:id="@+id/iv_icon_home"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerInParent="true"
                android:src="@drawable/icon_home" />
        </RelativeLayout>
    
    
        <RelativeLayout
            android:id="@+id/level2"
            android:layout_width="180dp"
            android:layout_height="90dp"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:background="@drawable/level2" >
    
    
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_margin="10dp"
                android:src="@drawable/icon_search" >
            </ImageView>
    
    
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_alignParentRight="true"
                android:layout_margin="10dp"
                android:src="@drawable/icon_myyouku" >
            </ImageView>
    
    
            <ImageView
                android:id="@+id/iv_icon_menu"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="5dp"
                android:src="@drawable/icon_menu" />
    
    
        </RelativeLayout>
    
    
        <RelativeLayout
            android:id="@+id/level3"
            android:layout_width="260dp"
            android:layout_height="130dp"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:background="@drawable/level3" >
    
    
            <ImageView
                android:id="@+id/iv_channel1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_marginBottom="10dp"
                android:layout_marginLeft="5dp"
                android:src="@drawable/channel1" />
    
    
            <ImageView
                android:id="@+id/iv_channel2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_above="@id/iv_channel1"
                android:layout_alignLeft="@id/iv_channel1"
                android:layout_marginBottom="7dp"
                android:layout_marginLeft="18dp"
                android:src="@drawable/channel2" />
    
    
    
    
            <ImageView
                android:id="@+id/iv_channel3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_above="@id/iv_channel2"
                android:layout_alignLeft="@id/iv_channel2"
                android:layout_marginBottom="2dp"
                android:layout_marginLeft="35dp"
                android:src="@drawable/channel3" />
    
    
            <ImageView
                android:id="@+id/iv_channel4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="5dp"
                android:src="@drawable/channel4" />
    
    
            <ImageView
                android:id="@+id/iv_channel7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_alignParentRight="true"
                android:layout_marginBottom="10dp"
                android:layout_marginRight="5dp"
                android:src="@drawable/channel7" />
    
    
            <ImageView
                android:id="@+id/iv_channel6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_above="@id/iv_channel7"
                android:layout_alignRight="@id/iv_channel7"
                android:layout_marginBottom="7dp"
                android:layout_marginRight="18dp"
                android:src="@drawable/channel6" />
    
    
            <ImageView
                android:id="@+id/iv_channel5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_above="@id/iv_channel6"
                android:layout_alignRight="@id/iv_channel6"
                android:layout_marginBottom="2dp"
                android:layout_marginRight="35dp"
                android:src="@drawable/channel5" />
        </RelativeLayout>
    
    </RelativeLayout>



    布局完之后的效果:




    之后我们就能够開始着手这个怎么实现,我们的基本想法是(小房子图标所在的为level1,第二圈灰色的部分为level2,最外圈为level3):

    1、点击小房子图标,假设level2和level3都处于显示状态,则将这两层都隐藏,假设这两层都不存在,则仅仅将level2显示出来;假设仅仅有level2显示着,那么将level2隐藏


    2、点击levle2的”三“字图标,则实现隐藏和显示level3组件


    3、点击手机的menu键,则实现假设level1,2,3都处于显示状态,则将三者都隐藏,假设仅仅有level1、level2显示,则将level1、2隐藏,假设仅仅有level1显示,则将level1隐藏;假设没有不论什么level显示着,则将level1和level2显示出来


    4、上面的显示和隐藏的过程,都使用动画来实现


    基本逻辑关系已经理清楚了,那么如今的问题就在于这个Animation怎样写;显然我们这里需要用到一个RotateAnimation旋转动画,因为这里牵涉到旋出和旋入的效果,我们必需要清楚这个动画的角度是怎样定的比方从0~180是旋入还是旋出效果

    经过实验,我们发现,RotateAnimation的角度例如以下,我们能够发现,它的角度定义是依照顺时针增长的



    那么依照这个角度来看,我们假设想要组件顺时针旋入,同一时候顺时针旋出的话,角度是要怎样确定的呢



    从上图能够比較easy看出来,顺时针旋出的话,角度是从0~180度,那么旋入呢?是不是从180~0度?,实际上这里旋入应该是180~360度

    相同的,假设这里想实现逆时针出入的话,角度能够设为0~-180和-180~-360度,留给大家自己试试。


    在角度确定好之后呢,我们能够来着手实现动画效果,这里因为三个组件level1、level2、level3的动画都是一致的,所以这里选择使用一个工具类,来实现几个静态方法,来定义动画,达到复用的效果:

    工具类例如以下:


    package com.alexchen.youkumenuexercise.utils;
    
    import android.view.View;
    import android.view.animation.RotateAnimation;
    
    public class AnimationUtils {
    	//旋出的动画,无延迟时间
    	public static void startAnimationOut(View view) {
    		startAnimationOut(view, 0);
    
    	}
    	//旋入的动画,无延迟时间
    	public static void startAnimationIn(View view) {
    		startAnimationIn(view, 0);
    	}
    	
    	//旋出的动画
    	//delay为动画延迟的时间,单位是毫秒
    	public static void startAnimationOut(View view, long delay) {
    		RotateAnimation animation = new RotateAnimation(0, 180,
    				view.getWidth() / 2, view.getHeight());
    		animation.setDuration(500);
    		animation.setStartOffset(delay);
    		animation.setFillAfter(true);
    		view.startAnimation(animation);
    
    	}
    	//旋入的动画
    	//delay为动画延迟的时间,单位是毫秒
    	public static void startAnimationIn(View view, long delay) {
    		RotateAnimation animation = new RotateAnimation(180, 360,
    				view.getWidth() / 2, view.getHeight());
    		animation.setDuration(500);
    		animation.setStartOffset(delay);
    		animation.setFillAfter(true);
    		view.startAnimation(animation);
    	}
    
    }
    



    当中设置了两个可以延时开启动画的方法,为的是让三个组件进出的时候可以体现出层次感,让用户体验更好。


    最后是Activity中的代码,这里没有做不论什么生命周期相关的处理,仅仅是简单的实现功能:


    package com.alexchen.youkumenuexercise;
    
    import com.alexchen.youkumenuexercise.utils.AnimationUtils;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.KeyEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    
    public class MainActivity extends Activity implements OnClickListener {
    
    	private RelativeLayout level1;
    	private RelativeLayout level2;
    	private RelativeLayout level3;
    
    	private ImageView iv_icon_menu;
    	private ImageView iv_icon_home;
    	/**
    	 * 表示level3是否是现状状态,默觉得true
    	 */
    	private boolean isLevel3In;
    	private boolean isLevel2In;
    	private boolean isLevel1In;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		isLevel3In = true;
    		isLevel2In = true;
    		isLevel1In = true;
    		initViews();
    		setOnclickListenersForViews();
    	}
    
    	/**
    	 * 设置views的监听事件
    	 */
    	private void setOnclickListenersForViews() {
    		iv_icon_home.setOnClickListener(this);
    		iv_icon_menu.setOnClickListener(this);
    
    	}
    
    	/**
    	 * 初始化须要的view组件
    	 */
    	private void initViews() {
    		level1 = (RelativeLayout) findViewById(R.id.level1);
    		level2 = (RelativeLayout) findViewById(R.id.level2);
    		level3 = (RelativeLayout) findViewById(R.id.level3);
    		iv_icon_menu = (ImageView) findViewById(R.id.iv_icon_menu);
    		iv_icon_home = (ImageView) findViewById(R.id.iv_icon_home);
    	}
    
    	/**
    	 * activity响应的点击事件
    	 */
    	@Override
    	public void onClick(View v) {
    		switch (v.getId()) {
    		case R.id.iv_icon_menu:
    			if (isLevel3In) {
    				// 假设level3是显示的,那么就让出去
    				AnimationUtils.startAnimationOut(level3);
    				isLevel3In = false;
    			} else {
    				// 假设level3是不显示的,那么让其进入
    				AnimationUtils.startAnimationIn(level3);
    				isLevel3In = true;
    			}
    
    			break;
    		case R.id.iv_icon_home:
    			if (isLevel2In) {
    				// 假设level2是显示状态
    				AnimationUtils.startAnimationOut(level2, 200);
    				isLevel2In = false;
    			} else {
    				AnimationUtils.startAnimationIn(level2);
    				isLevel2In = true;
    			}
    			if (isLevel3In) {
    				AnimationUtils.startAnimationOut(level3);
    				isLevel3In = false;
    			}
    
    			break;
    
    		default:
    			break;
    		}
    	}
    
    	@Override
    	public boolean onKeyDown(int keyCode, KeyEvent event) {
    		if (keyCode == KeyEvent.KEYCODE_MENU) {
    			// 假设是menu键按下的话:
    			changeLevelState();
    
    		}
    		return super.onKeyDown(keyCode, event);
    	}
    
    	/**
    	 * 改变三个圆环的状态
    	 */
    	private void changeLevelState() {
    		if (isLevel1In) {
    			AnimationUtils.startAnimationOut(level1, 400);
    			isLevel1In = false;
    		} else {
    			AnimationUtils.startAnimationIn(level1);
    			isLevel1In = true;
    		}
    		if (isLevel2In) {
    			AnimationUtils.startAnimationOut(level2, 200);
    			isLevel2In = false;
    		} else {
    			AnimationUtils.startAnimationIn(level2, 200);
    			isLevel2In = true;
    		}
    		if (isLevel3In) {
    			AnimationUtils.startAnimationOut(level3);
    			isLevel3In = false;
    		}
    	}
    
    }
    




  • 相关阅读:
    11.【原创】Object.keys()的一般用法
    5. 【原创】table设置text-overflow: ellipsis;(超出范围显示...)不生效
    12.【转载】vscode默认常用快捷键
    13.【原创】JS读取apk安装包的信息,做应用上传
    11.【原创】chrom文件上传后,手动释放内存
    26.Mysql "truncate"与"delete"的区别
    25.【转载】Mysql timestamp类型字段的CURRENT_TIMESTAMP与ON UPDATE CURRENT_TIMESTAMP属性
    bof
    ctf Wiener tricky
    分解大素数
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4544001.html
Copyright © 2020-2023  润新知