Androidのキャンバスの回転


時々私達はこのような状況に遭遇します.下から上まで縦に表示する必要がありますが、どうすればいいですか?textviewにはこのような属性設定がありますか?残念なことに、このような便利な属性は存在しません.自分でviewを定義してこそ、この要求に合うと思います.どうやって実現しますか?私たちは一つのビューを積載する時から、オンドラーでやりたいことをします.この関数でキャンバスを回転させます.90度でこのような効果が得られます.この時、スクリーンの座標(0,0)は左上から左下になります.システムの絵はすべて原点座標に基づいて描いています.(x 1,y 1)元の座標系(x 0,y 0)との対応関係は(x 1=-y 0,y 1=x 0)で、90度回転すると(x 1=-y 0,y 1=-x 0)です.

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.apis.view;

// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import com.example.android.apis.R;

/**
 * Example of how to write a custom subclass of View. LabelView is used to draw
 * simple text views. Note that it does not handle styled text or right-to-left
 * writing systems.
 * 
 */
public class LabelView extends View {
	private Paint mTextPaint;
	private String mText;
	private int mAscent;

	/**
	 * Constructor. This version is only needed if you will be instantiating the
	 * object manually (not from a layout XML file).
	 * 
	 * @param context
	 */
	public LabelView(Context context) {
		super(context);
		initLabelView();
	}

	/**
	 * Construct object, initializing with any attributes we understand from a
	 * layout file. These attributes are defined in
	 * SDK/assets/res/any/classes.xml.
	 * 
	 * @see android.view.View#View(android.content.Context,
	 *      android.util.AttributeSet)
	 */
	public LabelView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initLabelView();

		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.LabelView);

		CharSequence s = a.getString(R.styleable.LabelView_text);
		if (s != null) {
			setText(s.toString());
		}

		// Retrieve the color(s) to be used for this view and apply them.
		// Note, if you only care about supporting a single color, that you
		// can instead call a.getColor() and pass that to setTextColor().
		setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF000000));

		int textSize = a.getDimensionPixelOffset(
				R.styleable.LabelView_textSize, 0);
		if (textSize > 0) {
			setTextSize(textSize);
		}

		a.recycle();
	}

	private final void initLabelView() {
		mTextPaint = new Paint();
		mTextPaint.setAntiAlias(true);
		mTextPaint.setTextSize(16);
		mTextPaint.setColor(0xFF000000);
		setPadding(3, 3, 3, 3);
	}

	/**
	 * Sets the text to display in this label
	 * 
	 * @param text
	 *            The text to display. This will be drawn as one line.
	 */
	public void setText(String text) {
		mText = text;
		requestLayout();
		invalidate();
	}

	/**
	 * Sets the text size for this label
	 * 
	 * @param size
	 *            Font size
	 */
	public void setTextSize(int size) {
		mTextPaint.setTextSize(size);
		requestLayout();
		invalidate();
	}

	/**
	 * Sets the text color for this label.
	 * 
	 * @param color
	 *            ARGB value for the text
	 */
	public void setTextColor(int color) {
		mTextPaint.setColor(color);
		invalidate();
	}

	/**
	 * @see android.view.View#measure(int, int)
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setMeasuredDimension(measureWidth(widthMeasureSpec),
				measureHeight(heightMeasureSpec));
	}

	/**
	 * Determines the width of this view
	 * 
	 * @param measureSpec
	 *            A measureSpec packed into an int
	 * @return The width of the view, honoring constraints from measureSpec
	 */
	private int measureWidth(int measureSpec) {
		int result = 0;
		int specMode = MeasureSpec.getMode(measureSpec);
		int specSize = MeasureSpec.getSize(measureSpec);

		if (specMode == MeasureSpec.EXACTLY) {
			// We were told how big to be
			result = specSize;
		} else {
			// Measure the text
			result = (int) mTextPaint.measureText(mText) + getPaddingLeft()
					+ getPaddingRight();
			if (specMode == MeasureSpec.AT_MOST) {
				// Respect AT_MOST value if that was what is called for by
				// measureSpec
				result = Math.min(result, specSize);
			}
		}

		return result;
	}

	/**
	 * Determines the height of this view
	 * 
	 * @param measureSpec
	 *            A measureSpec packed into an int
	 * @return The height of the view, honoring constraints from measureSpec
	 */
	private int measureHeight(int measureSpec) {
		int result = 0;
		int specMode = MeasureSpec.getMode(measureSpec);
		int specSize = MeasureSpec.getSize(measureSpec);

		mAscent = (int) mTextPaint.ascent();
		if (specMode == MeasureSpec.EXACTLY) {
			// We were told how big to be
			result = specSize;
		} else {
			// Measure the text (beware: ascent is a negative number)
			result = (int) (-mAscent + mTextPaint.descent()) + getPaddingTop()
					+ getPaddingBottom();
			if (specMode == MeasureSpec.AT_MOST) {
				// Respect AT_MOST value if that was what is called for by
				// measureSpec
				result = Math.min(result, specSize);
			}
		}
		return result;
	}

	/**
	 * Render the text
	 * 
	 * @see android.view.View#onDraw(android.graphics.Canvas)
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		// not rotate
		// canvas.drawText(mText, 200, 500, mTextPaint);

		// rotate 90
		 canvas.rotate(90);
		 canvas.drawText(mText, 500, -200, mTextPaint);
		
		// rotate -90
//		 canvas.rotate(-90);
//		 canvas.drawText(mText, -500, 200, mTextPaint);

	}
}