Android工具类收藏

1.SharedPreference:

public class SharedPrefsUtil {
	public static void putValue(Context context, String key, int value) {
		Editor sp = PreferenceManager.getDefaultSharedPreferences(context).edit();
		sp.putInt(key, value);
		sp.commit();
	}
	public static void putValue(Context context, String key, boolean value) {
		Editor sp = PreferenceManager.getDefaultSharedPreferences(context).edit();
		sp.putBoolean(key, value);
		sp.commit();
	}
	public static void putValue(Context context, String key, String value) {
		Editor sp = PreferenceManager.getDefaultSharedPreferences(context).edit();
		sp.putString(key, value);
		sp.commit();
	}
	public static int getValue(Context context, String key, int defValue) {
		SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
		int value = sp.getInt(key, defValue);
		return value;
	}
	public static boolean getValue(Context context, String key, boolean defValue) {
		SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
		boolean value = sp.getBoolean(key, defValue);
		return value;
	}
	public static String getValue(Context context, String key, String defValue) {
		SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
		String value = sp.getString(key, defValue);
		return value;
	}
}

2.MathUtils:平面几何用到的工具方法

public final class MathUtils {
	// ===========================================================
	// Constants
	// ===========================================================
	public static final Random RANDOM = new Random(System.nanoTime());

