android中獲取屏幕信息,做標準刻度的尺子

在教學app中會有尺子的出現,我們如何獲取標準的刻度呢

實現的關鍵是:

1.獲取設備屏幕的信息

2.根據參數繪製尺子

3.設定尺子的相關動作


第一步的關鍵是DisplayMetrics,它的介紹是A structure describing general information about a display, such as its size, density, and font scaling.

和getWindowManager().getDefaultDisplay().getMetrics();它的介紹是Gets display metrics that describe the size and density of this display.

我們通過

dm = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(dm);
將屏幕信息傳入到dm結構體中,再將dm作爲傳參給我們的RulerView類

構造方法:

public RulerView(Context context, DisplayMetrics dm) {
		super(context);
		find_pixal(dm);
		ruler_length = 6 * xcm; // 設置一開始爲6釐米的尺子
		ruler_width = xcm;
		mid_point.set((float) (ruler_length * 0.5), 0);
		rect = new Rect(0, 0, (int) (ruler_length), (int) ruler_width);
	}
protected void find_pixal(DisplayMetrics dm) {
		xcm = (float) (dm.xdpi / 2.54); // 單位都是pixal
		xmm = xcm / 10;
	}


dm.xdpi是The exact physical pixels per inch of the screen in the X dimension.,我們將pixal/inch轉換成pixal每釐米只需要除以2.54即可,毫米同理。

其實實際上應該是要用上x和y一起計算的,不過基本所有設備x和y上的dpi都是一樣的,所以我們只用xdpi就好了

聲明FPoint mid_point做尺子的中點座標。

重寫onDraw方法:

先設置好畫筆的樣式,然後讓在canvas上以中點爲標準畫長度爲ruler_length並且標有刻度和數字的尺子。

我們這裏設置了angle_rotate,這是用於我們後面旋轉尺子用的

protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		Paint paint = new Paint();
		paint.setColor(Color.BLACK);
		paint.setStyle(Style.STROKE);
		paint.setStrokeWidth(2);
		paint.setTextSize(30);
		canvas.save();
		canvas.rotate(angle_rotate, mid_point.x, mid_point.y);
		canvas.drawRect(mid_point.x - ruler_length / 2, mid_point.y,
				mid_point.x + ruler_length / 2, mid_point.y + ruler_width,
				paint);
		for (int i = 0; i < ruler_length / xmm; i++) {
			float Left = mid_point.x - ruler_length / 2;
			if (i % 10 == 0 && i != 0) {
				canvas.drawLine(Left + i * xmm, mid_point.y, Left + i * xmm,
						mid_point.y + 50, paint);
				canvas.drawText(Integer.toString(i / 10), Left + i * xmm,
						mid_point.y + 55, paint);
			} else if (i == 0) {
				canvas.drawLine(Left + i * xmm, mid_point.y, Left + i * xmm,
						mid_point.y + 50, paint);
				canvas.drawText(Integer.toString(i / 5) + "cm", Left + i * xmm,
						mid_point.y + 55, paint);
			} else {
				canvas.drawLine(Left + i * xmm, mid_point.y, Left + i * xmm,
						mid_point.y + 30, paint);
			}
		}
		canvas.restore();
	}

接着我們處理拖拽和旋轉事件:

