环形旋转图3

第三版:



        已实现功能:

1.底部向上滑动可以控制上面View的旋转。

package com.example.wavedemo;

import java.util.ArrayList;
import java.util.List;

import com.example.wavedemo.RollbackGroup.MyRollbackListener;
import com.example.wavedemo.RollbackGroup.MyScrollChangedListener;
import com.example.wavedemo.RotationView.OnRotateChangedListener;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity6 extends Activity {
	private List<RotateBean> lists;
	private RotationView rotationView;
	private ArrowView arrowView;
	private RollbackGroup rollbackGroup;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main7);
		rotationView = (RotationView) this.findViewById(R.id.rotateView);
		arrowView = (ArrowView) this.findViewById(R.id.arrowView);
		lists = new ArrayList<RotateBean>();
		lists.add(new RotateBean("+0.75", 40, "#7eb445"));
		lists.add(new RotateBean("+0.35", 160, "#819d87"));
		lists.add(new RotateBean("+0.25", 20, "#e61a5f"));
		lists.add(new RotateBean("+0.25", 140, "#000000"));
		rotationView.setData(lists);
		rotationView.setRotateListener(new OnRotateChangedListener() {

			@Override
			public void onRotate(int index) {
				arrowView.setColor(lists.get(index).getColor());
			}
		});
		rollbackGroup = (RollbackGroup) this.findViewById(R.id.rollbackGroup);

		// 滑动下面时,让上面一起滚动
		rollbackGroup.setMyScrollChangedListener(new MyScrollChangedListener() {

			@Override
			public void onScroll(int delta, int top, int perChildHeight) {
				int index = top / perChildHeight;
				int remainder = top % perChildHeight;
				if (index == 0) {
					if (remainder <= perChildHeight / 2) {
						rotationView.rotateWheel(lists.get(index).getDegrees()
								* 1.0f / 2 / (perChildHeight / 2) * delta);
					} else {
						rotationView.rotateWheel(lists.get(
								lists.size() - index - 1).getDegrees()
								* 1.0f / 2 / (perChildHeight / 2) * delta);
					}
				} else {
					index=lists.size()-index;
					if (remainder <= perChildHeight / 2) {
						rotationView.rotateWheel(lists.get(index).getDegrees()
								* 1.0f / 2 / (perChildHeight / 2) * delta);
					} else {
						rotationView.rotateWheel(lists.get(
								index - 1).getDegrees()
								* 1.0f / 2 / (perChildHeight / 2) * delta);
					}
				}
			}
		});
		// 滑动下面,让上面回滚
		rollbackGroup.setMyRollbackListener(new MyRollbackListener() {

			@Override
			public void onRollback(int degrees, int delTop, int perChildHeight) {
				int index = -delTop / perChildHeight;
				int remainder = delTop % perChildHeight;
				if (index == 0) {
					index = 0;
					if (Math.abs(remainder) < perChildHeight / 2) {
						rotationView.rotateWheel(lists.get(index).getDegrees()
								* 1.0f / 2 / (perChildHeight / 2) * remainder);

					} else {
						rotationView.rotateWheel(lists.get(
								lists.size() - index - 1).getDegrees()
								* 1.0f
								/ 2
								/ (perChildHeight / 2.0f)
								* (perChildHeight - Math.abs(remainder)));
					}
				} else {
					Log.e("abc", "index" + index);
					index = lists.size() - index;
					if (Math.abs(remainder) < perChildHeight / 2) {
						rotationView.rotateWheel(lists.get(index).getDegrees()
								* 1.0f / 2 / (perChildHeight / 2.0f)
								* remainder);

					} else {
						rotationView.rotateWheel(lists.get(index - 1)
								.getDegrees()
								* 1.0f/2
								/ (perChildHeight / 2)
								* (perChildHeight - Math.abs(remainder)));
					}
				}

			}
		});

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		return super.onOptionsItemSelected(item);
	}

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingTop="20dp" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:orientation="horizontal" >

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <com.example.wavedemo.RotationView
            android:id="@+id/rotateView"
            android:layout_width="match_parent"
            android:layout_height="250dp" />

        <View
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="|"
        android:textColor="#5d3d78"
        android:visibility="gone" />

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <com.example.wavedemo.ArrowView
            android:id="@+id/arrowView"
            android:layout_width="match_parent"
            android:layout_height="60dp" />

        <com.example.wavedemo.RollbackGroup
            android:id="@+id/rollbackGroup"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="20dp"
            android:orientation="vertical" >

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical" >

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="40dp"
                    android:gravity="center"
                    android:textColor="#7eb445"
                    android:text="abc" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="40dp"
                    android:gravity="center"
                    android:textColor="#819d87"
                    android:text="def" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="40dp"
                    android:gravity="center"
                    android:textColor="#e61a5f"
                    android:text="hpq" />
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="40dp"
                    android:gravity="center"
                    android:textColor="#000000"
                    android:text="lnm" />
            </LinearLayout>
        </com.example.wavedemo.RollbackGroup>
    </FrameLayout>

