RichTextView.java revision d832154e333a3a45b5faecd518b664ddd297183c
1/* 2 * Copyright (C) 2016 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 17package com.android.setupwizardlib.view; 18 19import android.content.Context; 20import android.support.v4.view.ViewCompat; 21import android.text.Annotation; 22import android.text.SpannableString; 23import android.text.Spanned; 24import android.text.method.LinkMovementMethod; 25import android.text.style.TextAppearanceSpan; 26import android.util.AttributeSet; 27import android.util.Log; 28import android.view.MotionEvent; 29import android.widget.TextView; 30 31import com.android.setupwizardlib.span.LinkSpan; 32import com.android.setupwizardlib.span.SpanHelper; 33import com.android.setupwizardlib.util.LinkAccessibilityHelper; 34 35/** 36 * An extension of TextView that automatically replaces the annotation tags as specified in 37 * {@link SpanHelper#replaceSpan(android.text.Spannable, Object, Object)} 38 */ 39public class RichTextView extends TextView { 40 41 /* static section */ 42 43 private static final String TAG = "RichTextView"; 44 45 private static final String ANNOTATION_LINK = "link"; 46 private static final String ANNOTATION_TEXT_APPEARANCE = "textAppearance"; 47 48 /** 49 * Replace <annotation> tags in strings to become their respective types. Currently 2 50 * types are supported: 51 * <ol> 52 * <li><annotation link="foobar"> will create a 53 * {@link com.android.setupwizardlib.span.LinkSpan} that broadcasts with the key 54 * "foobar"</li> 55 * <li><annotation textAppearance="TextAppearance.FooBar"> will create a 56 * {@link android.text.style.TextAppearanceSpan} with @style/TextAppearance.FooBar</li> 57 * </ol> 58 */ 59 public static CharSequence getRichText(Context context, CharSequence text) { 60 if (text instanceof Spanned) { 61 final SpannableString spannable = new SpannableString(text); 62 final Annotation[] spans = spannable.getSpans(0, spannable.length(), Annotation.class); 63 for (Annotation span : spans) { 64 final String key = span.getKey(); 65 if (ANNOTATION_TEXT_APPEARANCE.equals(key)) { 66 String textAppearance = span.getValue(); 67 final int style = context.getResources() 68 .getIdentifier(textAppearance, "style", context.getPackageName()); 69 if (style == 0) { 70 Log.w(TAG, "Cannot find resource: " + style); 71 } 72 final TextAppearanceSpan textAppearanceSpan = 73 new TextAppearanceSpan(context, style); 74 SpanHelper.replaceSpan(spannable, span, textAppearanceSpan); 75 } else if (ANNOTATION_LINK.equals(key)) { 76 LinkSpan link = new LinkSpan(span.getValue()); 77 SpanHelper.replaceSpan(spannable, span, link); 78 } 79 } 80 return spannable; 81 } 82 return text; 83 } 84 85 /* non-static section */ 86 87 private LinkAccessibilityHelper mAccessibilityHelper; 88 89 public RichTextView(Context context) { 90 super(context); 91 init(); 92 } 93 94 public RichTextView(Context context, AttributeSet attrs) { 95 super(context, attrs); 96 init(); 97 } 98 99 private void init() { 100 mAccessibilityHelper = new LinkAccessibilityHelper(this); 101 ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper); 102 setMovementMethod(LinkMovementMethod.getInstance()); 103 } 104 105 @Override 106 public void setText(CharSequence text, BufferType type) { 107 text = getRichText(getContext(), text); 108 super.setText(text, type); 109 } 110 111 @Override 112 protected boolean dispatchHoverEvent(MotionEvent event) { 113 if (mAccessibilityHelper != null && mAccessibilityHelper.dispatchHoverEvent(event)) { 114 return true; 115 } 116 return super.dispatchHoverEvent(event); 117 } 118} 119