组合控件(优酷菜单)一

自定义控件实现三种方式:

1.继承viewviewgroup

2.继承已有的自定义控件,对已有的功能进行增强

3.组合方式,把控件组合到一起


自定义控件常用的三个方法:

1.onMeasure:测量view的大小   

2.onLayout :对子view进行排版  

3.onDraw :画出控件



1布局

里有3菜单,每个菜单中有一些按钮,可以用3个容器RelativeLayout)来表示3菜单,往里面添加按钮即可。(注:每个菜单都是一个半圆菜单的宽是直径,高是半径,所以宽是高的两倍)

 

注意3菜单布局的顺序,先men3,然后menu2然后menu1,顺序不能反,因为越往后的菜单越在界面的上方,这样面积最小的菜单1在最上方,菜单1会遮挡到下面的菜单2菜单3

2、控件的初始化

   

public class MainActivity extends Activity implements OnClickListener {
 
private RelativeLayout rl_menu3;
private RelativeLayout rl_menu2;
private RelativeLayout rl_menu1;
 
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rl_menu3 = (RelativeLayout) findViewById(R.id.rl_menu3);
        rl_menu2 = (RelativeLayout) findViewById(R.id.rl_menu2);
        rl_menu1 = (RelativeLayout) findViewById(R.id.rl_menu1);
        findViewById(R.id.btn_menu2).setOnClickListener(this);
        findViewById(R.id.btn_menu1).setOnClickListener(this);
    }
 
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_menu2:	// 单击菜单2按钮

break;
case R.id.btn_menu1:	// 单击菜单1按钮

break;
}
}
}


3、整体思路

代码的时候可以先整体思路,再写具体实现,如下为整体思路:

private boolean menu3Showing = true;
	private boolean menu2Showing = true;

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_menu2:	// 单击菜单2按钮
			if (menu3Showing) {
				// 隐藏菜单3
			} else {
				// 显示菜单3
			}
			menu3Showing = !menu3Showing;
			break;
		case R.id.btn_menu1:	// 单击菜单1按钮
			if (menu3Showing) {
				// 隐藏菜单3
				menu3Showing = false;

				// 隐藏菜单2(延迟)
			} else if (menu2Showing) {
				// 隐藏菜单2
			} else {
				// 显示菜单2
			}
			
			menu2Showing = !menu2Showing;
			break;
		}
	}


4、实现菜单旋转

面已经整体把握了思路,就差细节了,细节就是怎么菜单旋转起来,通过观察会发现3菜单的显示和隐藏效果都是一样的,所以显示和隐藏菜单的功能应该方法,方便,使用”先使用后创建技巧创建如下方法:

 

public class Utils {
	

	/** 隐藏菜单 */
	public static void hideMenu(View view) {
		float fromDegrees = 0f;			// 旋转的起始角度
		float toDegrees = -180f;			// 旋转的结束角度
		long startOffset = 0L;			// 动画开启的延迟时间
		int pivotXType = RotateAnimation.RELATIVE_TO_SELF;	// 指定旋转点x方向参照物
		int pivotYType = RotateAnimation.RELATIVE_TO_SELF;	// 指定旋转点y方向参照物
		float pivotXValue = 0.5f;		// 指定旋转点在x轴的位置
		float pivotYValue = 1.0f;		// 指定旋转点在y轴的位置
		RotateAnimation ra = new RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue);
		ra.setDuration(500);				// 指定动画的执行时间
		ra.setFillAfter(true);			// 让动画保持在结束状态
		ra.setStartOffset(startOffset);	// 指定动画延迟启动的时间
		view.startAnimation(ra);			// 开启动画
	}
	
}


   运行查看效果。

实现了隐藏之后,显示的就很简单了,跟隐藏是差不多的,只不过是旋转的角度不一样,隐藏是从0 -180,显示是从-180转0使用“方法抽取方式对上面的代码进行抽取,修改后如下:

   

public class Utils {

	/** 隐藏菜单 */
	public static void hideMenu(View view) {
		rotateView(view, 0f, -180f, 0L);
	}
	
	/** 隐藏菜单 */
	public static void hideMenu(View view, long startOffset) {
		rotateView(view, 0f, -180f, startOffset);
	}
	
	/** 显示菜单 */
	public static void showMenu(View view) {
		rotateView(view, -180f, 0f, 0L);
	}