	// ===========================================================
	// Fields
	// ===========================================================
	// ===========================================================
	// Constructors
	// ===========================================================
	// ===========================================================
	// Getter & Setter
	// ===========================================================
	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================
	// ===========================================================
	// Methods
	// ===========================================================
	public static final float atan2(final float dY, final float dX) {
		return (float) Math.atan2(dY, dX);
	}
	public static final float radToDeg(final float pRad) {
		return MathConstants.RAD_TO_DEG * pRad;
	}
	public static final float degToRad(final float pDegree) {
		return MathConstants.DEG_TO_RAD * pDegree;
	}
	public static final int signum(final int n) {
		if (n == 0) {
			return 0;
		} else if (n > 0) {
			return 1;
		} else {
			return -1;
		}
	}
	public static final int randomSign() {
		if (RANDOM.nextBoolean()) {
			return 1;
		} else {
			return -1;
		}
	}
	public static final float random(final float pMin, final float pMax) {
		return pMin + RANDOM.nextFloat() * (pMax - pMin);
	}
	/**
	 * @param pMin inclusive!
	 * @param pMax inclusive!
	 * @return
	 */
	public static final int random(final int pMin, final int pMax) {
		return pMin + RANDOM.nextInt(pMax - pMin + 1);
	}
	public static final boolean randomBoolean() {
		return MathUtils.random(0, 1) == 1;
	}
	public static final boolean isPowerOfTwo(final int n) {
		return ((n != 0) && (n & (n - 1)) == 0);
	}
	public static final int nextPowerOfTwo(final float f) {
		return MathUtils.nextPowerOfTwo((int) ((float) Math.ceil(f)));
	}
	public static final int nextPowerOfTwo(final int n) {
		int k = n;
		if (k == 0) {
			return 1;
		}
		k--;
		for (int i = 1; i < 32; i <<= 1) {
			k = k | k >> i;
		}
		return k + 1;
	}
	public static final int sum(final int[] pValues) {
		int sum = 0;
		for (int i = pValues.length - 1; i >= 0; i--) {
			sum += pValues[i];
		}
		return sum;
	}
	public static final void arraySumInternal(final int[] pValues) {
		final int valueCount = pValues.length;
		for (int i = 1; i < valueCount; i++) {
			pValues[i] = pValues[i - 1] + pValues[i];
		}
	}
	public static final void arraySumInternal(final long[] pValues) {
		final int valueCount = pValues.length;
		for (int i = 1; i < valueCount; i++) {
			pValues[i] = pValues[i - 1] + pValues[i];
		}
	}
	public static final void arraySumInternal(final long[] pValues, final long pFactor) {
		pValues[0] = pValues[0] * pFactor;
		final int valueCount = pValues.length;
		for (int i = 1; i < valueCount; i++) {
			pValues[i] = pValues[i - 1] + pValues[i] * pFactor;
		}
	}
	public static final void arraySumInto(final long[] pValues, final long[] pTargetValues, final long pFactor) {
		pTargetValues[0] = pValues[0] * pFactor;
		final int valueCount = pValues.length;
		for (int i = 1; i < valueCount; i++) {
			pTargetValues[i] = pTargetValues[i - 1] + pValues[i] * pFactor;
		}
	}
	public static final float arraySum(final float[] pValues) {
		float sum = 0;
		final int valueCount = pValues.length;
		for (int i = 0; i < valueCount; i++) {
			sum += pValues[i];
		}
		return sum;
	}
	public static final float arrayAverage(final float[] pValues) {
		return MathUtils.arraySum(pValues) / pValues.length;
	}
	public static float[] rotateAroundCenter(final float[] pVertices, final float pRotation,
			final float pRotationCenterX, final float pRotationCenterY) {
		if (pRotation != 0) {
			final float rotationRad = MathUtils.degToRad(pRotation);
			final float sinRotationRad = (float) Math.sin(rotationRad);
			final float cosRotationInRad = (float) Math.cos(rotationRad);
			for (int i = pVertices.length - 2; i >= 0; i -= 2) {
				final float pX = pVertices[i];
				final float pY = pVertices[i + 1];
				pVertices[i] = pRotationCenterX
						+ (cosRotationInRad * (pX - pRotationCenterX) - sinRotationRad * (pY - pRotationCenterY));
				pVertices[i + 1] = pRotationCenterY
						+ (sinRotationRad * (pX - pRotationCenterX) + cosRotationInRad * (pY - pRotationCenterY));
			}
		}
		return pVertices;
	}
	public static float[] scaleAroundCenter(final float[] pVertices, final float pScaleX, final float pScaleY,
			final float pScaleCenterX, final float pScaleCenterY) {
		if (pScaleX != 1 || pScaleY != 1) {
			for (int i = pVertices.length - 2; i >= 0; i -= 2) {
				pVertices[i] = pScaleCenterX + (pVertices[i] - pScaleCenterX) * pScaleX;
				pVertices[i + 1] = pScaleCenterY + (pVertices[i + 1] - pScaleCenterY) * pScaleY;
			}
		}
		return pVertices;
	}
	public static float[] rotateAndScaleAroundCenter(final float[] pVertices, final float pRotation,
			final float pRotationCenterX, final float pRotationCenterY, final float pScaleX, final float pScaleY,
			final float pScaleCenterX, final float pScaleCenterY) {
		MathUtils.rotateAroundCenter(pVertices, pRotation, pRotationCenterX, pRotationCenterY);
		return MathUtils.scaleAroundCenter(pVertices, pScaleX, pScaleY, pScaleCenterX, pScaleCenterY);
	}
	public static float[] revertScaleAroundCenter(final float[] pVertices, final float pScaleX, final float pScaleY,
			final float pScaleCenterX, final float pScaleCenterY) {
		return MathUtils.scaleAroundCenter(pVertices, 1 / pScaleX, 1 / pScaleY, pScaleCenterX, pScaleCenterY);
	}
	public static float[] revertRotateAroundCenter(final float[] pVertices, final float pRotation,
			final float pRotationCenterX, final float pRotationCenterY) {
		return MathUtils.rotateAroundCenter(pVertices, -pRotation, pRotationCenterX, pRotationCenterY);
	}
	public static float[] revertRotateAndScaleAroundCenter(final float[] pVertices, final float pRotation,
			final float pRotationCenterX, final float pRotationCenterY, final float pScaleX, final float pScaleY,
			final float pScaleCenterX, final float pScaleCenterY) {
		MathUtils.revertScaleAroundCenter(pVertices, pScaleX, pScaleY, pScaleCenterX, pScaleCenterY);
		return MathUtils.revertRotateAroundCenter(pVertices, pRotation, pRotationCenterX, pRotationCenterY);
	}
	public static final boolean isInBounds(final int pMinValue, final int pMaxValue, final int pValue) {
		return pValue >= pMinValue && pValue <= pMaxValue;
	}
	public static final boolean isInBounds(final float pMinValue, final float pMaxValue, final float pValue) {
		return pValue >= pMinValue && pValue <= pMaxValue;
	}
	/**
	 * @param pMinValue inclusive!
	 * @param pMaxValue inclusive!
	 * @param pValue
	 * @return
	 */
	public static final int bringToBounds(final int pMinValue, final int pMaxValue, final int pValue) {
		return Math.max(pMinValue, Math.min(pMaxValue, pValue));
	}
	/**
	 * @param pMinValue inclusive!
	 * @param pMaxValue inclusive!
	 * @param pValue
	 * @return
	 */
	public static final float bringToBounds(final float pMinValue, final float pMaxValue, final float pValue) {
		return Math.max(pMinValue, Math.min(pMaxValue, pValue));
	}
	/**
	 * @return the euclidean distance between the points (pX1, pY1) and (pX2, pY2).
	 */
	public static final float distance(final float pX1, final float pY1, final float pX2, final float pY2) {
		final float dX = pX2 - pX1;
		final float dY = pY2 - pY1;
		return (float) Math.sqrt((dX * dX) + (dY * dY));
	}
	/**
	 * @return the euclidean distance between the origin (0, 0) and (pX, pY).
	 */
	public static final float length(final float pX, final float pY) {
		return (float) Math.sqrt((pX * pX) + (pY * pY));
	}
	/**
	 * @param pX
	 * @param pY
	 * @param pMix [0...1]
	 * @return pX * (1 - pMix) + pY * pMix
	 */
	public static final float mix(final float pX, final float pY, final float pMix) {
		return pX * (1 - pMix) + pY * pMix;
	}
	/**
	 * @param pX
	 * @param pY
	 * @param pMix [0...1]
	 * @return (int)Math.round(pX * (1 - pMix) + pY * pMix)
	 */
	public static final int mix(final int pX, final int pY, final float pMix) {
		return Math.round(pX * (1 - pMix) + pY * pMix);
	}
	public static final boolean isEven(final int n) {
		return n % 2 == 0;
	}
	public static final boolean isOdd(final int n) {
		return n % 2 == 1;
	}
	public static float dot(final float pXA, final float pYA, final float pXB, final float pYB) {
		return pXA * pXB + pYA * pYB;
	}
	public static float cross(final float pXA, final float pYA, final float pXB, final float pYB) {
		return pXA * pYB - pXB * pYA;
	}
	// ===========================================================
	// 额外添加
	// ===========================================================
	/**
	 * 求以PX1,PY1点为顶点,12点钟方向顶点连线及X2Y2顶点连线的夹角
	 * @param pX1
	 * @param pY1
	 * @param pX2
	 * @param pY2
	 * @return
	 */
	public static double getAngleForTwelve(float pX1, float pY1, float pX2, float pY2) {
		if (pX1 == pX2 && pY1 == pY2) {
			return 0;
		}
		double x4 = pX1;
		double y4 = pY1 - 1;
		double ma_x = pX2 - pX1;
		double ma_y = pY2 - pY1;
		double mb_x = x4 - pX1;
		double mb_y = y4 - pY1;
		if (mb_y == 0) {
			mb_y = 1;
		}
		double v1 = (ma_x * mb_x) + (ma_y * mb_y);
		double ma_val = Math.sqrt(ma_x * ma_x + ma_y * ma_y);
		double mb_val = Math.sqrt(mb_x * mb_x + mb_y * mb_y);
		double cosA = v1 / (ma_val * mb_val);
		double angle = Math.acos(cosA) * 180.0f / Math.PI;
		if ((ma_x < 0 && ma_y >= 0) || (ma_x < 0 && ma_y <= 0)) {
			angle = 360.0f - angle;
		}
		return angle;
	}
	/**
	 * 求以PX1,PY1点为顶点,6点钟方向顶点连线及X2Y2顶点连线的夹角
	 * @param pX1
	 * @param pY1
	 * @param pX2
	 * @param pY2
	 * @return
	 */
	public static double getAngleForSix(float pX1, float pY1, float pX2, float pY2) {
		if (pX1 == pX2 && pY1 == pY2) {
			return 0;
		}
		double x4 = pX1;
		double y4 = pY1 + 1;
		double ma_x = pX2 - pX1;
		double ma_y = pY2 - pY1;
		double mb_x = x4 - pX1;
		double mb_y = y4 - pY1;
		if (mb_y == 0) {
			mb_y = -1;
		}
		double v1 = (ma_x * mb_x) + (ma_y * mb_y);
		double ma_val = Math.sqrt(ma_x * ma_x + ma_y * ma_y);
		double mb_val = Math.sqrt(mb_x * mb_x + mb_y * mb_y);
		double cosA = v1 / (ma_val * mb_val);
		double angle = Math.acos(cosA) * 180.0f / Math.PI;
		if ((ma_x > 0 && ma_y >= 0) || (ma_x > 0 && ma_y <= 0)) {
			angle = 360.0f - angle;
		}
		return angle;
	}
	/**
	 * @param a 长轴长度的一半
	 * @param b 短轴长度的一半
	 * @param aX 中点坐标
	 * @param aY 中点坐标
	 * @param angle 椭圆上某点坐标和中点的连线 与 正长轴的夹角
	 * @return
	 */
	public static Coordinate getCoordinateForOval(float a, float b, float aX, float aY, float angle) {
		float x = a * (float) Math.cos(Math.toRadians(angle));
		float y = b * (float) Math.sin(Math.toRadians(angle));
		Coordinate coordinate = new Coordinate(aX - x, aY - y);
		return coordinate;
	}
	/**
	 * 计算圆形中圆周上某点的坐标
	 * @param aX 顶点坐标X
	 * @param aY 顶点坐标Y
	 * @param r 半径
	 * @param aAngle1 边(顶点与6点钟方向)与边(顶点与所求坐标)的角度
	 */
	public static Coordinate getCoordinateForCircleSix(float aX, float aY, float r, float aAngle1) {
		aAngle1 = aAngle1 + 90;
		float Y = (float) (Math.sin(Math.toRadians(aAngle1)) * r);
		float X = (float) (Math.cos(Math.toRadians(aAngle1)) * r);
		Coordinate coordinate = new Coordinate(aX + X, aY + Y);
		return coordinate;
	}

