您的位置:首页 > 其它

一个旋转layout布局文件

2015-06-22 13:14 417 查看
package com.github.rongi.rotate_layout.layout;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import com.github.rongi.rotate_layout.example.R;

public class RotateLayout extends ViewGroup {

	public static class LayoutParams extends ViewGroup.LayoutParams {

		public int angle;

		public LayoutParams(Context context, AttributeSet attrs) {
			super(context, attrs);
			final TypedArray a = context.obtainStyledAttributes(attrs,
					R.styleable.RotateLayout_Layout);
			angle = a.getInt(R.styleable.RotateLayout_Layout_layout_angle, 0);
		}

		public LayoutParams(ViewGroup.LayoutParams layoutParams) {
			super(layoutParams);
		}

	}

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

	public RotateLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		setWillNotDraw(false);
	}

	public View getView() {
		return getChildAt(0);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		final View view = getView();
		if (view != null) {
			final LayoutParams layoutParams = (LayoutParams) view
					.getLayoutParams();
			if (angle != layoutParams.angle) {
				angle = layoutParams.angle;
				angleChanged = true;
			}

			if (Math.abs(angle % 180) == 90) {
				measureChild(view, heightMeasureSpec, widthMeasureSpec);
				setMeasuredDimension(
						resolveSize(view.getMeasuredHeight(), widthMeasureSpec),
						resolveSize(view.getMeasuredWidth(), heightMeasureSpec));
			} else {
				measureChild(view, widthMeasureSpec, heightMeasureSpec);
				setMeasuredDimension(
						resolveSize(view.getMeasuredWidth(), widthMeasureSpec),
						resolveSize(view.getMeasuredHeight(), heightMeasureSpec));
			}
		} else {
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		}
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		if (angleChanged || changed) {
			final RectF layoutRect = tempRectF1;
			final RectF layoutRectRotated = tempRectF2;
			layoutRect.set(0, 0, r - l, b - t);
			rotateMatrix.setRotate(angle, layoutRect.centerX(),
					layoutRect.centerY());
			rotateMatrix.mapRect(layoutRectRotated, layoutRect);
			layoutRectRotated.round(viewRectRotated);
			angleChanged = false;
		}

		final View view = getView();
		if (view != null) {
			view.layout(viewRectRotated.left, viewRectRotated.top,
					viewRectRotated.right, viewRectRotated.bottom);
		}
	}

	@Override
	protected void dispatchDraw(Canvas canvas) {
		canvas.save();
		canvas.rotate(-angle, getWidth() / 2f, getHeight() / 2f);
		super.dispatchDraw(canvas);
		canvas.restore();
	}

	@Override
	public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
		invalidate();
		return super.invalidateChildInParent(location, dirty);
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		viewTouchPoint[0] = event.getX();
		viewTouchPoint[1] = event.getY();

		rotateMatrix.mapPoints(childTouchPoint, viewTouchPoint);

		event.setLocation(childTouchPoint[0], childTouchPoint[1]);
		boolean result = super.dispatchTouchEvent(event);
		event.setLocation(viewTouchPoint[0], viewTouchPoint[1]);

		return result;
	}

	@Override
	public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
		return new RotateLayout.LayoutParams(getContext(), attrs);
	}

	@Override
	protected boolean checkLayoutParams(ViewGroup.LayoutParams layoutParams) {
		return layoutParams instanceof RotateLayout.LayoutParams;
	}

	@Override
	protected ViewGroup.LayoutParams generateLayoutParams(
			ViewGroup.LayoutParams layoutParams) {
		return new RotateLayout.LayoutParams(layoutParams);
	}

	private int angle;

	private final Matrix rotateMatrix = new Matrix();

	private final Rect viewRectRotated = new Rect();

	private final RectF tempRectF1 = new RectF();
	private final RectF tempRectF2 = new RectF();

	private final float[] viewTouchPoint = new float[2];
	private final float[] childTouchPoint = new float[2];

	private boolean angleChanged = true;

}

实现方案:

旋转,重新layout实现重新布局,传递消息时将x y坐标转换,达到目的。

完整工程:
https://github.com/luxiaoming/rotate-layout
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: