【问题标题】:Android TextView: How to place text above specific position in line/Setting height for ReplacementScan subclassAndroid TextView:如何在行中的特定位置上方放置文本/为 ReplacementScan 子类设置高度
【发布时间】:2014-01-11 02:29:35
【问题描述】:

我正在尝试在 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);
    }
}

您会看到和弦对齐并正确绘制,但与“The line above”重叠。

有没有办法实现我想要的,即在绘制我的自定义 Span 时以某种方式调整线条的线条高度?我还没有找到任何关于 ReplacementSpan 子类的好例子。

或者,我很乐意收到有关如何达到预期效果的其他建议。也许我在想一个完全错误的方向。

感谢您到目前为止的阅读以及提供的任何帮助!

【问题讨论】:

    标签: android textview


    【解决方案1】:

    在 Android 源代码中挖掘了一段时间后,我想我找到了解决方案:ReplacementSpangetSize 方法不仅应该将 Span 的宽度返回为 int,而且还可以更改 @ 987654324@ 作为参数传递。

    因此,使用以下代码,行距可以按需要工作:

    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));
    
    }
    

    【讨论】:

    • 值得注意的是 fm != null 检查是必要的。
    猜你喜欢
    • 1970-01-01
    • 2016-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 2014-01-18
    相关资源
    最近更新 更多