	public static class Coordinate {
		public float x = 0;
		public float y = 0;

		public Coordinate(float x, float y) {
			this.x = x;
			this.y = y;
		}
	}

	/**
	 * 点到直线的最短距离的判断 点(x0,y0) 到由两点组成的线段(x1,y1) ,( x2,y2 )
	 * @param x1 线段
	 * @param y1 线段
	 * @param x2 线段
	 * @param y2 线段
	 * @param x0 点
	 * @param y0 点
	 * @return
	 */
	public static float pointToLine(float x0, float y0, float x1, float y1, float x2, float y2) {
		float space = 0;
		float a, b, c;
		a = distance(x1, y1, x2, y2);// 线段的长度
		b = distance(x1, y1, x0, y0);// (x1,y1)到点的距离
		c = distance(x2, y2, x0, y0);// (x2,y2)到点的距离
		if (c <= 0.000001 || b <= 0.000001) {
			space = 0;
			return space;
		}
		if (a <= 0.000001) {
			space = b;
			return space;
		}
		if (c * c >= a * a + b * b) {
			space = b;
			return space;
		}
		if (b * b >= a * a + c * c) {
			space = c;
			return space;
		}
		float p = (a + b + c) / 2;// 半周长
		float s = (float) Math.sqrt(p * (p - a) * (p - b) * (p - c));// 海伦公式求面积
		space = 2 * s / a;// 返回点到线的距离(利用三角形面积公式求高)
		return space;
	}
	/**
	 * 求x0是否在正方形内
	 * @param x0
	 * @param y0
	 * @param x1
	 * @param y1
	 * @return
	 */
	public static boolean isPointInSquare(float x0, float y0, float[] x1, float[] y1) {
		if (x1.length != y1.length) {
			return false;
		}
		boolean left = false;
		boolean right = false;
		boolean top = false;
		boolean bottom = false;
		for (int i = 0; i < y1.length; i++) {
			if (pointInQuadrant(x0, y0, x1[i], y1[i]) == 7) {
				return true;
			}
			if (pointInQuadrant(x0, y0, x1[i], y1[i]) == 3 || pointInQuadrant(x0, y0, x1[i], y1[i]) == 4
					|| pointInQuadrant(x0, y0, x1[i], y1[i]) == -5) {
				left = true;
			} else if (pointInQuadrant(x0, y0, x1[i], y1[i]) == 1 || pointInQuadrant(x0, y0, x1[i], y1[i]) == 2
					|| pointInQuadrant(x0, y0, x1[i], y1[i]) == 5) {
				right = true;
			}
			if (pointInQuadrant(x0, y0, x1[i], y1[i]) == 1 || pointInQuadrant(x0, y0, x1[i], y1[i]) == 4
					|| pointInQuadrant(x0, y0, x1[i], y1[i]) == -6) {
				top = true;
			} else if (pointInQuadrant(x0, y0, x1[i], y1[i]) == 3 || pointInQuadrant(x0, y0, x1[i], y1[i]) == 2
					|| pointInQuadrant(x0, y0, x1[i], y1[i]) == 6) {
				bottom = true;
			}
		}
		if ((left && right) && (top && bottom)) {
			return true;
		}
		return false;
	}
	/**
	 * X1在X0的第几象限
	 * @param x0
	 * @param y0
	 * @param x1
	 * @param y1
	 * @return -5左边 5右边 -6上边 6下面 7中点
	 */
	public static int pointInQuadrant(float x0, float y0, float x1, float y1) {
		int code = 0;
		if (x0 > x1) {
			if (y0 > y1) {
				code = 4;
			} else if (y0 < y1) {
				code = 3;
			} else {
				code = -5;
			}
		} else if (x0 < x1) {
			if (y0 > y1) {
				code = 1;
			} else if (y0 < y1) {
				code = 2;
			} else {
				code = 5;
			}
		} else {
			if (y0 > y1) {
				code = -6;
			} else if (y0 < y1) {
				code = 6;
			} else {
				code = 7;
			}
		}
		return code;
	}
	/**
	 * 圆到正方形的距离
	 * @param x0 圆中点
	 * @param y0
	 * @param x 正方形左上顶点
	 * @param y
	 * @param width 正方形宽
	 * @param height
	 * @param rotation 正方形转动角度
	 * @return
	 */
	public static int circleToSquare(float x0, float y0, float x, float y, float width, float height, float rotation) {
		float centreX = x + width / 2;
		float centreY = y + height / 2;
		float xx[] = new float[4];
		float yy[] = new float[4];
		float diagonal = (float) Math.sqrt(width * width + height * height) / 2;
		Coordinate coordinate = null;
		coordinate = getCoordinateForCircleSix(centreX, centreY, diagonal, 135 + rotation); // 左上顶点
		float x1 = coordinate.x;
		float y1 = coordinate.y;
		xx[0] = x1;
		yy[0] = y1;
		coordinate = getCoordinateForCircleSix(centreX, centreY, diagonal, 225 + rotation); // 右上顶点
		float x2 = coordinate.x;
		float y2 = coordinate.y;
		xx[1] = x2;
		yy[1] = y2;
		coordinate = getCoordinateForCircleSix(centreX, centreY, diagonal, 315 + rotation); // 右下顶点
		float x3 = coordinate.x;
		float y3 = coordinate.y;
		xx[2] = x3;
		yy[2] = y3;
		coordinate = getCoordinateForCircleSix(centreX, centreY, diagonal, 45 + rotation); // 左下顶点
		float x4 = coordinate.x;
		float y4 = coordinate.y;
		xx[3] = x4;
		yy[3] = y4;
		float space1 = pointToLine(x0, y0, x1, y1, x2, y2);
		float space2 = pointToLine(x0, y0, x1, y1, x4, y4);
		float space3 = pointToLine(x0, y0, x3, y3, x2, y2);
		float space4 = pointToLine(x0, y0, x3, y3, x4, y4);
		float space5 = space1 < space2 ? space1 : space2;
		float space6 = space3 < space4 ? space3 : space4;
		float space = space5 < space6 ? space5 : space6;
		if (isPointInSquare(x0, y0, xx, yy)) {
			return (int) space * -1;
		}
		return (int) space;
	}

	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================
	public interface MathConstants {
		// ===========================================================
		// Constants
		// ===========================================================
		public static final float PI = (float) Math.PI;
		public static float PI_TWICE = PI * 2.0f;
		public static float PI_HALF = PI * 0.5f;
		public static final float DEG_TO_RAD = PI / 180.0f;
		public static final float RAD_TO_DEG = 180.0f / PI;
		// ===========================================================
		// Methods
		// ===========================================================
	}
}