public boolean onTouchEvent(MotionEvent event) {
		PointF touchPoint1;
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		// 主點按下
		case MotionEvent.ACTION_DOWN:
			touchPoint1 = supposedPoint(new PointF(event.getX(), event.getY()));
			if (rect.contains((int) touchPoint1.x, (int) touchPoint1.y)) {
				MODE = "DRAG";
				finger_first_down.set(event.getX(), event.getY());
				mid_point_saved.set(mid_point);
			} else {
				return false;
			}
			break;
		case MotionEvent.ACTION_POINTER_1_DOWN:
			PointF touchPoint2 = supposedPoint(new PointF(event.getX(1),
					event.getY(1)));
			if (rect.contains((int) touchPoint2.x, (int) touchPoint2.y)) {
				MODE = "ZOOM";
				finger_first_down.set(event.getX(0), event.getY(0));
				finger_second_down.set(event.getX(1), event.getY(1));
				angle_initial = rotation(event);
				angle_saved = angle_rotate;
				SingleToMulti = true;
				distance_initial = distance(event);
				distance_saved = ruler_length;
				mid_point_between_fingers_down.set(
						(event.getX(0) + event.getX(1)) / 2,
						(event.getY(0) + event.getY(1)) / 2);
			} else {
				return false;
			}
			break;
			
		case MotionEvent.ACTION_MOVE:
			if (MODE == "DRAG") {
				if (MultiToSingle) {
					finger_first_down.set(event.getX(), event.getY());
					mid_point_saved.set(mid_point);
					MultiToSingle = false;
				}
				mid_point.set(mid_point_saved.x + event.getX()
						- finger_first_down.x, mid_point_saved.y + event.getY()
						- finger_first_down.y);
				renewRect();
			} else if (MODE == "ZOOM") {
				if (SingleToMulti) {
					mid_point_saved.set(mid_point);
					SingleToMulti = false;
				}
				mid_point_between_fingers.set(
						(event.getX(0) + event.getX(1)) / 2,
						(event.getY(0) + event.getY(1)) / 2);
				mid_point.set(mid_point_saved.x + mid_point_between_fingers.x
						- mid_point_between_fingers_down.x, mid_point_saved.y
						+ mid_point_between_fingers.y
						- mid_point_between_fingers_down.y);
				angle_rotate = angle_saved + rotation(event) - angle_initial;
				ruler_length = distance_saved * distance(event)
						/ distance_initial;
				renewRect();
			}
			invalidate();
			break;

		case MotionEvent.ACTION_UP:
				MODE = "NONE";
			break;
		case MotionEvent.ACTION_POINTER_1_UP:
			MultiToSingle = true;
//			MODE = "DRAG";
//			System.out.println(MODE);
//			break;
			MODE = "NONE";
			break;
		}
		return true;
	}

private float rotation(MotionEvent event) {
		double delta_x = (event.getX(0) - event.getX(1));
		double delta_y = (event.getY(0) - event.getY(1));
		double radians = Math.atan2(delta_y, delta_x);
		return (float) Math.toDegrees(radians);
	}

	private float distance(MotionEvent event) {
		double x = (event.getX(0) - event.getX(1));
		double y = (event.getY(0) - event.getY(1));
		return (float) Math.sqrt(x * x + y * y);
	}

	protected float in360(float angel) {
		if (angel >= 360) {
			do {
				angel -= 360;
			} while (angel < 360);
		} else if (angel < 0) {
			do {
				angel += 360;
			} while (angel > 0);
		}
		return angel;
	}

	protected float distanceToMidPoint(PointF touchPoint) {
		double x = (touchPoint.x - mid_point.x);
		double y = (touchPoint.y - mid_point.y);
		return (float) Math.sqrt(x * x + y * y);
	}

	protected PointF supposedPoint(PointF touchPoint) {
		Float k = new Float(Math.toRadians(angle_rotate));
		PointF point_map = new PointF();
		point_map.x = new Float((touchPoint.x - mid_point.x) * Math.cos(k)
				+ (touchPoint.y - mid_point.y) * Math.sin(k) + mid_point.x);
		point_map.y = new Float(-(touchPoint.x - mid_point.x) * Math.sin(k)
				+ (touchPoint.y - mid_point.y) * Math.cos(k) + mid_point.y);
		return point_map;
	}
	
	protected void renewRect() {
		rect.left = (int) (mid_point.x - ruler_length * 0.5);
		rect.right = (int) (mid_point.x + ruler_length * 0.5);
		rect.top = (int) mid_point.y;
		rect.bottom = (int) (mid_point.y + ruler_width);
	}

這中間的邏輯略複雜。。
可以專門寫一篇博客了敲打


源碼在此→http://download.csdn.net/detail/edwardwayne/8492939



發佈了35 篇原創文章 · 獲贊 5 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章