	/**
	 * 旋转View
	 * @param view 要旋转的View
	 * @param fromDegrees 旋转的起始角度
	 * @param toDegrees 旋转的结束角度
	 * @param startOffset 动画启动的延迟时间
	 */
	private static void rotateView(View view, float fromDegrees, float toDegrees, long startOffset) {
		int pivotXType = RotateAnimation.RELATIVE_TO_SELF;	// 指定旋转点x方向参照物
		int pivotYType = RotateAnimation.RELATIVE_TO_SELF;	// 指定旋转点y方向参照物
		float pivotXValue = 0.5f;		// 指定旋转点在x轴的位置
		float pivotYValue = 1.0f;		// 指定旋转点在y轴的位置
		RotateAnimation ra = new RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue);
		ra.setDuration(500);				// 指定动画的执行时间
		ra.setFillAfter(true);			// 让动画保持在结束状态
		ra.setStartOffset(startOffset);	// 指定动画延迟启动的时间
		view.startAnimation(ra);			// 开启动画
	}
}


   在单击菜单的时候调用相应的工具类方法可,如下:

@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_menu2:	// 单击菜单2按钮
			if (menu3Showing) {
				// 隐藏菜单3
				Utils.hideMenu(rl_menu3);
			} else {
				// 显示菜单3
				Utils.showMenu(rl_menu3);
			}
			menu3Showing = !menu3Showing;
			break;
		case R.id.btn_menu1:	// 单击菜单1按钮
			
			if (menu3Showing) {
				// 隐藏菜单3
				Utils.hideMenu(rl_menu3);
				menu3Showing = false;
				
				// 隐藏菜单2(延迟)
				Utils.hideMenu(rl_menu2, 300);
			} else if (menu2Showing) {
				// 隐藏菜单2
				Utils.hideMenu(rl_menu2);
			} else {
				// 显示菜单2
				Utils.showMenu(rl_menu2);
			}
			
			menu2Showing = !menu2Showing;
			break;
		}
	}


   

5、菜单隐藏后,点击原来位置问题

菜单隐藏后在原来按钮位置击还是可以响应点击事件的

 

解决方案:遍历菜单中所有的控件,设置控件的clickable属性。修改Utils类,如下,红色代码为新增代码:

/**
	 * 设置View是否可以点击
	 * @param view
	 * @param clickable 是否可以点击
	 */
	private static void setViewClickable(View view, boolean clickable) {
		view.setClickable(clickable);
		if (view instanceof ViewGroup) {	// 如果是一个容器,则遍历这个容器中的所有子View
			ViewGroup viewGroup = (ViewGroup) view;
			for (int i = 0; i < viewGroup.getChildCount(); i++) {
				View child = viewGroup.getChildAt(i);
				child.setClickable(clickable);
			}
		}
	}

	/** 隐藏菜单 */
	public static void hideMenu(View view) {
		rotateView(view, 0f, -180f, 0L);
		setViewClickable(view, false);
	}
	
	/** 隐藏菜单 */
	public static void hideMenu(View view, long startOffset) {
		rotateView(view, 0f, -180f, startOffset);
		setViewClickable(view, false);
	}
	
	/** 显示菜单 */
	public static void showMenu(View view) {
		rotateView(view, -180f, 0f, 0L);
		setViewClickable(view, true);
	}


6、快速点击按钮问题

快速点击按钮时会发现菜单还没隐藏完就开始显示了,或者还没显示完又隐藏了,解决方案:监听动画的开启次数来判断是否需要执行

   给动画类添加一个监听器,修改Utils类,如下,红色代码为新增代码

private static void rotateView(View view, float fromDegrees, float toDegrees, long startOffset) {
		。。。之前的代码
		ra.setAnimationListener(listener);	// 设置动画监听器	
		view.startAnimation(ra);		// 开启动画
	}
	
	/** 动画开启的次数 */
	private static int startCount = 0;
	
	static AnimationListener listener = new AnimationListener() {
		
		@Override
		public void onAnimationStart(Animation animation) {
			startCount++;
		}
		
		@Override
		public void onAnimationRepeat(Animation animation) {
			
		}
		
		@Override
		public void onAnimationEnd(Animation animation) {
			startCount--;
		}
	};
	
	/**
	 * 是否还有动画在执行
	 * @return
	 */
	public static boolean hasAnimExecuting() {
		return startCount > 0;
	}


   

   在处理按钮的击事件之前先判断一下是否还有动画在执行,如果不再执行,修改MainActivity的按钮点击事件,如下:

        if (Utils.hasAnimExecuting()) {
            return;
        }


   


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值