3.Line和Quadrilateral:判断四边形是否相交,线段与线段是否相交

关于线段相交和四边形相交的原理:计算几何算法概览

public class Line {
	public float x1, y1;//P1,Q1
	public float x2, y2;//P2,Q2

	public Line(float x1, float y1, float x2, float y2) {
		super();
		this.x1 = x1;
		this.y1 = y1;
		this.x2 = x2;
		this.y2 = y2;
	}
	public void setLine(float x1, float y1, float x2, float y2) {
		this.x1 = x1;
		this.y1 = y1;
		this.x2 = x2;
		this.y2 = y2;
	}
	//获取斜率
	public float getSlope() {
		if (x2 == x1)
			return Float.NaN;
		return (y2 - y1) / (x2 - x1);
	}
	//设点为Q,线段为P1P2 ,判断点Q在该线段上的依据是:( Q - P1 ) × ( P2 - P1 ) = 0 且 Q 在以 P1,P2为对角顶点的矩形内。
	public boolean isOnline(float px, float py) {
		Line QP1 = new Line(px, py, x1, y1);
		Line P2P1 = new Line(x2, y2, x1, y1);
		float xmin = x1 > x2 ? x2 : x1;
		float xmax = x1 > x2 ? x1 : x2;
		float ymin = y1 > y2 ? y2 : y1;
		float ymax = y1 > y2 ? y1 : y2;
		if (QP1.cross(P2P1) != 0 || xmin > px || xmax < px || ymin > py || ymax < py) {
			return false;
		}
		return true;
	}
	public boolean isYMaxPoint(float py) {
		return py == Math.max(y1, y2);
	}
	public void reverse() {
		float temp = x2;
		x2 = x1;
		x1 = temp;
		temp = y2;
		y2 = y1;
		y1 = temp;
	}
	public float cross(Line line) {
		float px1 = x2 - x1;
		float py1 = y2 - y1;
		float px2 = line.x2 - line.x1;
		float py2 = line.y2 - line.y1;
		return px1 * py2 - px2 * py1;
	}
	//连个线段是否相交
	public boolean intersect(Line line) {
		//快速排斥试验
		float xmin, xmax, ymin, ymax, xmin2, xmax2, ymin2, ymax2;
		xmin = x1 > x2 ? x2 : x1;
		xmax = x1 > x2 ? x1 : x2;
		ymin = y1 > y2 ? y2 : y1;
		ymax = y1 > y2 ? y1 : y2;
		xmin2 = line.x1 > line.x2 ? line.x2 : line.x1;
		xmax2 = line.x1 > line.x2 ? line.x1 : line.x2;
		ymin2 = line.y1 > line.y2 ? line.y2 : line.y1;
		ymax2 = line.y1 > line.y2 ? line.y1 : line.y2;
		if (xmax2 < xmin || xmin2 > xmax || ymax2 < ymin || ymin2 > ymax) {
			return false;
		}
		//跨立试验:如果两线段相交,则两线段必然相互跨立对方
		//判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0
		//判断Q1Q2跨立P1P2的依据是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0
		Line P1Q1 = new Line(x1, y1, line.x1, line.y1);
		Line Q2Q1 = new Line(line.x2, line.y2, line.x1, line.y1);
		Line P2Q1 = new Line(x2, y2, line.x1, line.y1);
		float P1P2_Q1Q2 = P1Q1.cross(Q2Q1) * Q2Q1.cross(P2Q1);
		if (P1P2_Q1Q2 < 0)
			return false;
		Line Q1P1 = new Line(line.x1, line.y1, x1, y1);
		Line P2P1 = new Line(x2, y2, x1, y1);
		Line Q2P1 = new Line(line.x2, line.y2, x1, y1);
		float Q1Q2_P1P2 = Q1P1.cross(P2P1) * P2P1.cross(Q2P1);
		if (Q1Q2_P1P2 < 0)
			return false;
		return true;
	}
	public boolean isInQuadrilateral() {
		return false;
	}
}

//四边形
public class Quadrilateral {
	public Line[] lines;

	public Quadrilateral(Line[] lines) {
		super();
		this.lines = lines;
	}
	/**
	 * @Title: isInner
	 * @Description: 判断点P是否在多边形中是计算几何中一个非常基本但是十分重要的算法。以点P为端点,向左方作射线L,由于多边形是有界的,所以射线L的左端一定在多边形外,
	 *               考虑沿着L从无穷远处开始自左向右移动,遇到和多边形的第一个交点的时候,进入到了多边形的内部,遇到第二个交点的时候,离开了多边形,
	 *               ……所以很容易看出当L和多边形的交点数目C是奇数的时候,P在多边形内,是偶数的话P在多边形外。
	 * @param: @param px
	 * @param: @param py
	 * @param: @return
	 * @return: boolean
	 * @throws:
	 */
	public boolean isInner(float px, float py) {
		Line ray = new Line(Float.MIN_VALUE, py, px, py);
		int count = 0;
		for (Line s : lines) {
			if (s.isOnline(px, py)) {
				return true;
			} else if (s.getSlope() != 0) {//不是水平线段
				if (ray.isOnline(s.x1, s.y1) || ray.isOnline(s.x2, s.y2)) {
					if ((ray.isOnline(s.x1, s.y1) && s.isYMaxPoint(s.y1))
							|| (ray.isOnline(s.x2, s.y2) && s.isYMaxPoint(s.y2)))
						count++;
					//端点在射线上单不是两端点中纵坐标较大的端点,不对count处理
				} else if (ray.intersect(s)) {//射线与边相交
					count++;
				}
			}
		}
		//相交点为奇数表示在四边形内部
		return count % 2 == 1;
	}
}
4.根据内容自适应字体的TextView
public class FontFitTextView extends TextView {
	private static final String TAG = "FontFitTextView";
	private static final boolean DEBUG = false;
	//Attributes
	private Paint testPaint;
	private float minTextSize;
	private float maxTextSize;
	
