自定义View之圆形拖动DEMO

  1.   
  1. VIEW主文件  
  1. /** 
  2.   *  
  3.   */  
  4.  package com.android.circle;  
  5.    
  6.  import java.util.ArrayList;  
  7.  import java.util.List;  
  8.    
  9.  import android.content.ClipData;  
  10.  import android.content.ClipDescription;  
  11.  import android.content.Context;  
  12.  import android.content.Intent;  
  13.  import android.content.res.TypedArray;  
  14.  import android.graphics.Canvas;  
  15.  import android.graphics.Color;  
  16.  import android.graphics.Paint;  
  17.  import android.graphics.Paint.Style;  
  18.  import android.graphics.drawable.Drawable;  
  19.  import android.util.AttributeSet;  
  20.  import android.util.FloatMath;  
  21.  import android.util.Log;  
  22.  import android.view.DragEvent;  
  23.  import android.view.LayoutInflater;  
  24.  import android.view.MotionEvent;  
  25.  import android.view.View;  
  26.  import android.view.ViewGroup;  
  27.  import android.widget.ImageView;  
  28.  import android.widget.Toast;  
  29.    
  30.  public class CircleView extends ViewGroup {  
  31.     Paint mPaint;  
  32.     float mCenter_X, mCenter_Y;  
  33.     int mInnerRadius, mOuterRadius, mOuterSamllRadius, mCircleNumber;  
  34.     View mChild;  
  35.     double mDegree;  
  36.     LayoutInflater mLayoutInflater;  
  37.     ArrayList<CircleValue> mCircleValue = new ArrayList<CircleValue>();  
  38.     private onPenUpCallback mOnPenUpCallback;  
  39.       
  40.     /** 
  41.      * @param context 
  42.      * @param attrs 
  43.      */  
  44.     public CircleView(Context context, AttributeSet attrs) {  
  45.         super(context, attrs);  
  46.    
  47.         mPaint = new Paint();  
  48.    
  49.         TypedArray array = context.obtainStyledAttributes(attrs,  
  50.                 R.styleable.Circle);  
  51.         mInnerRadius = array.getDimensionPixelSize(  
  52.                 R.styleable.Circle_inner_radius, 50);  
  53.         mOuterRadius = array.getDimensionPixelSize(  
  54.                 R.styleable.Circle_outer_radius, 100);  
  55.         mOuterSamllRadius = array.getDimensionPixelSize(  
  56.                 R.styleable.Circle_outer_small_radius, 30);  
  57.         mCircleNumber = array.getInteger(R.styleable.Circle_number1, 4);  
  58.    
  59.         mLayoutInflater = LayoutInflater.from(getContext());  
  60.    
  61.         for (int i = 0; i < mCircleNumber; i++) {  
  62.             mChild = mLayoutInflater.inflate(R.layout.circle_item, null);  
  63.             mChild.setTag("" + i);  
  64.             mChild.setOnTouchListener(new View.OnTouchListener() {  
  65.                 float down_x=0 , down_y=0 , curr_x=0 , curr_y=0;  
  66.                 @Override  
  67.                 public boolean onTouch(View v, MotionEvent event) {  
  68.                     String _id = v.getTag().toString();  
  69.                     int id = Integer.parseInt(_id);  
  70.                       
  71.                     switch (event.getAction()) {  
  72.                     case MotionEvent.ACTION_DOWN:  
  73.                         down_x = event.getRawX();  
  74.                         down_y = event.getRawY();  
  75.                         break;  
  76.                     case MotionEvent.ACTION_MOVE:  
  77.                         curr_x = event.getRawX();  
  78.                         curr_y = event.getRawY();  
  79.                         moveView(v,id,down_x ,  down_y, curr_x , curr_y);  
  80.                           
  81.                         break;  
  82.                     case MotionEvent.ACTION_UP:  
  83.                     case MotionEvent.ACTION_CANCEL:  
  84.                           
  85.                         boolean ret = checkUp(v);  
  86.                         if(ret == true)  
  87.                         {  
  88.                             mOnPenUpCallback.CallBack();  
  89.                         }  
  90.                         else  
  91.                         {  
  92.                             CircleValue value =  getOriginalValue(id);  
  93.                             v.layout(value.left ,value.top , value.right , value.buttom);  
  94.                         }  
  95.                         break;  
  96.                           
  97.                     default:  
  98.                         break;  
  99.                     }  
  100.    
  101.                     return true;  
  102.                 }  
  103.             });  
  104.    
  105.             addView(mChild, i);  
  106.         }  
  107.    
  108.         array.recycle();  
  109.    
  110.     }  
  111.     public void setPenUpCallBack(onPenUpCallback c)  
  112.     {  
  113.         mOnPenUpCallback = c;  
  114.     }  
  115.       
  116.     private boolean checkUp(View v)  
  117.     {  
  118.         float x = v.getX()+v.getWidth()/2;  
  119.         float y = v.getY()+v.getHeight()/2;  
  120.           
  121.         float gx = Math.abs(x-mCenter_X);  
  122.         float gy = Math.abs(y-mCenter_Y);  
  123.           
  124.         double d = (double)(gx*gx + gy*gy);  
  125.         double radius = Math.sqrt(d);  
  126.    
  127.         if(radius < mInnerRadius)  
  128.         {  
  129.             return true;  
  130.         }  
  131.         else  
  132.         {  
  133.             return false;  
  134.         }  
  135.     }  
  136.       
  137.     private void moveView(View v, int id ,float down_x , float down_y, float curr_x ,float curr_y )  
  138.     {  
  139.         CircleValue value =  getOriginalValue(id);  
  140.         int gap_x , gap_y ;  
  141.           
  142.         gap_x = (int)(curr_x - down_x);  
  143.         gap_y = (int)(curr_y - down_y);  
  144.         v.layout(value.left+ gap_x,value.top+gap_y , value.right + gap_x , value.buttom + gap_y);  
  145.     }  
  146.       
  147.     public void onDraw(Canvas canvas) {  
  148.         super.onDraw(canvas);  
  149.    
  150.         mPaint.setStyle(Style.FILL);  
  151.         mPaint.setColor(Color.GRAY);  
  152.         canvas.drawCircle(mCenter_X, mCenter_Y, mOuterRadius, mPaint);  
  153.    
  154.         mPaint.setStyle(Style.FILL);  
  155.         mPaint.setColor(Color.GREEN);  
  156.         canvas.drawCircle(mCenter_X, mCenter_Y, mInnerRadius, mPaint);  
  157.    
  158.     }  
  159.    
  160.     private float calcCircleX(int index) {  
  161.         float x = 0;  
  162.         float degree = (float) mDegree * index;  
  163.    
  164.         x = FloatMath.sin(degree) * mOuterRadius;  
  165.         return mCenter_X + x;  
  166.     }  
  167.    
  168.     private float calcCircleY(int index) {  
  169.         float y = 0;  
  170.         float degree = (float) mDegree * index;  
  171.    
  172.         y = FloatMath.cos(degree) * mOuterRadius;  
  173.         return mCenter_Y - y;  
  174.     }  
  175.    
  176.     protected void onLayout(boolean changed, int left, int top, int right,  
  177.             int bottom) {  
  178.         mDegree = 2 * Math.PI / getChildCount();  
  179.         mCenter_X = getMeasuredWidth() >> 1;  
  180.         mCenter_Y = getMeasuredHeight() >> 1;  
  181.    
  182.         for (int i = 0; i < getChildCount(); i++) {  
  183.             View child = getChildAt(i);  
  184.    
  185.             int w = child.getMeasuredWidth();  
  186.             int h = child.getMeasuredHeight();  
  187.    
  188.             child.measure(w, h);  
  189.    
  190.             float cx = calcCircleX(i);  
  191.             float cy = calcCircleY(i);  
  192.             int sx = (int) cx - (w >> 1);  
  193.             int sy = (int) cy - (h >> 1);  
  194.    
  195.             child.layout(sx, sy, sx + w, sy + h);  
  196.             if(w!=0 && h!=0)  
  197.             {  
  198.                 CircleValue mValue = new CircleValue(sx, sy, sx + w, sy + h);  
  199.                 mCircleValue.add(mValue);  
  200.             }  
  201.         }  
  202.     }  
  203.       
  204.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  205.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  206.         setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);  
  207.     }  
  208.    
  209.     private CircleValue getOriginalValue(int id)  
  210.     {  
  211.         return mCircleValue.get(id);  
  212.     }  
  213.       
  214.     public interface onPenUpCallback{  
  215.         public void CallBack();  
  216.     }  
  217.       
  218.     private class CircleValue {  
  219.         public int left, top, right, buttom;  
  220.    
  221.         public CircleValue() {  
  222.             left = 0;  
  223.             top = 0;  
  224.             right = 0;  
  225.             buttom = 0;  
  226.         }  
  227.           
  228.         public CircleValue(int l, int t, int r, int b) {  
  229.             left = l;  
  230.             top = t;  
  231.             right = r;  
  232.             buttom = b;  
  233.         }  
  234.           
  235.         public void setValue(int l, int t, int r, int b) {  
  236.             left = l;  
  237.             top = t;  
  238.             right = r;  
  239.             buttom = b;  
  240.         }  
  241.     }  
  242.  }  
  243.    
