2

我需要在特定框内的画布上绘制文本。我已经在使用 DynamicLayout 来自动计算和换行以适应框的宽度。现在我需要自动椭圆化文本以适应框高度。

我怎样才能做到这一点?它不一定需要高度(像素),它可以是最大行数。


例子:

“这是一个适合框内的示例文本”

实际结果:

------------
|This is a |
|text to   |
|fit inside|
------------
 the box   

预期结果:

------------
|This is a |
|text to   |
|fit in... |
------------

我这样创建 DynamicLayout:

textLayout = new DynamicLayout(mText, mTextPaint, 100, Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);

然后我画成这样:

canvas.save();
canvas.translate(500, 500 - textLayout.getHeight() / 2);
textLayout.draw(canvas);
canvas.restore();
4

4 回答 4

4

由于我知道框内的行数 ( mMaxLines),我扩展了 DynamicLayout 并覆盖了一些方法:

@Override
public int getLineCount() {
    if (super.getLineCount() - 1 > mMaxLines) {
        return mMaxLines;
    }
    return super.getLineCount() - 1;
}

@Override
public int getEllipsisCount(int line) {
    if (line == mMaxLines - 1 && super.getLineCount() - 2 > line) {
        return 1;
    }
    return 0;
}

@Override
public int getEllipsisStart(int line) {
    if (line == mMaxLines - 1 && super.getLineCount() - 2 > line) {
        return getLineEnd(line) - getLineStart(line) - 1;
    }
    return 0;
}

然后我有以下结果:

------------
|This is a |
|text to   |
|fit in... |
------------
于 2013-06-30T15:41:21.877 回答
0

请在下面与我们相同的 DynamicLayout 中添加参数。DynamicLayout(CharSequence base, CharSequence display, TextPaint paint, int width, Layout.Alignment align, float spacingmult, float spacingadd, boolean includepad, TextUtils.TruncateAt ellipsize, int ellipsizedWidth);

于 2013-06-27T12:10:42.200 回答
0

对于未来的读者,试试这个 StaticLayoutWithMaxLines backport:

import android.os.Build;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextDirectionHeuristic;
import android.text.TextDirectionHeuristics;
import android.text.TextPaint;
import android.text.TextUtils.TruncateAt;
import android.util.Log;

import java.lang.reflect.Constructor;

public class StaticLayoutWithMaxLines {
private static final String LOGTAG =  StaticLayoutWithMaxLines.class.getSimpleName();

private static final String TEXT_DIR_CLASS = "android.text.TextDirectionHeuristic";
private static final String TEXT_DIRS_CLASS = "android.text.TextDirectionHeuristics";
private static final String TEXT_DIR_FIRSTSTRONG_LTR = "FIRSTSTRONG_LTR";

private static boolean sInitialized;

private static Constructor<StaticLayout> sConstructor;
private static Object[] sConstructorArgs;
private static Object sTextDirection;

public static synchronized void ensureInitialized() {
    if (sInitialized) {
        return;
    }

    try {
        final Class<?> textDirClass;
        if (Build.VERSION.SDK_INT >= 18) {
            textDirClass = TextDirectionHeuristic.class;
            sTextDirection = TextDirectionHeuristics.FIRSTSTRONG_LTR;
        } else {
            final ClassLoader loader = StaticLayoutWithMaxLines.class.getClassLoader();
            textDirClass = loader.loadClass(TEXT_DIR_CLASS);

            final Class<?> textDirsClass = loader.loadClass(TEXT_DIRS_CLASS);
            sTextDirection = textDirsClass.getField(TEXT_DIR_FIRSTSTRONG_LTR)
                                          .get(textDirsClass);
        }

        final Class<?>[] signature = new Class[] {
                CharSequence.class,
                int.class,
                int.class,
                TextPaint.class,
                int.class,
                Alignment.class,
                textDirClass,
                float.class,
                float.class,
                boolean.class,
                TruncateAt.class,
                int.class,
                int.class
        };

        // Make the StaticLayout constructor with max lines public
        sConstructor = StaticLayout.class.getDeclaredConstructor(signature);
        sConstructor.setAccessible(true);
        sConstructorArgs = new Object[signature.length];
    } catch (NoSuchMethodException e) {
        Log.e(LOGTAG, "StaticLayout constructor with max lines not found.", e);
    } catch (ClassNotFoundException e) {
        Log.e(LOGTAG, "TextDirectionHeuristic class not found.", e);
    } catch (NoSuchFieldException e) {
        Log.e(LOGTAG, "TextDirectionHeuristics.FIRSTSTRONG_LTR not found.", e);
    } catch (IllegalAccessException e) {
        Log.e(LOGTAG, "TextDirectionHeuristics.FIRSTSTRONG_LTR not accessible.", e);
    } finally {
        sInitialized = true;
    }
}

public static boolean isSupported() {
    if (Build.VERSION.SDK_INT < 14) {
        return false;
    }

    ensureInitialized();
    return (sConstructor != null);
}

public static synchronized StaticLayout create(CharSequence source, int bufstart, int bufend,
                                               TextPaint paint, int outerWidth, Alignment align,
                                               float spacingMult, float spacingAdd,
                                               boolean includePad, TruncateAt ellipsize,
                                               int ellipsisWidth, int maxLines) {
    ensureInitialized();

    try {
        sConstructorArgs[0] = source;
        sConstructorArgs[1] = bufstart;
        sConstructorArgs[2] = bufend;
        sConstructorArgs[3] = paint;
        sConstructorArgs[4] = outerWidth;
        sConstructorArgs[5] = align;
        sConstructorArgs[6] = sTextDirection;
        sConstructorArgs[7] = spacingMult;
        sConstructorArgs[8] = spacingAdd;
        sConstructorArgs[9] = includePad;
        sConstructorArgs[10] = ellipsize;
        sConstructorArgs[11] = ellipsisWidth;
        sConstructorArgs[12] = maxLines;

        return sConstructor.newInstance(sConstructorArgs);
    } catch (Exception e) {
        throw new IllegalStateException("Error creating StaticLayout with max lines: " + e);
    }
}

}

来自这里的代码片段。

并像这样使用它:

canvas.save();
CharSequence text = YOUR TEXT HERE;
StaticLayout textLayout = StaticLayoutWithMaxLines.create(text, 0, text.length(),
mPaintText, canvas.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false,
                    TextUtils.TruncateAt.END, canvas.getWidth(), 4);

canvas.translate(mViewCenterX, y + mItemHeight / 2 - textLayout.getHeight() / 2);
textLayout.draw(canvas);
canvas.restore();
于 2017-08-10T15:07:21.860 回答
-1

参考这个自动椭圆

http://developer.android.com/reference/android/widget/TextView.html#attr_android%3aellipsize

于 2013-06-27T11:25:34.127 回答