	public FontFitTextView(Context context) {
		super(context);
		initialise();
	}
	public FontFitTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initialise();
	}
	private void initialise() {
		testPaint = new Paint();
		testPaint.set(this.getPaint());
		//max size defaults to the intially specified text size unless it is too small
		maxTextSize = this.getTextSize();
		if (maxTextSize < 11) {
			maxTextSize = 30;
		}
		minTextSize = 10;
	}
	/* Re size the font so the specified text fits in the text box
	 * assuming the text box is the specified width.
	 */
	private void refitText(String text, int textWidth) {
		if (textWidth > 0) {
			int availableWidth = textWidth - this.getPaddingLeft() - this.getPaddingRight();
			int availableHeight = getHeight() - this.getPaddingTop() - this.getPaddingBottom();
			float trySize = maxTextSize;
			testPaint.setTextSize(trySize);
			FontMetrics fm = testPaint.getFontMetrics();
			int fontHeight = (int) Math.ceil(fm.descent - fm.top) + 2;
			while ((trySize > minTextSize) && ((testPaint.measureText(text) > availableWidth)|| fontHeight > availableHeight)) {
				trySize -= 1;
				if (trySize <= minTextSize) {
					trySize = minTextSize;
					break;
				}
				testPaint.setTextSize(trySize);
				fm = testPaint.getFontMetrics();
				fontHeight = (int) Math.ceil(fm.descent - fm.top) + 2;
			}
			this.setTextSize(trySize);
		}
	}
	//获取字体高度
	public int getFontHeight(float fontSize) {
		Paint paint = new Paint();
		paint.setTextSize(fontSize);
		FontMetrics fm = paint.getFontMetrics();
		return (int) Math.ceil(fm.descent - fm.top) + 2;
	}
	
	@Override
	protected void onTextChanged(final CharSequence text, final int start, final int before, final int after) {
		refitText(text.toString(), this.getWidth());
	}
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		if (w != oldw) {
			refitText(this.getText().toString(), w);
		}
	}
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (DEBUG) {
			Paint pt = new Paint();
			pt.setColor(0x80ff0000);
			pt.setStrokeWidth(5.0f);
			pt.setStyle(Paint.Style.STROKE);
			canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);
		}
	}
	//Getters and Setters
	public float getMinTextSize() {
		return minTextSize;
	}
	public void setMinTextSize(int minTextSize) {
		this.minTextSize = minTextSize;
	}
	public float getMaxTextSize() {
		return maxTextSize;
	}
	public void setMaxTextSize(int minTextSize) {
		this.maxTextSize = minTextSize;
	}
}
5.平滑滚动的ListView

