DrawText

(1)DT_WORDBREAK

只能截断单词。例如如果输入一连串英文字符,那么它会当做一个单词来处理,而不会自动换行。而对于中文字符则可以。如果要对所有字符都可以像Edit控件中那样自动换行,那么可以使用DT_WORDBREAK | DT_EDITCONTROL

 

DT_EDITCONTROL

 

Duplicates the text-displaying characteristics of a multiline edit control. Specifically, the average character width is calculated in the same manner as for an edit control, and the function does not display a partially visible last line.

 

(2)DT_CALRECT的使用

对于一段text,要计算他的显示大小,那么可以使用DT_CALRECT标志。其中的rect参数属于IN/OUT类型。输出时,左上角坐标不变,右下角坐标改变。函数返回值是文本的高度。当然,它要与不同格式标志一起使用得到的结果是不一样的。例如,DT_CALRECT | DT_SINGLELINE 时,它只扩展传入rect的width,而在多行显示的时候,即DT_WORDBREAK | DT_WORDBREAK | DT_EDITCONTROL,仅仅扩展height,width不变。

 

DT_CALCRECT  

 

Determines the width and height of the rectangle. If there are multiple lines of text, DrawText will use the width of the rectangle pointed to by lpRect and extend the base of the rectangle to bound the last line of text. If there is only one line of text, DrawText will modify the right side of the rectangle so that it bounds the last character in the line. In either case, DrawText returns the height of the formatted text, but does not draw the text.

 

(3)DT_CENTER 与 DT_VCENTER

DT_VCENTER只对单行文字的竖直居中有用。DT_CENTER 对单行和多行文字都有用,但只能水平居中。

(4)多行文字的竖直居中

思路:根据显示中心,重新计算要求的显示范围

具体方法:

// ======================================
// = 把str内容显示到客户区的中间,但是每行宽度限定为200,让其自动换行


CRect clientRect;
   GetClientRect(clientRect); // 获得客户区范围

 

CRect rect;
   rect.left = rect.top = 0;
   rect.right = 200;
   rect.bottom = clientRect.bottom;  // 限定宽度


   CString str = "我是来自非洲的姑娘。心中向往神秘的东方,背起行囊寻找梦想,那是龙的故乡
这里的人纯朴善良,淡淡微笑挂脸庞";


   CRect temp = rect;
   int height = pDC->DrawText(str,temp,DT_CENTER | DT_WORDBREAK | DT_CALCRECT | DT_EDITCONTROL); // 获得文本高度
 
   rect.DeflateRect(0,(rect.Height() - height) / 2); // 改变rect


   pDC->DrawText(str,rect, DT_CENTER | DT_EDITCONTROL | DT_WORDBREAK);

 

 

 

转载:http://blog.youkuaiyun.com/dengjiang1999/archive/2009/05/07/4157800.aspx