/**
  * 
  */
 package com.android.circle;
 
 import java.util.ArrayList;
 import java.util.List;
 
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Paint.Style;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.FloatMath;
 import android.util.Log;
 import android.view.DragEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.Toast;
 
 public class CircleView extends ViewGroup {
 	Paint mPaint;
 	float mCenter_X, mCenter_Y;
 	int mInnerRadius, mOuterRadius, mOuterSamllRadius, mCircleNumber;
 	View mChild;
 	double mDegree;
 	LayoutInflater mLayoutInflater;
 	ArrayList<CircleValue> mCircleValue = new ArrayList<CircleValue>();
 	private onPenUpCallback mOnPenUpCallback;
 	
 	/**
 	 * @param context
 	 * @param attrs
 	 */
 	public CircleView(Context context, AttributeSet attrs) {
 		super(context, attrs);
 
 		mPaint = new Paint();
 
 		TypedArray array = context.obtainStyledAttributes(attrs,
 				R.styleable.Circle);
 		mInnerRadius = array.getDimensionPixelSize(
 				R.styleable.Circle_inner_radius, 50);
 		mOuterRadius = array.getDimensionPixelSize(
 				R.styleable.Circle_outer_radius, 100);
 		mOuterSamllRadius = array.getDimensionPixelSize(
 				R.styleable.Circle_outer_small_radius, 30);
 		mCircleNumber = array.getInteger(R.styleable.Circle_number1, 4);
 
 		mLayoutInflater = LayoutInflater.from(getContext());
 
 		for (int i = 0; i < mCircleNumber; i++) {
 			mChild = mLayoutInflater.inflate(R.layout.circle_item, null);
 			mChild.setTag("" + i);
 			mChild.setOnTouchListener(new View.OnTouchListener() {
 				float down_x=0 , down_y=0 , curr_x=0 , curr_y=0;
 				@Override
 				public boolean onTouch(View v, MotionEvent event) {
 					String _id = v.getTag().toString();
 					int id = Integer.parseInt(_id);
 					
 					switch (event.getAction()) {
 					case MotionEvent.ACTION_DOWN:
 						down_x = event.getRawX();
 						down_y = event.getRawY();
 						break;
 					case MotionEvent.ACTION_MOVE:
 						curr_x = event.getRawX();
 						curr_y = event.getRawY();
 						moveView(v,id,down_x ,  down_y, curr_x , curr_y);
 						
 						break;
 					case MotionEvent.ACTION_UP:
 					case MotionEvent.ACTION_CANCEL:
 						
 						boolean ret = checkUp(v);
 						if(ret == true)
 						{
 							mOnPenUpCallback.CallBack();
 						}
 						else
 						{
 							CircleValue value =  getOriginalValue(id);
 							v.layout(value.left ,value.top , value.right , value.buttom);
 						}
 						break;
 						
 					default:
 						break;
 					}
 
 					return true;
 				}
 			});
 
 			addView(mChild, i);
 		}
 
 		array.recycle();
 
 	}
 	public void setPenUpCallBack(onPenUpCallback c)
 	{
 		mOnPenUpCallback = c;
 	}
 	
 	private boolean checkUp(View v)
 	{
 		float x = v.getX()+v.getWidth()/2;
 		float y = v.getY()+v.getHeight()/2;
 		
 		float gx = Math.abs(x-mCenter_X);
 		float gy = Math.abs(y-mCenter_Y);
 		
 		double d = (double)(gx*gx + gy*gy);
 		double radius = Math.sqrt(d);
 
 		if(radius < mInnerRadius)
 		{
 			return true;
 		}
 		else
 		{
 			return false;
 		}
 	}
 	
 	private void moveView(View v, int id ,float down_x , float down_y, float curr_x ,float curr_y )
 	{
 		CircleValue value =  getOriginalValue(id);
 		int gap_x , gap_y ;
 		
 		gap_x = (int)(curr_x - down_x);
 		gap_y = (int)(curr_y - down_y);
 		v.layout(value.left+ gap_x,value.top+gap_y , value.right + gap_x , value.buttom + gap_y);
 	}
 	
 	public void onDraw(Canvas canvas) {
 		super.onDraw(canvas);
 
 		mPaint.setStyle(Style.FILL);
 		mPaint.setColor(Color.GRAY);
 		canvas.drawCircle(mCenter_X, mCenter_Y, mOuterRadius, mPaint);
 
 		mPaint.setStyle(Style.FILL);
 		mPaint.setColor(Color.GREEN);
 		canvas.drawCircle(mCenter_X, mCenter_Y, mInnerRadius, mPaint);
 
 	}
 
 	private float calcCircleX(int index) {
 		float x = 0;
 		float degree = (float) mDegree * index;
 
 		x = FloatMath.sin(degree) * mOuterRadius;
 		return mCenter_X + x;
 	}
 
 	private float calcCircleY(int index) {
 		float y = 0;
 		float degree = (float) mDegree * index;
 
 		y = FloatMath.cos(degree) * mOuterRadius;
 		return mCenter_Y - y;
 	}
 
 	protected void onLayout(boolean changed, int left, int top, int right,
 			int bottom) {
 		mDegree = 2 * Math.PI / getChildCount();
 		mCenter_X = getMeasuredWidth() >> 1;
 		mCenter_Y = getMeasuredHeight() >> 1;
 
 		for (int i = 0; i < getChildCount(); i++) {
 			View child = getChildAt(i);
 
 			int w = child.getMeasuredWidth();
 			int h = child.getMeasuredHeight();
 
 			child.measure(w, h);
 
 			float cx = calcCircleX(i);
 			float cy = calcCircleY(i);
 			int sx = (int) cx - (w >> 1);
 			int sy = (int) cy - (h >> 1);
 
 			child.layout(sx, sy, sx + w, sy + h);
 			if(w!=0 && h!=0)
 			{
 				CircleValue mValue = new CircleValue(sx, sy, sx + w, sy + h);
 				mCircleValue.add(mValue);
 			}
 		}
 	}
 	
 	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 		setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
 	}
 
 	private CircleValue getOriginalValue(int id)
 	{
 		return mCircleValue.get(id);
 	}
 	
 	public interface onPenUpCallback{
 		public void CallBack();
 	}
 	
 	private class CircleValue {
 		public int left, top, right, buttom;
 
 		public CircleValue() {
 			left = 0;
 			top = 0;
 			right = 0;
 			buttom = 0;
 		}
 		
 		public CircleValue(int l, int t, int r, int b) {
 			left = l;
 			top = t;
 			right = r;
 			buttom = b;
 		}
 		
 		public void setValue(int l, int t, int r, int b) {
 			left = l;
 			top = t;
 			right = r;
 			buttom = b;
 		}
 	}
 }
 
  1. attrs.xml   
attrs.xml 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.  <resources>  
  3.    
  4.      <declare-styleable name="Circle">  
  5.          <attr name="inner_radius" format="dimension" />  
  6.          <attr name="outer_radius" format="dimension" />  
  7.          <attr name="outer_small_radius" format="dimension" />  
  8.          <attr name="number1" format="integer" />  
  9.      </declare-styleable>  
  10.    
  11.  </resources>  
<?xml version="1.0" encoding="utf-8"?>
 <resources>
 
     <declare-styleable name="Circle">
         <attr name="inner_radius" format="dimension" />
         <attr name="outer_radius" format="dimension" />
         <attr name="outer_small_radius" format="dimension" />
         <attr name="number1" format="integer" />
     </declare-styleable>
 
 </resources>


此view只是一个demo.可以用于解锁界面等.下面是效果图.周边圆环拖动到中间区域内则响应触发事件.不在区域之内则回到原来的地方


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值