/**
 * A ListView that can be asked to scroll (smoothly or otherwise) to a specific position. This class
 * takes advantage of similar functionality that exists in {@link ListView} and enhances it.
 */
public class AutoScrollListView extends ListView {
	/**
	 * Position the element at about 1/3 of the list height
	 */
	private static final float PREFERRED_SELECTION_OFFSET_FROM_TOP = 0.33f;
	private int mRequestedScrollPosition = -1;
	private boolean mSmoothScrollRequested;

	public AutoScrollListView(Context context) {
		super(context);
	}
	public AutoScrollListView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	public AutoScrollListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	/**
	 * Brings the specified position to view by optionally performing a jump-scroll maneuver: first
	 * it jumps to some position near the one requested and then does a smooth scroll to the
	 * requested position. This creates an impression of full smooth scrolling without actually
	 * traversing the entire list. If smooth scrolling is not requested, instantly positions the
	 * requested item at a preferred offset.
	 */
	public void requestPositionToScreen(int position, boolean smoothScroll) {
		mRequestedScrollPosition = position;
		mSmoothScrollRequested = smoothScroll;
		requestLayout();
	}
	@Override
	protected void layoutChildren() {
		super.layoutChildren();
		if (mRequestedScrollPosition == -1) {
			return;
		}
		final int position = mRequestedScrollPosition;
		mRequestedScrollPosition = -1;
		int firstPosition = getFirstVisiblePosition() + 1;
		int lastPosition = getLastVisiblePosition();
		if (position >= firstPosition && position <= lastPosition) {
			return; // Already on screen
		}
		final int offset = (int) (getHeight() * PREFERRED_SELECTION_OFFSET_FROM_TOP);
		if (!mSmoothScrollRequested) {
			setSelectionFromTop(position, offset);
			// Since we have changed the scrolling position, we need to redo child layout
			// Calling "requestLayout" in the middle of a layout pass has no effect,
			// so we call layoutChildren explicitly
			super.layoutChildren();
		} else {
			// We will first position the list a couple of screens before or after
			// the new selection and then scroll smoothly to it.
			int twoScreens = (lastPosition - firstPosition) * 2;
			int preliminaryPosition;
			if (position < firstPosition) {
				preliminaryPosition = position + twoScreens;
				if (preliminaryPosition >= getCount()) {
					preliminaryPosition = getCount() - 1;
				}
				if (preliminaryPosition < firstPosition) {
					setSelection(preliminaryPosition);
					super.layoutChildren();
				}
			} else {
				preliminaryPosition = position - twoScreens;
				if (preliminaryPosition < 0) {
					preliminaryPosition = 0;
				}
				if (preliminaryPosition > lastPosition) {
					setSelection(preliminaryPosition);
					super.layoutChildren();
				}
			}
			smoothScrollToPositionFromTop(position, offset);
		}
	}
}

6.线程工具类

public class ThreadUtils {
	public static final ExecutorService fixedExec = Executors
			.newFixedThreadPool(5, new ThreadFactory() {
				@Override
				public Thread newThread(Runnable runnable) {
					Thread thread = new Thread(runnable,
							"ThreadUtils_fixedExec");
					return thread;
				}
			});
	private static final ScheduledExecutorService scheduExec = Executors
			.newScheduledThreadPool(3, new ThreadFactory() {
				@Override
				public Thread newThread(Runnable runnable) {
					Thread thread = new Thread(runnable,
							"ThreadUtils_scheduExec");
					return thread;
				}
			});

