VIEW主文件
/**
*
*/
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;
}
}
}
attrs.xml
<?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.可以用于解锁界面等.下面是效果图.周边圆环拖动到中间区域内则响应触发事件.不在区域之内则回到原来的地方