我有一个自定义的TextView,它覆盖了onDraw
方法,在文本视图周围绘制一个红色边框。
当我将引力设置为左边的其他内容 AND singleLine = true 时:未绘制边框。
以下屏幕截图说明了问题:第二个textView没有边框
TL表示TOP | LEFT; C表示CENTER; SL意味着单行; T意味着真实; F表示错误
这是代码(可以复制/粘贴和运行 - 不需要布局文件)
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MyActivity extends Activity {
private final int TEXT_VIEW_WIDTH_PX = 400;
private final int TEXT_VIEW_HEIGHT_PX = 60;
private Paint borderPaint = new Paint();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout rootView = new RelativeLayout(this);
getWindow().setContentView(rootView);
borderPaint.setColor(Color.RED);
MyTextView text1 = makeTextView("Grav=TL ; SL=F",100);
rootView.addView(text1);
MyTextView text2 = makeTextView("Grav=C ; SL=T",200);
//combination of the 2 following attributes cause the issue
text2.setSingleLine(true);
text2.setGravity(Gravity.CENTER);
rootView.addView(text2);
MyTextView text3 = makeTextView("Grav=C ; SL=F",300);
text3.setGravity(Gravity.CENTER);
rootView.addView(text3);
MyTextView text4 = makeTextView("Grav=TL ; SL=T",400);
text4.setSingleLine(true);
rootView.addView(text4);
}
/**
* Custom TextView with red border
*/
private class MyTextView extends TextView {
private MyTextView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(1,1,1,TEXT_VIEW_HEIGHT_PX-1,borderPaint);
canvas.drawLine(1,1,TEXT_VIEW_WIDTH_PX-1,1,borderPaint);
canvas.drawLine(TEXT_VIEW_WIDTH_PX-1,1,TEXT_VIEW_WIDTH_PX-1,TEXT_VIEW_HEIGHT_PX-1,borderPaint);
canvas.drawLine(1,TEXT_VIEW_HEIGHT_PX-1,TEXT_VIEW_WIDTH_PX-1,TEXT_VIEW_HEIGHT_PX-1,borderPaint);
}
}
/**
* create a MyTextView with 'text' context and located at x=50 ; y=marginTop
* (nothing relevant for the issue here)
*/
private MyTextView makeTextView(String text, int marginTop){
MyTextView textView = new MyTextView(this);
textView.setText(text);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(TEXT_VIEW_WIDTH_PX,TEXT_VIEW_HEIGHT_PX);
lp.topMargin = marginTop;
lp.leftMargin = 50;
textView.setLayoutParams(lp);
return textView;
}
}
答案 0 :(得分:7)
感谢pskink的彻底研究(来自对我的另一个答案的评论):
如果您想知道为什么自定义
onDraw
没有绘制任何内容,只需Log.d
canvas.getMatrix()
的值。[它]似乎画布被翻译/水平滚动(至少在我的情况下)左侧8159像素,因此调用
canvas.translate(8159, 0)
修复了问题,当然8159不是幻数并且可以变化。我找到了,在
VERY_WIDE
中看TextView
常数,设置为16384(2 ** 14),在我的情况下TextView
的宽度为66,现在(16384- 66)/ 2 == 8159,瞧!...但是VERY_WIDE是私有的,所以你无法访问它: - (
从这里开始,我想知道是否可以通过getScrollX()
轻松地以编程方式检索偏移量,并确保它可以检索到。这种方法通过取消水平滚动来转换画布而不是“黑客”单行。它更自然地显示单行。
内部自定义TextView
:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// translate the canvas before drawing onto it, fixing the position
canvas.translate(getScrollX(), 0);
canvas.drawLine(1, 1, 1, TEXT_VIEW_HEIGHT_PX - 1, borderPaint);
canvas.drawLine(1, 1, TEXT_VIEW_WIDTH_PX - 1, 1, borderPaint);
canvas.drawLine(TEXT_VIEW_WIDTH_PX - 1, 1, TEXT_VIEW_WIDTH_PX - 1,
TEXT_VIEW_HEIGHT_PX - 1, borderPaint);
canvas.drawLine(1, TEXT_VIEW_HEIGHT_PX - 1, TEXT_VIEW_WIDTH_PX - 1,
TEXT_VIEW_HEIGHT_PX - 1, borderPaint);
}
此代码尚未针对所有情况进行彻底测试。我只确认了OP
提供的4个案例答案 1 :(得分:3)
问题似乎来自setSingleLine()
。解决方法是在setHorizontallyScrolling(false)
之后调用setSingleLine(true)
,但如果文本太长,这将“包装”文本。您甚至无法使用setEllipsize()
截断它;它没有任何影响。
MyTextView text2 = makeTextView(
"Grav=C ; SL=T a ab abc abcd abcde abcdef abcdefg abcdefgh abcdefghi",
200);
text2.setSingleLine(true);
text2.setHorizontallyScrolling(false);
text2.setGravity(Gravity.CENTER);
我仍然无法确定问题,但我的猜测是在单行上。
调用text2.setSingleLine(true);
时,Android会执行此操作:
public void setSingleLine(boolean singleLine) {
setInputTypeSingleLine(singleLine);
applySingleLine(singleLine, true, true);
}
// no effect, since there is no editor
/*
private void setInputTypeSingleLine(boolean singleLine) {
if (mEditor != null &&
(mEditor.mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
if (singleLine) {
mEditor.mInputType &= ~EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
} else {
mEditor.mInputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
}
}
}
*/
private void applySingleLine(boolean singleLine, boolean applyTransformation,
boolean changeMaxLines) {
mSingleLine = singleLine;
if (singleLine) {
setLines(1);
setHorizontallyScrolling(true);
if (applyTransformation) {
setTransformationMethod(SingleLineTransformationMethod.getInstance());
}
} else {
if (changeMaxLines) {
setMaxLines(Integer.MAX_VALUE);
}
setHorizontallyScrolling(false);
if (applyTransformation) {
setTransformationMethod(null);
}
}
}
从这里开始,我总结说applySingleLine()
中的某个地方导致了这个问题。因此,我尝试通过将代码更改为下面来“模拟”单行,问题仍然存在。
MyTextView text2 = makeTextView("Grav=C ; SL=T",200);
//text2.setSingleLine(true);
text2.setLines(1);
text2.setHorizontallyScrolling(true);
text2.setTransformationMethod(SingleLineTransformationMethod.getInstance());
text2.setGravity(Gravity.CENTER);
rootView.addView(text2);
但是当我对setHorizontallyScrolling(true)
发表评论时,问题就消失了!因此,通过在setHorizontallyScrolling(false)
之后调用setSingleLine(true)
,它会否定效果并解决问题,但如果文本太长,这将“包装”文本。