2014-12-03 2 views
3

Я пытаюсь добавить красной волнистой линией ниже ошибок в текстах, таких как:Как добавить красной волнистой линии ниже текст в TextView Андроида

enter image description here

К сожалению, я не могу найти правильный * Span класс, чтобы обернуть текст ошибки.

Как следует реализовать такую ​​функцию в Android?

+0

вы пробовали что-нибудь до сих пор? –

+0

ну, я исследовал существующие классы Span, но не нашел ни одного, соответствующего этому требованию. Я пытаюсь найти способ сделать это, в настоящее время исследуя создание пользовательского Span. Но мне интересно, не пропустил ли я что-нибудь, что мне неизвестно, реализация с открытым исходным кодом или даже правильный учебник о том, как реализовать что-то подобное. – Iftah

ответ

0

Код bpronin для меня не работал - диапазон был слишком мал на экране с высоким разрешением, и он охватывал весь текст, а не только исправную ошибку.

Но после его идея, которую я обновил свой ответ, чтобы удалить потребность добавленного ресурса:

public class ErrorSpan extends DynamicDrawableSpan { 

    private int width; 
    int lineWidth; 
    int waveSize; 
    int color; 


    public ErrorSpan(Resources resources) { 
     this(resources, Color.RED, 1, 3); 
    } 

    public ErrorSpan(Resources resources, int color, int lineWidth, int waveSize) { 
     super(DynamicDrawableSpan.ALIGN_BASELINE); 
     // Get the screen's density scale 
     final float scale = resources.getDisplayMetrics().density; 
     // Convert the dps to pixels, based on density scale 
     this.lineWidth = (int) (lineWidth * scale + 0.5f); 
     this.waveSize = (int) (waveSize * scale + 0.5f); 
     this.color = color; 
    } 

    @Override 
    public Drawable getDrawable() { 
     return null; 
    } 

    @Override 
    public int getSize(Paint paint, CharSequence text, 
         int start, int end, 
         Paint.FontMetricsInt fm) { 
     width = (int) paint.measureText(text, start, end); 
     return width; 
    } 


    @Override 
    public void draw(Canvas canvas, CharSequence text, 
        int start, int end, float x, 
        int top, int y, int bottom, Paint paint) { 

     Paint p = new Paint(paint); 
     p.setColor(color); 
     p.setStrokeWidth(lineWidth); 

     int doubleWaveSize = waveSize * 2; 
     for (int i = (int)x; i < x + width; i += doubleWaveSize) { 
      canvas.drawLine(i, bottom, i + waveSize, bottom - waveSize, p); 
      canvas.drawLine(i + waveSize, bottom - waveSize, i + doubleWaveSize, bottom, p); 
     } 
     canvas.drawText(text.subSequence(start, end).toString(), x, y, paint); 
    } 
} 
3

Я решил эту проблему путем реализации пользовательского Span:

Добавить error_underline.png ваши ресурсы: red wavy line < - крошечные 6x3 пикселей здесь

Затем использовать этот класс для создания пролетов:

static class ErrorSpan extends DynamicDrawableSpan { 

    private BitmapDrawable mRedWavy; 
    private int mWidth; 
    private int mBmpHeight; 

    ErrorSpan(Resources resources) { 
     super(DynamicDrawableSpan.ALIGN_BASELINE); 
     mRedWavy = new BitmapDrawable(resources, BitmapFactory.decodeResource(resources, R.drawable.error_underline)); 
     mBmpHeight = mRedWavy.getIntrinsicHeight(); 
     mRedWavy.setTileModeX(TileMode.REPEAT); 
    } 

    @Override 
    public Drawable getDrawable() { 
     return mRedWavy; 
    } 

    @Override 
    public int getSize(Paint paint, CharSequence text, 
         int start, int end, 
         Paint.FontMetricsInt fm) { 
     mWidth = (int) paint.measureText(text, start, end); 
     return mWidth; 
    } 


    @Override 
    public void draw(Canvas canvas, CharSequence text, 
        int start, int end, float x, 
        int top, int y, int bottom, Paint paint) { 

     mRedWavy.setBounds(0, 0, mWidth, mBmpHeight); 
     canvas.save(); 
     canvas.translate(x, bottom-mBmpHeight); 
     mRedWavy.draw(canvas); 
     canvas.restore(); 
     canvas.drawText(text.subSequence(start, end).toString(), x, y, paint); 
    } 
} 
2

Другое решение, не касаясь ресурсов:

public class WavyUnderlineSpan implements LineBackgroundSpan { 

private int color; 
private int lineWidth; 
private int waveSize; 

public WavyUnderlineSpan() { 
    this(Color.RED, 1, 3); 
} 

public WavyUnderlineSpan(int color, int lineWidth, int waveSize) { 
    this.color = color; 
    this.lineWidth = lineWidth; 
    this.waveSize = waveSize; 
} 

@Override 
public void drawBackground(Canvas canvas, Paint paint, int left, int right, int top, int baseline, int bottom, 
          CharSequence text, int start, int end, int lnum) { 
    Paint p = new Paint(paint); 
    p.setColor(color); 
    p.setStrokeWidth(lineWidth); 

    int width = (int) paint.measureText(text, start, end); 
    int doubleWaveSize = waveSize * 2; 
    for (int i = left; i < left + width; i += doubleWaveSize) { 
     canvas.drawLine(i, bottom, i + waveSize, bottom - waveSize, p); 
     canvas.drawLine(i + waveSize, bottom - waveSize, i + doubleWaveSize, bottom, p); 
    } 
} 

}

+0

поддерживается, безусловно, лучше без дополнительного растрового изображения в ресурсах. Одна (крошечная) вещь отсутствует, использует независимые от устройства пиксели, так что волнистая линия будет выглядеть одинаково во всех разрешениях. – Iftah

+0

err, проверено сейчас - волнистая линия охватывает всю строку, а не только «натянутый» текст – Iftah

Смежные вопросы