我正试图在TextView中用和弦显示歌词.为此,我需要在正文的特定部分上方放置字母或符号.到目前为止,我的想法是将ReplacementSpan子类化为:
import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.FontMetricsInt; import android.text.style.ReplacementSpan; public class ChordSpan extends ReplacementSpan { String chord; public ChordSpan(String chord) { super(); this.chord = chord; } @Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { FontMetricsInt fm = paint.getFontMetricsInt(); int space = fm.ascent-fm.descent+fm.leading; canvas.drawText(text, start, end, x, y, paint); canvas.drawText(chord, x, y+space, paint); } @Override public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) { return Math.round(paint.measureText(text, start, end)); } }
这可以很好地将和弦符号放在文本上方.但是,当我添加和弦时,我还没有找到一种调整行高的方法,因此和弦会在TextView中的前一行中被绘制.这段代码演示了我的意思:
package com.example.chordspan; import android.os.Bundle; import android.app.Activity; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.view.Gravity; import android.widget.TextView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this.getBaseContext()); tv.setGravity(Gravity.CENTER_VERTICAL); SpannableStringBuilder sb = new SpannableStringBuilder(); sb.append("The line above\n"); int start = sb.length(); sb.append("A line with chords\n"); sb.setSpan(new ChordSpan("C"), start, start+2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); sb.setSpan(new ChordSpan("Am"), start+7, start+11, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); sb.append("The line below"); tv.setText(sb); setContentView(tv); } }
您将看到和弦已对齐并正确绘制,但与"上面的线"重叠.
有没有办法实现我想要的,即在绘制我的自定义跨度时以某种方式调整线条的线条高度?我还没有找到任何有关ReplacementSpan子类的好例子.
或者,我很乐意收到有关如何达到预期效果的其他建议.也许我正在思考一个完全错误的方向.
感谢您阅读到目前为止,并提供任何帮助!
四处寻找在Android源相当长一段时间之后,我想我找到了解决方案:ReplacementSpan
的getSize
方法不应该只返回跨度的宽度为int
,但也可以改变FontMetricsInt
作为参数传递.
因此,使用以下代码,行间距按预期工作:
public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) { if ( fm != null ) { int space = paint.getFontMetricsInt(fm); fm.ascent -= space; fm.top -= space; } return Math.round(paint.measureText(text, start, end)); }