Merge "Create new API for ImageSpan"
This commit is contained in:
@@ -47136,7 +47136,9 @@ package android.text.style {
|
||||
public abstract class ReplacementSpan extends android.text.style.MetricAffectingSpan {
|
||||
ctor public ReplacementSpan();
|
||||
method public abstract void draw(@NonNull android.graphics.Canvas, CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, float, int, int, int, @NonNull android.graphics.Paint);
|
||||
method @Nullable public CharSequence getContentDescription();
|
||||
method public abstract int getSize(@NonNull android.graphics.Paint, CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.graphics.Paint.FontMetricsInt);
|
||||
method public void setContentDescription(@Nullable CharSequence);
|
||||
method public void updateDrawState(android.text.TextPaint);
|
||||
method public void updateMeasureState(android.text.TextPaint);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.os.Parcelable;
|
||||
import android.sysprop.DisplayProperties;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.text.style.AccessibilityClickableSpan;
|
||||
import android.text.style.AccessibilityReplacementSpan;
|
||||
import android.text.style.AccessibilityURLSpan;
|
||||
import android.text.style.AlignmentSpan;
|
||||
import android.text.style.BackgroundColorSpan;
|
||||
@@ -735,6 +736,8 @@ public class TextUtils {
|
||||
/** @hide */
|
||||
public static final int LINE_HEIGHT_SPAN = 28;
|
||||
/** @hide */
|
||||
public static final int ACCESSIBILITY_REPLACEMENT_SPAN = 29;
|
||||
/** @hide */
|
||||
public static final int LAST_SPAN = LINE_HEIGHT_SPAN;
|
||||
|
||||
/**
|
||||
@@ -860,7 +863,7 @@ public class TextUtils {
|
||||
|
||||
case LEADING_MARGIN_SPAN:
|
||||
readSpan(p, sp, new LeadingMarginSpan.Standard(p));
|
||||
break;
|
||||
break;
|
||||
|
||||
case URL_SPAN:
|
||||
readSpan(p, sp, new URLSpan(p));
|
||||
@@ -933,7 +936,11 @@ public class TextUtils {
|
||||
case LINE_HEIGHT_SPAN:
|
||||
readSpan(p, sp, new LineHeightSpan.Standard(p));
|
||||
break;
|
||||
|
||||
|
||||
case ACCESSIBILITY_REPLACEMENT_SPAN:
|
||||
readSpan(p, sp, new AccessibilityReplacementSpan(p));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("bogus span encoding " + kind);
|
||||
}
|
||||
|
||||
100
core/java/android/text/style/AccessibilityReplacementSpan.java
Normal file
100
core/java/android/text/style/AccessibilityReplacementSpan.java
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.text.style;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.ParcelableSpan;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* This class serves as a parcelable placeholder for the ReplacementSpans.
|
||||
*
|
||||
* This span contains content description of original span to let Accessibility service to do the
|
||||
* substitution for it.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class AccessibilityReplacementSpan extends ReplacementSpan
|
||||
implements ParcelableSpan {
|
||||
// The content description of the span this one replaces
|
||||
private CharSequence mContentDescription;
|
||||
|
||||
/**
|
||||
* @param contentDescription The content description of the span this one replaces
|
||||
*/
|
||||
public AccessibilityReplacementSpan(CharSequence contentDescription) {
|
||||
this.setContentDescription(contentDescription);
|
||||
mContentDescription = contentDescription;
|
||||
}
|
||||
|
||||
public AccessibilityReplacementSpan(Parcel p) {
|
||||
mContentDescription = p.readCharSequence();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpanTypeId() {
|
||||
return getSpanTypeIdInternal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpanTypeIdInternal() {
|
||||
return TextUtils.ACCESSIBILITY_REPLACEMENT_SPAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
writeToParcelInternal(dest, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcelInternal(Parcel dest, int flags) {
|
||||
dest.writeCharSequence(mContentDescription);
|
||||
}
|
||||
|
||||
@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) {
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull
|
||||
Parcelable.Creator<AccessibilityReplacementSpan> CREATOR =
|
||||
new Parcelable.Creator<AccessibilityReplacementSpan>() {
|
||||
@Override
|
||||
public AccessibilityReplacementSpan createFromParcel(Parcel parcel) {
|
||||
return new AccessibilityReplacementSpan(parcel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibilityReplacementSpan[] newArray(int size) {
|
||||
return new AccessibilityReplacementSpan[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -25,6 +25,8 @@ import android.text.TextPaint;
|
||||
|
||||
public abstract class ReplacementSpan extends MetricAffectingSpan {
|
||||
|
||||
private CharSequence mContentDescription = null;
|
||||
|
||||
/**
|
||||
* Returns the width of the span. Extending classes can set the height of the span by updating
|
||||
* attributes of {@link android.graphics.Paint.FontMetricsInt}. If the span covers the whole
|
||||
@@ -60,6 +62,27 @@ public abstract class ReplacementSpan extends MetricAffectingSpan {
|
||||
@IntRange(from = 0) int start, @IntRange(from = 0) int end, float x,
|
||||
int top, int y, int bottom, @NonNull Paint paint);
|
||||
|
||||
/**
|
||||
* Gets a brief description of this ImageSpan for use in accessibility support.
|
||||
*
|
||||
* @return The content description.
|
||||
*/
|
||||
@Nullable
|
||||
public CharSequence getContentDescription() {
|
||||
return mContentDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specific content description into ImageSpan.
|
||||
* ReplacementSpans are shared with accessibility services,
|
||||
* but only the content description is available from them.
|
||||
*
|
||||
* @param contentDescription content description. The default value is null.
|
||||
*/
|
||||
public void setContentDescription(@Nullable CharSequence contentDescription) {
|
||||
mContentDescription = contentDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does nothing, since ReplacementSpans are measured
|
||||
* explicitly instead of affecting Paint properties.
|
||||
|
||||
@@ -39,8 +39,10 @@ import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.AccessibilityClickableSpan;
|
||||
import android.text.style.AccessibilityReplacementSpan;
|
||||
import android.text.style.AccessibilityURLSpan;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.ReplacementSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
@@ -2641,36 +2643,85 @@ public class AccessibilityNodeInfo implements Parcelable {
|
||||
public void setText(CharSequence text) {
|
||||
enforceNotSealed();
|
||||
mOriginalText = text;
|
||||
// Replace any ClickableSpans in mText with placeholders
|
||||
if (text instanceof Spanned) {
|
||||
ClickableSpan[] spans =
|
||||
((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
|
||||
if (spans.length > 0) {
|
||||
Spannable spannable = new SpannableStringBuilder(text);
|
||||
for (int i = 0; i < spans.length; i++) {
|
||||
ClickableSpan span = spans[i];
|
||||
if ((span instanceof AccessibilityClickableSpan)
|
||||
|| (span instanceof AccessibilityURLSpan)) {
|
||||
// We've already done enough
|
||||
break;
|
||||
}
|
||||
int spanToReplaceStart = spannable.getSpanStart(span);
|
||||
int spanToReplaceEnd = spannable.getSpanEnd(span);
|
||||
int spanToReplaceFlags = spannable.getSpanFlags(span);
|
||||
spannable.removeSpan(span);
|
||||
ClickableSpan replacementSpan = (span instanceof URLSpan)
|
||||
? new AccessibilityURLSpan((URLSpan) span)
|
||||
: new AccessibilityClickableSpan(span.getId());
|
||||
spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
|
||||
spanToReplaceFlags);
|
||||
}
|
||||
mText = spannable;
|
||||
return;
|
||||
}
|
||||
CharSequence tmpText = text;
|
||||
tmpText = replaceClickableSpan(tmpText);
|
||||
tmpText = replaceReplacementSpan(tmpText);
|
||||
mText = tmpText;
|
||||
return;
|
||||
}
|
||||
mText = (text == null) ? null : text.subSequence(0, text.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces any ClickableSpans in mText with placeholders.
|
||||
*
|
||||
* @param text The text.
|
||||
*
|
||||
* @return The spannable with ClickableSpan replacement.
|
||||
*/
|
||||
private CharSequence replaceClickableSpan(CharSequence text) {
|
||||
ClickableSpan[] clickableSpans =
|
||||
((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
|
||||
Spannable spannable = new SpannableStringBuilder(text);
|
||||
if (clickableSpans.length == 0) {
|
||||
return text;
|
||||
}
|
||||
for (int i = 0; i < clickableSpans.length; i++) {
|
||||
ClickableSpan span = clickableSpans[i];
|
||||
if ((span instanceof AccessibilityClickableSpan)
|
||||
|| (span instanceof AccessibilityURLSpan)) {
|
||||
// We've already done enough
|
||||
break;
|
||||
}
|
||||
int spanToReplaceStart = spannable.getSpanStart(span);
|
||||
int spanToReplaceEnd = spannable.getSpanEnd(span);
|
||||
int spanToReplaceFlags = spannable.getSpanFlags(span);
|
||||
spannable.removeSpan(span);
|
||||
ClickableSpan replacementSpan = (span instanceof URLSpan)
|
||||
? new AccessibilityURLSpan((URLSpan) span)
|
||||
: new AccessibilityClickableSpan(span.getId());
|
||||
spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
|
||||
spanToReplaceFlags);
|
||||
}
|
||||
return spannable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any ImageSpans in mText with its content description.
|
||||
*
|
||||
* @param text The text.
|
||||
*
|
||||
* @return The spannable with ReplacementSpan replacement.
|
||||
*/
|
||||
private CharSequence replaceReplacementSpan(CharSequence text) {
|
||||
ReplacementSpan[] replacementSpans =
|
||||
((Spanned) text).getSpans(0, text.length(), ReplacementSpan.class);
|
||||
SpannableStringBuilder spannable = new SpannableStringBuilder(text);
|
||||
if (replacementSpans.length == 0) {
|
||||
return text;
|
||||
}
|
||||
for (int i = 0; i < replacementSpans.length; i++) {
|
||||
ReplacementSpan span = replacementSpans[i];
|
||||
CharSequence replacementText = span.getContentDescription();
|
||||
if (span instanceof AccessibilityReplacementSpan) {
|
||||
// We've already done enough
|
||||
break;
|
||||
}
|
||||
if (replacementText == null) {
|
||||
continue;
|
||||
}
|
||||
int spanToReplaceStart = spannable.getSpanStart(span);
|
||||
int spanToReplaceEnd = spannable.getSpanEnd(span);
|
||||
int spanToReplaceFlags = spannable.getSpanFlags(span);
|
||||
spannable.removeSpan(span);
|
||||
ReplacementSpan replacementSpan = new AccessibilityReplacementSpan(replacementText);
|
||||
spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
|
||||
spanToReplaceFlags);
|
||||
}
|
||||
return spannable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hint text of this node. Only applies to nodes where text can be entered.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user