	/**
	 * @Title: splitTaksk
	 * @Description:将线程中的一个大任务拆分成几个小任务并行执行,注意:此方法会阻塞所调用的线程
	 * @param: @param threadPoolsize
	 * @param: @param runnable
	 * @return: void
	 * @throws:
	 */
	public static void executeDivideTasks(List runnables) {
		Object lock = new Object();
		Map resultMap = new HashMap();
		if (runnables != null && !runnables.isEmpty()) {
			for (int i = 0; i < runnables.size(); i++) {
				fixedExec.submit(new InnerRunnalbe(runnables.get(i), runnables
						.size(), lock, String.valueOf(i), resultMap));
			}
			synchronized (lock) {
				try {
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	/**
	 * @Title: executeTask
	 * @Description: 向线程池提交一个任务
	 * @param: @param runnables
	 * @return: void
	 * @throws:
	 */
	public static void executeTask(Runnable... runnables) {
		for (Runnable runnable : runnables) {
			fixedExec.submit(runnable);
		}
	}

	/**
	 * @ClassName: InnerRunnalbe
	 * @Description: Runnable的代理类,内部执行线程,执行完所有任务后通知释放锁
	 * @author: yuedong bao
	 * @date: 2015-7-31 上午10:55:12
	 */
	private static class InnerRunnalbe implements Runnable {
		private final Runnable task;
		private final int taskSize;
		private final Object lock;
		private final Map reslutMap;
		private final String taskName;

		public InnerRunnalbe(Runnable task, int taskSize, Object lock,
				String taskName, Map reslutMap) {
			super();
			this.task = task;
			this.taskSize = taskSize;
			this.lock = lock;
			this.taskName = taskName;
			this.reslutMap = reslutMap;
		}
		@Override
		public void run() {
			try {
				task.run();
				synchronized (reslutMap) {
					reslutMap.put(taskName, true);
				}
			} catch (Exception e) {
				e.printStackTrace();
				synchronized (reslutMap) {
					reslutMap.put(taskName, false);
				}
			} finally {
				if (reslutMap.size() == taskSize) {
					synchronized (lock) {
						lock.notify();
					}
				}
			}
		}
	}

	/**
	 * 执行一次
	 * @Title: addDelayTask
	 * @param @param autoTask
	 * @param @param delay
	 * @return void
	 * @throws
	 */
	public static void addDelayTask(AutoTask autoTask, int delayMills) {
		ScheduledFuture scheduledFuture = scheduExec.schedule(autoTask,
				delayMills, TimeUnit.MILLISECONDS);
		autoTask.setScheduledFuture(scheduledFuture);
	}
	/**
	 * 循环
	 * @Title: addRateTask
	 * @param @param autoTask
	 * @param @param period
	 * @return void
	 * @throws
	 */
	public static void addRateTask(AutoTask autoTask, int period) {
		ScheduledFuture scheduledFuture = scheduExec.scheduleAtFixedRate(
				autoTask, 0, period, TimeUnit.MILLISECONDS);
		autoTask.setScheduledFuture(scheduledFuture);
	}
	/**
	 * 延迟多久执行
	 * @Title: addRateTask
	 * @param @param autoTask
	 * @param @param initialDelay
	 * @param @param period
	 * @return void
	 * @throws
	 */
	public static void addRateTask(AutoTask autoTask, int initialDelay,
			int period) {
		ScheduledFuture scheduledFuture = scheduExec.scheduleAtFixedRate(
				autoTask, initialDelay, period, TimeUnit.MILLISECONDS);
		autoTask.setScheduledFuture(scheduledFuture);
	}

	public static abstract class AutoTask implements Runnable {
		private ScheduledFuture scheduledFuture;

		public void setScheduledFuture(ScheduledFuture scheduledFuture) {
			this.scheduledFuture = scheduledFuture;
		}
		public abstract void onCancel();
		/**
		 * Returns true if this task completed. Completion may be due to normal termination, an
		 * exception, or cancellation -- in all of these cases, this method will return true.
		 * @Title: isDone
		 * @param @return
		 * @return boolean
		 * @throws
		 */
		public boolean isDone() {
			if (scheduledFuture != null) {
				return scheduledFuture.isDone();
			}
			return true;
		}
		public boolean isCancelled() {
			if (scheduledFuture != null) {
				scheduledFuture.isCancelled();
			}
			return true;
		}
		/**
		 * 关闭任务
		 * @Title: stop
		 * @param @param mayInterruptIfRunning true 正在执行的中断,false等待完成
		 * @return void
		 * @throws
		 */
		public void stop(boolean mayInterruptIfRunning) {
			if (scheduledFuture != null) {
				scheduledFuture.cancel(mayInterruptIfRunning);
				onCancel();
			}
			scheduledFuture = null;
		}
	}
}










==============================To be continued============================

你可能感兴趣的:(Android基础,Android,工具类)