</LinearLayout>

package com.example.wavedemo;

import android.annotation.SuppressLint;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

public class RollbackGroup extends LinearLayout {

	private ViewDragHelper viewDragHelper;
	private float sensitivity = 1.0f;
	private int width;
	private int height;
	private int childCount;
	private int perChildHeight;
	private int range;// 拖动的最大范围
	private int deltaTop;
	private MyScrollChangedListener listener;// 为了控制RotaationView
	private MyRollbackListener rollbackListener;// 为了回滚RotationView

	@SuppressLint("NewApi")
	public RollbackGroup(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public RollbackGroup(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public RollbackGroup(Context context) {
		this(context, null);
	}

	public void init() {
		setOrientation(LinearLayout.VERTICAL);
		if (viewDragHelper == null) {
			viewDragHelper = ViewDragHelper.create(this, sensitivity,
					new ViewDragHelper.Callback() {

						@Override
						public boolean tryCaptureView(View arg0, int arg1) {
							return true;
						}

						@Override
						public int clampViewPositionHorizontal(View child,
								int left, int dx) {
							return super.clampViewPositionHorizontal(child,
									left, dx);
						}

						@Override
						public int clampViewPositionVertical(View child,
								int top, int dy) {
							if (top > 0) {
								top = 0;
							} else if (top < -range) {
								top = -range;
							}
							if (listener != null) {

								listener.onScroll(-dy, -top,
										perChildHeight);
							}

							deltaTop = top;

							return top;
						}

						@Override
						public void onViewReleased(View releasedChild,
								float xvel, float yvel) {
							super.onViewReleased(releasedChild, xvel, yvel);
							// 向最近的View回滚
							int currentIndex = 0;
							int finalTop = 0;

							if (-deltaTop % perChildHeight != 0) {

								currentIndex = -deltaTop / perChildHeight;
								if (-deltaTop % perChildHeight < perChildHeight / 2) {
									finalTop = -currentIndex * perChildHeight;
								} else {
									finalTop = -(currentIndex + 1)
											* perChildHeight;
								}
								//回滚RotationView
								if(rollbackListener!=null)
								{
									rollbackListener.onRollback(deltaTop-finalTop,deltaTop,perChildHeight);
								}
								if (viewDragHelper.smoothSlideViewTo(
										getChildAt(0), 0, finalTop)) {
									// 返回true, 说明还没有移动到指定位置。需要重绘界面
									ViewCompat
											.postInvalidateOnAnimation(RollbackGroup.this);
								}

							}
						}

					});
		}
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		width = w;
		height = h;
		childCount = ((ViewGroup) getChildAt(0)).getChildCount();
		if (childCount >= 1) {
			perChildHeight = (int) (height * 1.0f / childCount);
			range = (height - perChildHeight);
		}

	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		if (viewDragHelper != null) {
			return viewDragHelper.shouldInterceptTouchEvent(ev);
		}
		return super.onInterceptTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (viewDragHelper != null) {
			viewDragHelper.processTouchEvent(event);
			return true;
		}
		return super.onTouchEvent(event);
	}

	@Override
	public void computeScroll() {
		super.computeScroll();
		// 2. 维持动画的继续
		if (viewDragHelper.continueSettling(true)) {
			// 返回true, 说明还没有移动到指定位置。需要重绘界面
			ViewCompat.postInvalidateOnAnimation(this);
		}
	}

	/**
	 * 为了与RotationView联动
	 * 
	 * @author huozhenpeng
	 * 
	 */
	interface MyScrollChangedListener {
		void onScroll(int delta, int top, int perChildHeight);
	}

	public void setMyScrollChangedListener(MyScrollChangedListener listener) {
		this.listener = listener;
	}

	/**
	 * 为了使RotationView回滚
	 * 
	 * @author huozhenpeng
	 * 
	 */
	interface MyRollbackListener {
		void onRollback(int degrees,int index,int perChildHeight);
	}

	public void setMyRollbackListener(MyRollbackListener rollListener) {
		this.rollbackListener = rollListener;
	}

}

package com.example.wavedemo;

import java.util.List;

import com.example.wavedemo.RollbackGroup.MyScrollChangedListener;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageView;

/**
 * 
 * @author huozhenpeng
 * 
 */
public class RotationView extends ImageView {
	private int width;
	private int height;
	private Paint paint;
	private RectF rectf;
	private int paintWidth = 100;
	private int margin;
	private double startAngle;// 记录开始角度
	private Matrix matrix;
	private double totalRotation;
	private int padding;// 设置padding或者leftpadding
	private boolean isFirst = true;
	private Bitmap imageScaled;
	private Canvas mCanvas;
	private TextPaint textpaint;
	private int textsize = 50;
	private FontMetrics fontMetrics;
	private List<RotateBean> datas;
	private RotateBean rotateBean;
	public  int currentIndex = 0;
	public RollbackGroup rollbackGroup;
	private OnRotateChangedListener listener;

	public RotationView(Context context) {
		this(context, null);
	}

	public RotationView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public RotationView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public void init() {
		this.setScaleType(ScaleType.MATRIX);
		paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
		paint.setStrokeWidth(paintWidth);
		paint.setStyle(Style.STROKE);
		textpaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
		textpaint.setTextSize(textsize);
		textpaint.setTextAlign(Align.CENTER);
		if (matrix == null) {
			matrix = new Matrix();
		} else {
			matrix.reset();
		}
		setImageMatrix(matrix);
		
		
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(heightMeasureSpec, heightMeasureSpec);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		width = w;
		height = h;
		padding = getPaddingLeft();
		margin = padding + paintWidth / 2;
		rectf = new RectF(margin, margin, width - margin, height - margin);
		imageScaled = Bitmap.createBitmap(width, height, Config.ARGB_8888);
		mCanvas = new Canvas();
		mCanvas.setBitmap(imageScaled);
		if (isFirst) {
			if (datas != null) {
				int sumDegrees = 0;
				for (int i = 0; i < datas.size(); i++) {
					rotateBean = datas.get(i);
					paint.setColor(Color.parseColor(rotateBean.getColor()));
					mCanvas.drawArc(rectf, sumDegrees, rotateBean.getDegrees(),
							false, paint);
					sumDegrees += rotateBean.getDegrees();
				}
			}
		}
		isFirst = false;
		setImageBitmap(imageScaled);
		if (datas != null) {
			rotateWheel2(90-datas.get(0).getDegrees()/2);
		}
		totalRotation=datas.get(0).getDegrees()/2;
		fontMetrics = textpaint.getFontMetrics();

	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (datas != null) {
			textpaint.setColor(Color.parseColor(datas.get(currentIndex)
					.getColor()));
			canvas.drawText(
					datas.get(currentIndex).getShowData(),
					width / 2,
					height / 2 - (fontMetrics.ascent + fontMetrics.descent) / 2,
					textpaint);
		}

	}

	/**
	 * 得到(x,y)点的象限值
	 * 
	 * @return quadrant 1,2,3 or 4
	 */
	private static int getQuadrant(double x, double y) {
		if (x >= 0) {
			return y >= 0 ? 1 : 4;
		} else {
			return y >= 0 ? 2 : 3;
		}
	}

	/**
	 * 得到(x,y)点的角度
	 */
	private double getAngle(double x, double y) {
		x = x - (width / 2d);
		y = height - y - (height / 2d);// (就是wheelHeight/2-y,由于变为数学中的坐标系,所以相当于取了一下反)

		switch (getQuadrant(x, y)) {
		case 1:
			return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
		case 2:
			return 180 - Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
		case 3:
			return 180 + (-1 * Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
		case 4:
			return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
		default:
			return 0;
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			startAngle = getAngle(event.getX(), event.getY());
			break;

		case MotionEvent.ACTION_MOVE:
			double currentAngle = getAngle(event.getX(), event.getY());
			rotateWheel((float) (startAngle - currentAngle));
			startAngle = currentAngle;
			break;

		case MotionEvent.ACTION_UP:
			totalRotation = totalRotation % 360;
			if (totalRotation < 0) {
				totalRotation = 360 + totalRotation;
			}
			MyPoint point = null;
			for (int i = 0; i < datas.size(); i++) {
				point = datas.get(i).getPoint();
				if (point.getX1() < totalRotation
						&& totalRotation < point.getX2()) {
					rotateWheel((float) (point.getX3() - totalRotation));
					currentIndex = i;
					if(listener!=null)
					{
						listener.onRotate(currentIndex);
					}
				}

			}
			break;
		}

		return true;
	}

	/**
	 * 要旋转的角度
	 * 
	 * @param degrees
	 */
	public void rotateWheel(float degrees) {
		matrix.postRotate(degrees, width / 2, height / 2);
		setImageMatrix(matrix);
		totalRotation = totalRotation + degrees;
	}
	/**
	 * 要旋转的角度
	 * 
	 * @param degrees
	 */
	public void rotateWheel2(float degrees) {
		matrix.postRotate(degrees, width / 2, height / 2);
		setImageMatrix(matrix);
	}

	/**
	 * 设置数据,寻找规律
	 * 
	 * degree x1 x2 x3
	 * 
	 * 0 90 0 90 45
	 * 
	 * 1 60 300 360 330
	 * 
	 * 2 50 250 300 225
	 * 
	 * 3 160 90 250 170
	 * 
	 * 
	 * @param datas
	 */
	public void setData(List<RotateBean> datas) {
		this.datas = datas;
		// 为point属性赋值
		for (int i = 0; i < datas.size(); i++) {
			MyPoint point = new MyPoint();
			int x1 = 0;
			int x2 = 0;
			int x3 = 0;
			if (i == 0) {
				x1 = 0;
				x2 = datas.get(i).getDegrees();
				x3 = x2 / 2;
				point.set(x1, x2, x3);
			} else {
				for (int j = i + 1; j < datas.size(); j++) {
					x1 += datas.get(j).getDegrees();
				}
				x3 = x1 + datas.get(i).getDegrees() / 2
						+ datas.get(0).getDegrees();
				x1 += datas.get(0).getDegrees();
				x2 = x1 + datas.get(i).getDegrees();
				point.set(x1, x2, x3);
			}
			datas.get(i).setPoint(point);
		}
		init();
	}
	
	interface  OnRotateChangedListener
	{
		void onRotate(int index);
	}
	/**
	 * 箭头变颜色使用
	 * @param listener
	 */
	public void setRotateListener(OnRotateChangedListener listener)
	{
		this.listener=listener;
	}
	
	public int getTotalDegrees()
	{
		return (int) totalRotation;
	}
	
		
	

}


package com.example.wavedemo;

import java.io.Serializable;

public class MyPoint implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public MyPoint() {
		// TODO Auto-generated constructor stub
	}

	private int x1;
	private int x2;
	private int x3;

	public int getX1() {
		return x1;
	}

	public void setX1(int x1) {
		this.x1 = x1;
	}

	public int getX2() {
		return x2;
	}

	public void setX2(int x2) {
		this.x2 = x2;
	}

	public int getX3() {
		return x3;
	}

	public void setX3(int x3) {
		this.x3 = x3;
	}

	public void set(int x1, int x2, int x3) {
		setX1(x1);
		setX2(x2);
		setX3(x3);
	}

	@Override
	public String toString() {
		return "MyPoint [x1=" + x1 + ", x2=" + x2 + ", x3=" + x3 + "]";
	}
	
	

}

package com.example.wavedemo;

import java.io.Serializable;


public class RotateBean implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private String showData;
	private int degrees;
	private boolean isSelected;
	private String color;// 十六进制颜色值
	private MyPoint point;//只是记录两个点(并非x和y)

	public String getShowData() {
		return showData;
	}

	public void setShowData(String showData) {
		this.showData = showData;
	}

	public int getDegrees() {
		return degrees;
	}

	public void setDegrees(int degrees) {
		this.degrees = degrees;
	}

	public boolean isSelected() {
		return isSelected;
	}

	public void setSelected(boolean isSelected) {
		this.isSelected = isSelected;
	}

	public RotateBean(String showData, int degrees) {
		super();
		this.showData = showData;
		this.degrees = degrees;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}
	
	

	public MyPoint getPoint() {
		return point;
	}

	public void setPoint(MyPoint point) {
		this.point = point;
	}


	@Override
	public String toString() {
		return "RotateBean [showData=" + showData + ", degrees=" + degrees
				+ ", isSelected=" + isSelected + ", color=" + color
				+ ", point=" + point + "]";
	}

	public RotateBean(String showData, int degrees, String color) {
		super();
		this.showData = showData;
		this.degrees = degrees;
		this.color = color;
	}
	
		

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值