1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.exoplayer2.text.span; 17 18 import android.text.Spannable; 19 import android.text.style.ForegroundColorSpan; 20 21 /** 22 * Utility methods for Android <a href="https://developer.android.com/guide/topics/text/spans">span 23 * styling</a>. 24 */ 25 public final class SpanUtil { 26 27 /** 28 * Adds {@code span} to {@code spannable} between {@code start} and {@code end}, removing any 29 * existing spans of the same type and with the same indices and flags. 30 * 31 * <p>This is useful for types of spans that don't make sense to duplicate and where the 32 * evaluation order might have an unexpected impact on the final text, e.g. {@link 33 * ForegroundColorSpan}. 34 * 35 * @param spannable The {@link Spannable} to add {@code span} to. 36 * @param span The span object to be added. 37 * @param start The start index to add the new span at. 38 * @param end The end index to add the new span at. 39 * @param spanFlags The flags to pass to {@link Spannable#setSpan(Object, int, int, int)}. 40 */ addOrReplaceSpan( Spannable spannable, Object span, int start, int end, int spanFlags)41 public static void addOrReplaceSpan( 42 Spannable spannable, Object span, int start, int end, int spanFlags) { 43 Object[] existingSpans = spannable.getSpans(start, end, span.getClass()); 44 for (Object existingSpan : existingSpans) { 45 if (spannable.getSpanStart(existingSpan) == start 46 && spannable.getSpanEnd(existingSpan) == end 47 && spannable.getSpanFlags(existingSpan) == spanFlags) { 48 spannable.removeSpan(existingSpan); 49 } 50 } 51 spannable.setSpan(span, start, end, spanFlags); 52 } 53 SpanUtil()54 private SpanUtil() {} 55 } 56