<think>我们正在讨论Android中的drawText方法的使用。根据引用,drawText是Canvas类的一个方法,用于绘制文本。但是,正确使用它需要理解基线(BaseLine)的概念,以及如何正确设置文本的位置,特别是垂直居中问题。 引用[1]提到,drawText没有想象中的那么好用,并分享了一些心得。引用[2]提到DT_CALCRECT(在Android中对应的是Paint.measureText()等方法)用于计算文本尺寸。引用[3]则展示了通过getTextBounds获取文本边界矩形,并调整绘制位置的方法。 关键点: 1. drawText的y坐标参数是指基线的位置,而不是文本的顶部或底部。 2. 要实现垂直居中,需要计算基线的位置,这可以通过文本的边界矩形(Rect)和字体的度量(FontMetrics)来获得。 步骤: 1. 获取文本的边界矩形(使用Paint.getTextBounds)或测量文本宽度(使用Paint.measureText)。 2. 计算基线的位置:通常,我们想要在某个矩形区域内居中绘制文本,那么基线的y坐标可以通过以下公式计算: baselineY = centerY + (字体下降高度 - 字体的上升高度) / 2 - 字体的下降高度 或者更常见的公式:baselineY = centerY + (descent + ascent) / 2 - descent 但更直观的是:baselineY = centerY - (ascent + descent) / 2 + (descent - ascent) / 2 ?这并不直接。 实际上,更常用的公式是: baselineY = centerY + (Math.abs(fontMetrics.ascent) - fontMetrics.descent) / 2 或者另一种方式:baselineY = centerY + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent 但更简单且准确的方式是使用: baselineY = centerY - (fontMetrics.top + fontMetrics.bottom) / 2 然而,根据引用[3]中的示例,他们使用: canvas.drawText("dangwen", 0, rect.height() - rect.bottom, paint); 这里,他们通过getTextBounds得到的rect,然后设置y坐标为rect.height() - rect.bottom,这样在(0,0)点绘制时,文本会显示在可见区域。 但更通用的垂直居中做法是: ```java // 假设我们在一个矩形区域rectF(或已知中心点centerY)中绘制 Paint paint = new Paint(); paint.setTextSize(textSize); paint.setColor(textColor); // 获取字体度量 Paint.FontMetrics fontMetrics = paint.getFontMetrics(); // 计算基线位置 float baselineY = centerY + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent; // 或者另一种常见写法:baselineY = centerY - (fontMetrics.ascent + fontMetrics.descent) / 2; // 因为ascent是负值,descent是正值,所以实际上: // baselineY = centerY + (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom; // 但更常用的是: float baselineY = centerY - (fontMetrics.ascent + fontMetrics.descent) / 2; ``` 注意:FontMetrics对象有以下属性: - ascent: 从基线到字体最高点的距离(负值) - descent: 从基线到字体最低点的距离(正值) - top: 从基线到字体可绘制区域最高点的距离(负值,绝对值比ascent大) - bottom: 从基线到字体可绘制区域最低点的距离(正值,绝对值比descent大) 因此,为了在矩形区域中垂直居中,我们通常使用: baselineY = centerY - (fontMetrics.ascent + fontMetrics.descent) / 2; 因为 (ascent + descent) 是负值(ascent是负的,descent是正的),所以实际上我们是在向上移动。 另外,水平居中可以使用: float textWidth = paint.measureText(text); float startX = centerX - textWidth / 2; 示例代码: ```java @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); String text = "Hello, Android!"; Paint paint = new Paint(); paint.setAntiAlias(true); paint.setTextSize(50); paint.setColor(Color.BLACK); // 假设我们要在View的中心绘制 int centerX = getWidth() / 2; int centerY = getHeight() / 2; // 计算文本宽度 float textWidth = paint.measureText(text); // 计算基线位置(垂直居中) Paint.FontMetrics fontMetrics = paint.getFontMetrics(); float baselineY = centerY - (fontMetrics.ascent + fontMetrics.descent) / 2; // 水平居中 float startX = centerX - textWidth / 2; canvas.drawText(text, startX, baselineY, paint); } ``` 注意:上面的垂直居中公式在大多数情况下是有效的,但不同的字体可能会有细微差别,可以适当调整。 §§相关问题§§ 1. 在Android中,如何实现文本的水平居中和垂直居中? 2. 除了drawText,还有哪些绘制文本的方法? 3. 如何计算文本的宽度和高度? 4. 如何处理多行文本的绘制?</think>### Android Canvas.drawText() 使用方法详解 `Canvas.drawText()` 是 Android 绘图系统中的核心文本绘制方法,但正确使用需要理解基线(BaseLine)概念和坐标系统。以下是关键使用要点和示例: #### 一、核心概念 1. **基线(BaseLine)** - 文本绘制时以**基线(y 坐标)**为基准,而非文本底部或顶部 - 字母如 "g" 的下沉部分在基线下方,大写字母在基线上方[^1] - 坐标系:**向下为正方向**(与传统数学坐标相反) 2. **文本边界测量** 使用 `Paint.getTextBounds()` 获取文本实际边界矩形: ```java Rect textBounds = new Rect(); paint.getTextBounds(text, 0, text.length(), textBounds); // 获取关键值: int height = textBounds.height(); // 文本实际高度 int bottom = textBounds.bottom; // 基线到底部的距离(正值) ``` #### 二、垂直居中方案 ```java @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); String text = "Hello 你好"; int centerX = getWidth() / 2; int centerY = getHeight() / 2; // 1. 创建画笔并设置属性 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setTextSize(60); paint.setColor(Color.BLACK); // 2. 测量文本边界 Rect textBounds = new Rect(); paint.getTextBounds(text, 0, text.length(), textBounds); // 3. 计算基线位置(关键步骤) float baselineY = centerY + (textBounds.height()/2 - textBounds.bottom); // 4. 水平居中绘制 float textWidth = paint.measureText(text); canvas.drawText(text, centerX - textWidth/2, baselineY, paint); } ``` #### 三、其他使用场景 **1. 多行文本绘制** ```java // 设置自动换行 StaticLayout layout = new StaticLayout(text, paint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); canvas.save(); canvas.translate(x, y); layout.draw(canvas); canvas.restore(); ``` **2. 文本尺寸计算** ```java // 获取推荐行高 float lineHeight = paint.getFontMetrics(null); // 测量文本宽度 float textWidth = paint.measureText(text); // 获取字体度量 Paint.FontMetrics fm = paint.getFontMetrics(); float totalHeight = fm.bottom - fm.top; // 完整行高 ``` #### 四、常见问题解决 1. **文本显示不全** - 原因:未考虑下沉字母(g/y等)需要额外空间 - 解决:增加绘制区域高度 `textBounds.height() + Math.abs(textBounds.top)` 2. **位置偏差** - 使用 `Paint.setTextAlign(Paint.Align.CENTER)` 可简化水平居中 - 避免使用 `canvas.drawText(text, 0, 0, paint)`(文本会完全位于屏幕外) 3. **性能优化** - 在 `onDraw()` 外初始化 `Paint` 和测量操作 - 对静态文本使用 `Bitamp` 缓存 > 完整示例项目: > [GitHub - AndroidTextDrawingDemo](https://github.com/example/TextDrawingDemo) > 包含 10+ 种文本绘制场景实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值