android一个转盘效果的容器viewgroup

来源:互联网 发布:js iso时间格式 编辑:程序博客网 时间:2024/05/17 02:03

最近看到建设银行的主页面里面有一个带旋转效果的,心血来潮,正好公司最近活比较少,就花时间自己写了一个先上一下效果图


 * 转盘viewgroup,将会已转盘的形式排列所有子view,view之间间距一样,所以不要添加过多的view
 * 支持长按删除
 * 支持复位播放音效




图有点大,也不知道如何缩小,大家凑合看看

代码其实也比较简单,我就贴出来比较重要的代码让大家看看

首先当然是手势的处理,我是把一个圆圈用一个“X”型,给他分成四部分

private int checkArea(float x, float y){int locationInWindow[] = new int[2];getLocationInWindow(locationInWindow);int parentX = locationInWindow[0] + getWidth()/2;int parentY = locationInWindow[1] + getHeight()/2;double distance = Math.sqrt((parentX - x)*(parentX - x) + (parentY - y)*(parentY - y));//两个点之间的距离double disY = Math.abs(y - parentY);double radian = Math.asin(disY/distance);double angle = (radian / Math.PI) * 180;if(y <= parentY && x <= parentX){// 1,4象限if(angle < 45)return 4;elsereturn 1;}else if(y <= parentY && x >= parentX){ //1,2象限if(angle <=90 && angle >=45)return 1;elsereturn 2;}else if(y >= parentY && x >= parentX){//2,3象限if(angle <= 45)return 2;elsereturn 3;}else{// 3,4象限if(angle < 45)return 4;elsereturn 3;}}
不同的象限所处理的手势也不一样,为了简单方便,1.3象限只处理x轴的滑动,2,4象限只处理y轴的滑动

case MotionEvent.ACTION_MOVE:area = checkArea(event.getRawX(), event.getRawY());float moveY = event.getRawY() - lastY;float moveX = event.getRawX() - lastX;switch (area) {case 1:turnClockwise(moveX);speed = moveX;break;case 2:turnClockwise(moveY);speed = moveY;break;case 3:turnClockwise(-moveX);speed = -moveX;break;case 4:turnClockwise(-moveY);speed = -moveY;break;}lastX = event.getRawX();lastY = event.getRawY();break;
旋转函数
private void turnClockwise(float move){float angle = move / 5;for(int i=0 ; i<location.size() ; i++){location.get(i).setNumber((location.get(i).getNumber() + angle)%360);if(location.get(i).getNumber() >= -10 && location.get(i).getNumber() <= 10 ){//需要一个范围if(location.get(i).isFlag()){sound.onPlaySound();location.get(i).setFlag(false); //用于表示该图标已经播放完声音}}else{location.get(i).setFlag(true);}}requestLayout();//重新计算每个子view的位置//invalidate();}

还有遇到最大的问题就是touchevent的冲突,由于父控件处理了所有的touchevent,所以子控件没收到touchevent,于是就用了SimpleOnGestureListener来处理,再onTouchEvent函数里面将每一个touchevent都传到SimpleOnGestureListener里面,接着重写onSingleTapUp函数来处理单击事件即可,虽然这样也能够处理了,但是感觉效果还是不太好,如果来处理子空间的滑动动作呢?

private class MyGestureDetectorListener extends SimpleOnGestureListener{/** * down事件 */@Overridepublic boolean onDown(MotionEvent arg0) {return false;}/** * 滑动手势事件;Touch了滑动一点距离后,在ACTION_UP时才会触发       参数:e1 第1个ACTION_DOWN MotionEvent 并且只有一个;e2 最后一个ACTION_MOVE MotionEvent ;velocityX X轴上的移动速度,像素/秒 ;velocityY Y轴上的移动速度,像素/秒.触发条件:X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒 */@Overridepublic boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2,float arg3) {return false;}/** * 长按事件;Touch了不移动一直Touch down时触发  */@Overridepublic void onLongPress(MotionEvent arg0) {viewIsBeingLongClick = getChildAt(checkClickChild(arg0.getX(), arg0.getY()));//initPopUpMenu(); ---1//showContextMenuForChild(viewIsBeingLongClick); ---2//menu.show();initPopUpWindow();window.showAsDropDown(viewIsBeingLongClick);}/** * 拖动事件。无论是用手拖动view,或者是以抛的动作滚动,都会多次触发,这个方法在ACTION_MOVE动作发生时就会触发        抛:手指触动屏幕后,稍微滑动后立即松开onDown-----》onScroll----》onScroll----》onScroll----》………----->onFling 拖动onDown------》onScroll----》onScroll------》onFiling */@Overridepublic boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2,float arg3) {return false;}/** * down事件发生而move或则up还没发生前触发该   事件;Touch了还没有滑动时触发(与onDown,onLongPress)比较onDown只要Touch down一定立刻触发。而Touchdown后过一会没有滑动先触发onShowPress再是onLongPress。所以Touchdown后一直不滑动按照onDown->onShowPress->onLongPress这个顺序触发。 */@Overridepublic void onShowPress(MotionEvent arg0) {}/** * 一次点击up事件;在touch down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touchup时触发。 点击一下非常快的(不滑动)Touchup:onDown->onSingleTapUp->onSingleTapConfirmed           点击一下稍微慢点的(不滑动)Touchup:onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed */@Overridepublic boolean onSingleTapUp(MotionEvent arg0) {if(listener != null){int i = checkClickChild(arg0.getX(), arg0.getY());if( i != -1)listener.onClick((String) getChildAt(i).getTag());}return false;}}
点我下载

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

最近又重写了一下,发现oninterceptouchevent函数直接返回true这种做法非常不合理,甚至说是错误的,因为这样一定会造成子控件接收不到touchevent,所以参照scrollview的解决方法又重写了一份,第一份就不删了,可以参考作为错误的方法

第二版本源码点我下载


1 0
原创粉丝点击