2014-07-11 15 views
8

Tôi đang cố gắng thay đổi chuỗi của mình để tạo một huy hiệu với một số ở giữa bằng cách sử dụng Chuỗi có thể chỉnh sửa. Tôi có thể làm nổi bật chữ/số thích hợp bằng cách đặt BackGroundColorSpan, nhưng cần trợ giúp làm cho nó đẹp hơn một chút. Tôi đã hy vọng sẽ làm tròn góc với một chút đệm xung quanh toàn bộ hình dạng.Android Spannablecontent Với ​​các góc tròn

Bài viết này thực sự gần gũi với những gì tôi đang cố gắng để làm: Android SpannableString set background behind part of text

tôi thực sự cần phải giữ cho nguồn tài nguyên như một TextView do cách nó tương tác với ứng dụng của tôi.

Bất kỳ ý tưởng nào về cách sử dụng ReplaceSpan cho tình huống cụ thể của tôi?

Dưới đây là đoạn mã của tôi:

  if (menuItem.getMenuItemType() == SlidingMenuItem.MenuItemType.NOTIFICATIONS) { 
       myMenuRow.setTypeface(null, Typeface.NORMAL); 
       myMenuRow.setTextColor(getContext().getResources().getColor(R.color.BLACK)); 
       myMenuRow.setActivated(false); 
       SpannableString spannablecontent = new SpannableString(myMenuRow.getText()); 
       spannablecontent.setSpan(new BackgroundColorSpan(Color.argb(150,0,0,0)), 18, myMenuRow.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 
       myMenuRow.setText(spannablecontent); 
+0

đăng một hình ảnh những gì bạn muốn làm – pskink

+0

uy tín của tôi là không đủ cao ... – ericlokness

+0

để đăng liên kết? – pskink

Trả lời

9

Sau khi đọc nhận được một chút giúp đỡ với một bộ chuyển đổi cho C#, tôi đã đưa ra với điều này. Tôi vẫn có một số tinh chỉnh để làm, nhưng nếu có ai cũng đang tìm kiếm một câu trả lời tương tự.

public class RoundedBackgroundSpan extends ReplacementSpan 
{ 

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

    @Override 
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) 
    { 
     RectF rect = new RectF(x, top, x + text.length(), bottom); 
     paint.setColor(Color.CYAN); 
     canvas.drawRoundRect(rect, 20, 20, paint); 
     paint.setColor(Color.WHITE); 
     canvas.drawText(text, start, end, x, y, paint); 
    } 
} 
9

Đây là phiên bản được cải tiến dựa trên câu trả lời @ericlokness, với nền tùy chỉnh và màu văn bản. Nó cũng hoạt động với nhiều nhịp trên cùng một TextView.

public class RoundedBackgroundSpan extends ReplacementSpan 
{ 
    private final int _padding = 20; 
    private int _backgroundColor; 
    private int _textColor; 

    public RoundedBackgroundSpan(int backgroundColor, int textColor) { 
    super(); 
    _backgroundColor = backgroundColor; 
    _textColor = textColor; 
    } 

    @Override 
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { 
    return (int) (_padding + paint.measureText(text.subSequence(start, end).toString()) + _padding); 
    } 

    @Override 
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) 
    { 
    float width = paint.measureText(text.subSequence(start, end).toString()); 
    RectF rect = new RectF(x - _padding, top, x + width + _padding, bottom); 
    paint.setColor(_backgroundColor); 
    canvas.drawRoundRect(rect, 20, 20, paint); 
    paint.setColor(_textColor); 
    canvas.drawText(text, start, end, x, y, paint); 
    } 
} 
4

Tôi tiếp tục cải thiện lớp mvandillen.

Điều này dường như làm việc rất tốt:

public class RoundedBackgroundSpan extends ReplacementSpan 
    { 
     private final int mPadding = 10; 
     private int mBackgroundColor; 
     private int mTextColor; 

     public RoundedBackgroundSpan(int backgroundColor, int textColor) { 
      super(); 
      mBackgroundColor = backgroundColor; 
      mTextColor = textColor; 
     } 

     @Override 
     public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { 
      return (int) (mPadding + paint.measureText(text.subSequence(start, end).toString()) + mPadding); 
     } 

     @Override 
     public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) 
     { 
      float width = paint.measureText(text.subSequence(start, end).toString()); 
      RectF rect = new RectF(x, top+mPadding, x + width + 2*mPadding, bottom); 
      paint.setColor(mBackgroundColor); 
      canvas.drawRoundRect(rect, mPadding, mPadding, paint); 
      paint.setColor(mTextColor); 
      canvas.drawText(text, start, end, x+mPadding, y, paint); 
     } 
    } 
13

Thật sự tôi thấy vấn đề lớn với tất cả những câu trả lời khi hiển thị nhiều dòng phù hiệu. Sau nhiều thử nghiệm và tinh chỉnh. Cuối cùng tôi đã nhận được phiên bản tốt nhất ở trên.

Ý tưởng cơ bản là đánh lừa TextView bằng cách đặt kích thước văn bản lớn hơn nhiều và đặt kích thước mong muốn trong khoảng. Ngoài ra, bạn có thể thấy tôi đang vẽ nền huy hiệu và văn bản khác nhau.

Vì vậy, đây là RoundedBackgroundSpan tôi:

public class RoundedBackgroundSpan extends ReplacementSpan { 

    private static final int CORNER_RADIUS = 12; 

    private static final float PADDING_X = GeneralUtils.convertDpToPx(12); 
    private static final float PADDING_Y = GeneralUtils.convertDpToPx(2); 

    private static final float MAGIC_NUMBER = GeneralUtils.convertDpToPx(2); 

    private int mBackgroundColor; 
    private int mTextColor; 
    private float mTextSize; 

    /** 
    * @param backgroundColor color value, not res id 
    * @param textSize  in pixels 
    */ 
    public RoundedBackgroundSpan(int backgroundColor, int textColor, float textSize) { 
     mBackgroundColor = backgroundColor; 
     mTextColor = textColor; 
     mTextSize = textSize; 
    } 

    @Override 
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { 
     paint = new Paint(paint); // make a copy for not editing the referenced paint 

     paint.setTextSize(mTextSize); 

     // Draw the rounded background 
     paint.setColor(mBackgroundColor); 
     float textHeightWrapping = GeneralUtils.convertDpToPx(4); 
     float tagBottom = top + textHeightWrapping + PADDING_Y + mTextSize + PADDING_Y + textHeightWrapping; 
     float tagRight = x + getTagWidth(text, start, end, paint); 
     RectF rect = new RectF(x, top, tagRight, tagBottom); 
     canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, paint); 

     // Draw the text 
     paint.setColor(mTextColor); 
     canvas.drawText(text, start, end, x + PADDING_X, tagBottom - PADDING_Y - textHeightWrapping - MAGIC_NUMBER, paint); 
    } 

    private int getTagWidth(CharSequence text, int start, int end, Paint paint) { 
     return Math.round(PADDING_X + paint.measureText(text.subSequence(start, end).toString()) + PADDING_X); 
    } 

    @Override 
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { 
     paint = new Paint(paint); // make a copy for not editing the referenced paint 
     paint.setTextSize(mTextSize); 
     return getTagWidth(text, start, end, paint); 
    } 
} 

Và đây là làm thế nào tôi đang sử dụng nó:

public void setTags(ArrayList<String> tags) { 
    if (tags == null) { 
     return; 
    } 

    mTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 26); // Tricking the text view for getting a bigger line height 

    SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); 

    String between = " "; 
    int tagStart = 0; 

    float textSize = 13 * getResources().getDisplayMetrics().scaledDensity; // sp to px 

    for (String tag : tags) { 
     // Append tag and space after 
     stringBuilder.append(tag); 
     stringBuilder.append(between); 

     // Set span for tag 
     RoundedBackgroundSpan tagSpan = new RoundedBackgroundSpan(bgColor, textColor, textSize); 
     stringBuilder.setSpan(tagSpan, tagStart, tagStart + tag.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 

     // Update to next tag start 
     tagStart += tag.length() + between.length(); 
    } 

    mTextView.setText(stringBuilder); 
} 


Lưu ý:

  • Bạn có thể chơi với tất cả các kích thước và hằng số để phù hợp với thứ bạn muốn YLE
  • Nếu bạn sử dụng một phông chữ bên ngoài hãy chắc chắn để thiết lập android: includeFontPadding = "false" nếu không nó có thể lộn xộn lên chiều cao của dòng

Enjoy :)

+1

Tôi đã thêm MAGIC_NUMBER vì từ một số lý do tôi không thể lấy văn bản được làm trung tâm theo chiều dọc và tôi không có đầu mối tại sao nhưng nó được vẽ 2 dp bên dưới. Điều này đã được thử nghiệm trên một số độ phân giải. – Shirane85

+0

Giải pháp này đã cho tôi một điểm khởi đầu tuyệt vời. Tôi sử dụng khoảng cách thêm dòng để có được xung quanh phải vượt qua một kích thước phông chữ. –

+0

Từ những gì tôi nhớ, khoảng cách dòng thêm làm chiều cao của hàng đầu tiên hoặc cuối cùng khác nhau nếu có nhiều hơn 2 dòng. Đó là lý do tại sao tôi đã làm theo cách này. – Shirane85

1

Ok, vậy câu hỏi là một chút lộn xộn, đây là giải pháp của tôi từ DanieleB và mvandillen.

public class RoundedBackgroundSpan extends ReplacementSpan { 

    private static final int CORNER_RADIUS = 8; 
    private static final int PADDING_X = 12; 

    private int mBackgroundColor; 
    private int mTextColor; 

    /** 
    * @param backgroundColor background color 
    * @param textColor  text color 
    */ 
    public RoundedBackgroundSpan(int backgroundColor, int textColor) { 
     mBackgroundColor = backgroundColor; 
     mTextColor = textColor; 
    } 

    @Override 
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { 
     return (int) (PADDING_X + paint.measureText(text.subSequence(start, end).toString()) + PADDING_X); 
    } 

    @Override 
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { 
     float width = paint.measureText(text.subSequence(start, end).toString()); 
     RectF rect = new RectF(x, top, x + width + 2 * PADDING_X, bottom); 
     paint.setColor(mBackgroundColor); 
     canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, paint); 
     paint.setColor(mTextColor); 
     canvas.drawText(text, start, end, x + PADDING_X, y, paint); 
    } 
} 

Mẹo: bạn có thể loại bỏ các Format và sử dụng màu sắc TextView mặc định:

@Override 
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { 
    Paint paint1 = new Paint(paint); 
    float width = paint1.measureText(text.subSequence(start, end).toString()); 
    RectF rect = new RectF(x, top, x + width + 2 * PADDING_X, bottom); 
    paint1.setColor(mBackgroundColor); 
    canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, paint1); 
    canvas.drawText(text, start, end, x + PADDING_X, y, paint); 
} 
1

Dưới đây là phiên bản của tôi dựa trên câu trả lời @mvandillen. Tôi cũng cần một số lợi nhuận ở đầu nhịp.

import android.graphics.Canvas; 
import android.graphics.Paint; 
import android.graphics.RectF; 
import android.support.annotation.NonNull; 
import android.text.style.ReplacementSpan; 

public class CoolBackgroundColorSpan extends ReplacementSpan { 

    private final int mBackgroundColor; 
    private final int mTextColor; 
    private final float mCornerRadius; 
    private final float mPaddingStart; 
    private final float mPaddingEnd; 
    private final float mMarginStart; 

    public CoolBackgroundColorSpan(int backgroundColor, int textColor, float cornerRadius, float paddingStart, float paddingEnd, float marginStart) { 
     super(); 
     mBackgroundColor = backgroundColor; 
     mTextColor = textColor; 
     mCornerRadius = cornerRadius; 
     mPaddingStart = paddingStart; 
     mPaddingEnd = paddingEnd; 
     mMarginStart = marginStart; 
    } 

    @Override 
    public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { 
     return (int) (mPaddingStart + paint.measureText(text.subSequence(start, end).toString()) + mPaddingEnd); 
    } 

    @Override 
    public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) { 
     float width = paint.measureText(text.subSequence(start, end).toString()); 
     RectF rect = new RectF(x - mPaddingStart + mMarginStart, top, x + width + mPaddingEnd + mMarginStart, bottom); 
     paint.setColor(mBackgroundColor); 
     canvas.drawRoundRect(rect, mCornerRadius, mCornerRadius, paint); 
     paint.setColor(mTextColor); 
     canvas.drawText(text, start, end, x + mMarginStart, y, paint); 
    } 
} 

Làm thế nào để sử dụng:

int flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE; 
SpannableString staffTitleSpan = new SpannableString("staff: "); 
SpannableString staffNameSpan = new SpannableString("John Smith"); 
staffNameSpan.setSpan(new StyleSpan(Typeface.BOLD), 0, staffNameSpan.length(), flag); 
staffNameSpan.setSpan(new CoolBackgroundColorSpan(mStaffNameSpanBgColor, mStaffNameSpanTextColor, mStaffNameSpanBgRadius, mStaffNameSpanBgPaddingStart, mStaffNameSpanBgPaddingEnd, mStaffNameSpanMarginStart), 0, staffNameSpan.length(), flag); 
SpannableStringBuilder builder = new SpannableStringBuilder(); 
builder.append(staffTitleSpan); 
builder.append(staffNameSpan); 

staffTextView.setText(builder); 

Preview:

enter image description here

Các vấn đề liên quan