From 112425c298ca58934582fc6829eac25a1a8cd5e0 Mon Sep 17 00:00:00 2001 From: Aleksandr Borisenko Date: Tue, 15 Aug 2017 20:14:03 +0300 Subject: [PATCH] Fixed #245: different padding between lines --- .../java/com/tokenautocomplete/ViewSpan.java | 76 +++++++++++++------ 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/library/src/main/java/com/tokenautocomplete/ViewSpan.java b/library/src/main/java/com/tokenautocomplete/ViewSpan.java index 0828b7b6..5bf0774e 100644 --- a/library/src/main/java/com/tokenautocomplete/ViewSpan.java +++ b/library/src/main/java/com/tokenautocomplete/ViewSpan.java @@ -2,7 +2,9 @@ import android.graphics.Canvas; import android.graphics.Paint; +import android.support.annotation.IntRange; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.text.style.ReplacementSpan; import android.view.View; import android.view.ViewGroup; @@ -12,56 +14,80 @@ * * Created on 2/3/15. * @author mgod + * + * Updated on 15/04/2017 + * Aleksandr Borisenko */ public class ViewSpan extends ReplacementSpan { + + private static final String TAG = ViewSpan.class.getSimpleName(); + + private static final char SENTINEL = ','; + protected View view; private int maxWidth; + private boolean prepared; - public ViewSpan(View v, int maxWidth) { + public ViewSpan(View view, int maxWidth) { super(); this.maxWidth = maxWidth; - view = v; - view.setLayoutParams(new ViewGroup.LayoutParams( + this.view = view; + this.view.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + prepared = false; } private void prepView() { - int widthSpec = View.MeasureSpec.makeMeasureSpec(maxWidth, View.MeasureSpec.AT_MOST); - int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + if (!prepared) { + int widthSpec = View.MeasureSpec.makeMeasureSpec(maxWidth, View.MeasureSpec.AT_MOST); + int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); - view.measure(widthSpec, heightSpec); - view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); + view.measure(widthSpec, heightSpec); + view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); + prepared = true; + } } - public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, - float x, int top, int y, int bottom, @NonNull Paint paint) { + public int getHeight() { prepView(); + return view.getHeight(); + } + @Override + public void draw( + @NonNull Canvas canvas, CharSequence text, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, + float x, int top, int y, int bottom, @NonNull Paint paint) { + prepView(); canvas.save(); - //Centering the token looks like a better strategy that aligning the bottom - int padding = (bottom - top - view.getBottom()) / 2; - canvas.translate(x, bottom - view.getBottom() - padding); + canvas.translate(x, top); view.draw(canvas); canvas.restore(); } - public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i2, Paint.FontMetricsInt fm) { + @Override + public int getSize( + @NonNull Paint paint, CharSequence text, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, + @Nullable Paint.FontMetricsInt fm) { prepView(); - + // NOTE: only the first tag (measure) has ~2dp "padding" + // NOTE: a string with the single tag can be trimmed up to span height when the layout is inflated + String str = text.toString(); + str = str.substring(0, str.lastIndexOf(SENTINEL) + 1); + if (start == 0 && str.length() > end) { + // WORKAROUND: first measure is ignored if there are other ones + return view.getRight(); + } if (fm != null) { - //We need to make sure the layout allots enough space for the view - int height = view.getMeasuredHeight(); - int need = height - (fm.descent - fm.ascent); - if (need > 0) { - int ascent = need / 2; - //This makes sure the text drawing area will be tall enough for the view - fm.descent += need - ascent; - fm.ascent -= ascent; - fm.bottom += need - ascent; - fm.top -= need / 2; + final int height = view.getMeasuredHeight(); + final int top_need = height - (fm.bottom - fm.top); + if (top_need != 0) { + int top_patch = top_need / 2; + fm.ascent = (fm.top -= top_patch); + fm.descent = (fm.bottom += top_need - top_patch); } } - return view.getRight(); } }