Android Tutorial - 2D Graphics : Text
Set Paint Text size
package app.Test; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Path.Direction; import android.os.Bundle; import android.view.View; public class appTest extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new GraphicsView(this)); } static public class GraphicsView extends View { private static final String QUOTE = "This is a test. This is a demo."; private Path circle; private Paint cPaint; private Paint tPaint; public GraphicsView(Context context) { super(context); int color = Color.argb(127, 255, 0, 255); circle = new Path(); circle.addCircle(150, 150, 100, Direction.CW); cPaint = new Paint(Paint.ANTI_ALIAS_FLAG); cPaint.setStyle(Paint.Style.STROKE); cPaint.setColor(Color.LTGRAY); cPaint.setStrokeWidth(3); setBackgroundResource(R.drawable.icon); tPaint = new Paint(Paint.ANTI_ALIAS_FLAG); tPaint.setStyle(Paint.Style.FILL_AND_STROKE); tPaint.setColor(Color.BLACK); tPaint.setTextSize(20f); } @Override protected void onDraw(Canvas canvas) { canvas.drawTextOnPath(QUOTE, circle, 0, 20, tPaint); } } } //main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/icon"> <org.example.graphics.Graphics.GraphicsView android:id="@+id/graphics" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout> //strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Graphics</string> </resources> //colors.xml <?xml version="1.0" encoding="utf-8"?> <resources> <color name="mycolor">#7fff00ff</color> </resources>
Draw text
package app.test; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.widget.ImageView; public class Test extends Activity { ImageView drawingImageView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); drawingImageView = (ImageView) this.findViewById(R.id.DrawingImageView); Bitmap bitmap = Bitmap.createBitmap((int) getWindowManager() .getDefaultDisplay().getWidth(), (int) getWindowManager() .getDefaultDisplay().getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawingImageView.setImageBitmap(bitmap); // Text Paint paint = new Paint(); paint.setColor(Color.GREEN); paint.setTextSize(40); float text_x = 120; float text_y = 120; canvas.drawText("Hello", text_x, text_y, paint); } }
Text on a Path
package app.test; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Typeface; import android.os.Bundle; import android.widget.ImageView; public class Test extends Activity { ImageView drawingImageView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); drawingImageView = (ImageView) this.findViewById(R.id.DrawingImageView); Bitmap bitmap = Bitmap.createBitmap((int) getWindowManager() .getDefaultDisplay().getWidth(), (int) getWindowManager() .getDefaultDisplay().getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawingImageView.setImageBitmap(bitmap); // Text on a Path Paint paint = new Paint(); paint.setColor(Color.GREEN); paint.setTextSize(20); paint.setTypeface(Typeface.DEFAULT); Path p = new Path(); p.moveTo(20, 20); p.lineTo(100, 150); p.lineTo(200, 220); canvas.drawTextOnPath("Hello this is text on a path", p, 0, 0, paint); } }
Text Align
package app.test; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Picture; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; public class Test extends GraphicsActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new SampleView(this)); } private static class SampleView extends View { private Paint mPaint; private float mX; private float[] mPos; private Path mPath; private Paint mPathPaint; private static final int DY = 30; private static final String TEXT_L = "Left"; private static final String TEXT_C = "Center"; private static final String TEXT_R = "Right"; private static final String POSTEXT = "Positioned"; private static final String TEXTONPATH = "Along a path"; private static void makePath(Path p) { p.moveTo(10, 0); p.cubicTo(100, -50, 200, 50, 300, 0); } private float[] buildTextPositions(String text, float y, Paint paint) { float[] widths = new float[text.length()]; // initially get the widths for each char int n = paint.getTextWidths(text, widths); // now popuplate the array, interleaving spaces for the Y values float[] pos = new float[n * 2]; float accumulatedX = 0; for (int i = 0; i < n; i++) { pos[i * 2 + 0] = accumulatedX; pos[i * 2 + 1] = y; accumulatedX += widths[i]; } return pos; } public SampleView(Context context) { super(context); setFocusable(true); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setTextSize(30); mPaint.setTypeface(Typeface.SERIF); mPos = buildTextPositions(POSTEXT, 0, mPaint); mPath = new Path(); makePath(mPath); mPathPaint = new Paint(); mPathPaint.setAntiAlias(true); mPathPaint.setColor(0x800000FF); mPathPaint.setStyle(Paint.Style.STROKE); } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(Color.WHITE); Paint p = mPaint; float x = mX; float y = 0; float[] pos = mPos; // draw the normal strings p.setColor(0x80FF0000); canvas.drawLine(x, y, x, y + DY * 3, p); p.setColor(Color.BLACK); canvas.translate(0, DY); p.setTextAlign(Paint.Align.LEFT); canvas.drawText(TEXT_L, x, y, p); canvas.translate(0, DY); p.setTextAlign(Paint.Align.CENTER); canvas.drawText(TEXT_C, x, y, p); canvas.translate(0, DY); p.setTextAlign(Paint.Align.RIGHT); canvas.drawText(TEXT_R, x, y, p); canvas.translate(100, DY * 2); // now draw the positioned strings p.setColor(0xBB00FF00); for (int i = 0; i < pos.length / 2; i++) { canvas.drawLine(pos[i * 2 + 0], pos[i * 2 + 1] - DY, pos[i * 2 + 0], pos[i * 2 + 1] + DY * 2, p); } p.setColor(Color.BLACK); p.setTextAlign(Paint.Align.LEFT); canvas.drawPosText(POSTEXT, pos, p); canvas.translate(0, DY); p.setTextAlign(Paint.Align.CENTER); canvas.drawPosText(POSTEXT, pos, p); canvas.translate(0, DY); p.setTextAlign(Paint.Align.RIGHT); canvas.drawPosText(POSTEXT, pos, p); // now draw the text on path canvas.translate(-100, DY * 2); canvas.drawPath(mPath, mPathPaint); p.setTextAlign(Paint.Align.LEFT); canvas.drawTextOnPath(TEXTONPATH, mPath, 0, 0, p); canvas.translate(0, DY * 1.5f); canvas.drawPath(mPath, mPathPaint); p.setTextAlign(Paint.Align.CENTER); canvas.drawTextOnPath(TEXTONPATH, mPath, 0, 0, p); canvas.translate(0, DY * 1.5f); canvas.drawPath(mPath, mPathPaint); p.setTextAlign(Paint.Align.RIGHT); canvas.drawTextOnPath(TEXTONPATH, mPath, 0, 0, p); } @Override protected void onSizeChanged(int w, int h, int ow, int oh) { super.onSizeChanged(w, h, ow, oh); mX = w * 0.5f; // remember the center of the screen } } } class GraphicsActivity extends Activity { // set to true to test Picture private static final boolean TEST_PICTURE = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void setContentView(View view) { if (TEST_PICTURE) { ViewGroup vg = new PictureLayout(this); vg.addView(view); view = vg; } super.setContentView(view); } } class PictureLayout extends ViewGroup { private final Picture mPicture = new Picture(); public PictureLayout(Context context) { super(context); } public PictureLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void addView(View child) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child); } @Override public void addView(View child, int index) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child, index); } @Override public void addView(View child, LayoutParams params) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child, params); } @Override public void addView(View child, int index, LayoutParams params) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child, index, params); } @Override protected LayoutParams generateDefaultLayoutParams() { return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int count = getChildCount(); int maxHeight = 0; int maxWidth = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { measureChild(child, widthMeasureSpec, heightMeasureSpec); } } maxWidth += getPaddingLeft() + getPaddingRight(); maxHeight += getPaddingTop() + getPaddingBottom(); Drawable drawable = getBackground(); if (drawable != null) { maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); } setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), resolveSize(maxHeight, heightMeasureSpec)); } private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx, float sy) { canvas.save(); canvas.translate(x, y); canvas.clipRect(0, 0, w, h); canvas.scale(0.5f, 0.5f); canvas.scale(sx, sy, w, h); canvas.drawPicture(mPicture); canvas.restore(); } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight())); mPicture.endRecording(); int x = getWidth() / 2; int y = getHeight() / 2; if (false) { canvas.drawPicture(mPicture); } else { drawPict(canvas, 0, 0, x, y, 1, 1); drawPict(canvas, x, 0, x, y, -1, 1); drawPict(canvas, 0, y, x, y, 1, -1); drawPict(canvas, x, y, x, y, -1, -1); } } @Override public ViewParent invalidateChildInParent(int[] location, Rect dirty) { location[0] = getLeft(); location[1] = getTop(); dirty.set(0, 0, getWidth(), getHeight()); return getParent(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = super.getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { final int childLeft = getPaddingLeft(); final int childTop = getPaddingTop(); child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight()); } } } }
Measure Text
package app.test; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Picture; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; public class Test extends GraphicsActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new SampleView(this)); } private static final int WIDTH = 50; private static final int HEIGHT = 50; private static final int STRIDE = 64; // must be >= WIDTH private static int[] createColors() { int[] colors = new int[STRIDE * HEIGHT]; for (int y = 0; y < HEIGHT; y++) { for (int x = 0; x < WIDTH; x++) { int r = x * 255 / (WIDTH - 1); int g = y * 255 / (HEIGHT - 1); int b = 255 - Math.min(r, g); int a = Math.max(r, g); colors[y * STRIDE + x] = (a << 24) | (r << 16) | (g << 8) | b; } } return colors; } private static class SampleView extends View { private Paint mPaint; private float mOriginX = 10; private float mOriginY = 80; public SampleView(Context context) { super(context); setFocusable(true); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStrokeWidth(5); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setTextSize(64); mPaint.setTypeface(Typeface.create(Typeface.SERIF, Typeface.ITALIC)); } private void showText(Canvas canvas, String text, Paint.Align align) { // mPaint.setTextAlign(align); Rect bounds = new Rect(); float[] widths = new float[text.length()]; int count = mPaint.getTextWidths(text, 0, text.length(), widths); float w = mPaint.measureText(text, 0, text.length()); mPaint.getTextBounds(text, 0, text.length(), bounds); mPaint.setColor(0xFF88FF88); canvas.drawRect(bounds, mPaint); mPaint.setColor(Color.BLACK); canvas.drawText(text, 0, 0, mPaint); float[] pts = new float[2 + count*2]; float x = 0; float y = 0; pts[0] = x; pts[1] = y; for (int i = 0; i < count; i++) { x += widths[i]; pts[2 + i*2] = x; pts[2 + i*2 + 1] = y; } mPaint.setColor(Color.RED); mPaint.setStrokeWidth(0); canvas.drawLine(0, 0, w, 0, mPaint); mPaint.setStrokeWidth(5); canvas.drawPoints(pts, 0, (count + 1) << 1, mPaint); } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(Color.WHITE); canvas.translate(mOriginX, mOriginY); showText(canvas, "Measure", Paint.Align.LEFT); canvas.translate(0, 80); showText(canvas, "wiggy!", Paint.Align.CENTER); canvas.translate(0, 80); showText(canvas, "Text", Paint.Align.RIGHT); } } } class GraphicsActivity extends Activity { // set to true to test Picture private static final boolean TEST_PICTURE = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void setContentView(View view) { if (TEST_PICTURE) { ViewGroup vg = new PictureLayout(this); vg.addView(view); view = vg; } super.setContentView(view); } } class PictureLayout extends ViewGroup { private final Picture mPicture = new Picture(); public PictureLayout(Context context) { super(context); } public PictureLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void addView(View child) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child); } @Override public void addView(View child, int index) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child, index); } @Override public void addView(View child, LayoutParams params) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child, params); } @Override public void addView(View child, int index, LayoutParams params) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child, index, params); } @Override protected LayoutParams generateDefaultLayoutParams() { return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int count = getChildCount(); int maxHeight = 0; int maxWidth = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { measureChild(child, widthMeasureSpec, heightMeasureSpec); } } maxWidth += getPaddingLeft() + getPaddingRight(); maxHeight += getPaddingTop() + getPaddingBottom(); Drawable drawable = getBackground(); if (drawable != null) { maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); } setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), resolveSize(maxHeight, heightMeasureSpec)); } private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx, float sy) { canvas.save(); canvas.translate(x, y); canvas.clipRect(0, 0, w, h); canvas.scale(0.5f, 0.5f); canvas.scale(sx, sy, w, h); canvas.drawPicture(mPicture); canvas.restore(); } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight())); mPicture.endRecording(); int x = getWidth() / 2; int y = getHeight() / 2; if (false) { canvas.drawPicture(mPicture); } else { drawPict(canvas, 0, 0, x, y, 1, 1); drawPict(canvas, x, 0, x, y, -1, 1); drawPict(canvas, 0, y, x, y, 1, -1); drawPict(canvas, x, y, x, y, -1, -1); } } @Override public ViewParent invalidateChildInParent(int[] location, Rect dirty) { location[0] = getLeft(); location[1] = getTop(); dirty.set(0, 0, getWidth(), getHeight()); return getParent(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = super.getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { final int childLeft = getPaddingLeft(); final int childTop = getPaddingTop(); child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight()); } } } }
Get Text Width
import android.graphics.Paint; class Main { public static float GetTextWidth(String Sentence, float Size) { Paint FontPaint = new Paint(); FontPaint.setTextSize(Size); return FontPaint.measureText(Sentence.trim()) + (int) (Size * 0.1); // ??????? } }
Using Spannable text and set style
package app.test; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.text.Spannable; import android.text.style.BackgroundColorSpan; import android.text.style.StyleSpan; import android.text.util.Linkify; import android.widget.EditText; import android.widget.TextView; public class Test extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView tv =(TextView)this.findViewById(R.id.tv); tv.setAutoLinkMask(Linkify.ALL); tv.setText("asdf"); TextView tv3 =(TextView)this.findViewById(R.id.tv3); tv3.setText("asdf",TextView.BufferType.SPANNABLE); Spannable spn = (Spannable) tv3.getText(); spn.setSpan(new BackgroundColorSpan(Color.RED), 0, 7,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spn.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC),0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); EditText et =(EditText)this.findViewById(R.id.et); et.setText("asdf"); Spannable spn2 = (Spannable) et.getText(); spn2.setSpan(new BackgroundColorSpan(Color.RED), 0, 7,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spn2.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC),0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } //main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:autoLink="web|map" android:text="Please visit www.androidbook.com for more help on using Android." android:minLines="5" android:typeface="serif" /> <TextView android:id="@+id/tv" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/tvStyled" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@+string/styledText" /> <TextView android:id="@+id/tv3" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <EditText android:id="@+id/et" android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputType="text|textAutoCorrect|textAutoComplete|textMultiLine" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/tv" /> <TextView android:id="@+id/errors" style="@style/ErrorText" android:text="There's trouble down at the mill." /> <TextView android:id="@+id/danger" style="@style/ErrorText.Danger" android:text="SERIOUSLY! THERE'S TROUBLE DOWN AT THE MILL!!" /> </LinearLayout> //strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, ActivityMenu</string> <string name="app_name">HelloMenu</string> <string name="button1">button1</string> <string name="button2">button2</string> <string name="tv">I am a TextView</string> <string name="et">I am an EditText</string> <string name="actv">AutoComplete:</string> <string name="mactv">MultiAutoComplete:</string> </resources> //styles.xml <?xml version="1.0" encoding="utf-8"?> <resources> <style name="ErrorText"> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:textColor">#FF0000</item> <item name="android:typeface">monospace</item> </style> <style name="ErrorText.Danger" > <item name="android:textStyle">bold</item> </style> </resources>
Rotate and transformation
package com.ai.android.ExerciseSystemIntents; import android.util.Log; import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; import android.view.animation.LinearInterpolator; import android.view.animation.Transformation; import android.graphics.Camera; import android.graphics.Matrix; public class ViewAnimation1 extends Animation { float centerX, centerY; Camera cam = new Camera(); public ViewAnimation1(float cx, float cy) { centerX = cx; centerY = cy; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); Log.d("d","width:" + width); Log.d("d","height:" + height); Log.d("d","pwidth:" + parentWidth); Log.d("d","pheight:" + parentHeight); setDuration(2500); setFillAfter(true); setInterpolator(new LinearInterpolator()); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { applyTransformationNew(interpolatedTime,t); } protected void applyTransformationNew(float interpolatedTime, Transformation t) { final Matrix matrix = t.getMatrix(); cam.save(); cam.translate(0.0f, 0.0f, (1300 - 1300.0f * interpolatedTime)); cam.rotateY(360 * interpolatedTime); cam.getMatrix(matrix); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); cam.restore(); } }