Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6d36821 authored by Luca Zanolin's avatar Luca Zanolin
Browse files

Add EditTextShortcutSpan to provide edit short cut in the text view.

At the moment, EditTextShortcutSpan allows only the deletion of the text. In the future, we may decide to add extra functionality,
like "retry" where all the text is removed and a specific IME is triggered.

Fix the underline. The underline is not defined in thickness, and not as a multiplier of the default underline thickness.

Change the behaviour of SuggestionRangeSpan to match the specification.

Change-Id: I80437d9887c7a2ff8f62c38afbb0cb7add7ee9c8
parent c5d0fac0
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -20677,6 +20677,14 @@ package android.text.style {
    field protected final int mVerticalAlignment;
  }
  public class EasyEditSpan implements android.text.ParcelableSpan {
    ctor public EasyEditSpan();
    ctor public EasyEditSpan(android.os.Parcel);
    method public int describeContents();
    method public int getSpanTypeId();
    method public void writeToParcel(android.os.Parcel, int);
  }
  public class ForegroundColorSpan extends android.text.style.CharacterStyle implements android.text.ParcelableSpan android.text.style.UpdateAppearance {
    ctor public ForegroundColorSpan(int);
    ctor public ForegroundColorSpan(android.os.Parcel);
+12 −7
Original line number Diff line number Diff line
@@ -723,7 +723,7 @@ class TextLine {
        float ret = 0;

        int contextLen = contextEnd - contextStart;
        if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineColor !=0 || runIsRtl))) {
        if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineCount != 0 || runIsRtl))) {
            int flags = runIsRtl ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR;
            if (mCharsValid) {
                ret = wp.getTextRunAdvances(mChars, start, runLen,
@@ -753,21 +753,26 @@ class TextLine {
                wp.setColor(previousColor);
            }

            if (wp.underlineColor != 0) {
            if (wp.underlineCount != 0) {
                // kStdUnderline_Offset = 1/9, defined in SkTextFormatParams.h
                float middle = y + wp.baselineShift + (1.0f / 9.0f) * wp.getTextSize();
                // kStdUnderline_Thickness = 1/18, defined in SkTextFormatParams.h
                float halfHeight = wp.underlineThickness * (1.0f / 18.0f / 2.0f) * wp.getTextSize();
                float underlineTop = y + wp.baselineShift + (1.0f / 9.0f) * wp.getTextSize();

                int previousColor = wp.getColor();
                Paint.Style previousStyle = wp.getStyle();
                boolean previousAntiAlias = wp.isAntiAlias();

                wp.setColor(wp.underlineColor);
                wp.setStyle(Paint.Style.FILL);
                c.drawRect(x, middle - halfHeight, x + ret, middle + halfHeight, wp);
                wp.setAntiAlias(true);

                for (int i = 0; i < wp.underlineCount; i++) {
                    wp.setColor(wp.underlineColors[i]);
                    c.drawRect(x, underlineTop, x + ret, underlineTop + wp.underlineThicknesses[i],
                            wp);
                }

                wp.setStyle(previousStyle);
                wp.setColor(previousColor);
                wp.setAntiAlias(previousAntiAlias);
            }

            drawTextRun(c, wp, start, end, contextStart, contextEnd, runIsRtl,
+39 −12
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@ import android.graphics.Paint;
 * data used during text measuring and drawing.
 */
public class TextPaint extends Paint {

    private static final int DEFAULT_UNDERLINE_SIZE = 3;

    // Special value 0 means no background paint
    public int bgColor;
    public int baselineShift;
@@ -33,12 +36,17 @@ public class TextPaint extends Paint {
     * Special value 0 means no custom underline
     * @hide
     */
    public int underlineColor;
    public int[] underlineColors;
    /**
     * Defined as a multiplier of the default underline thickness. Use 1.0f for default thickness.
     * @hide
     */
    public float underlineThickness;
    public float[] underlineThicknesses;
    /**
     * The number of underlines currently stored in the array. If 0, no underline is drawn.
     * @hide
     */
    public int underlineCount;

    public TextPaint() {
        super();
@@ -64,24 +72,43 @@ public class TextPaint extends Paint {
        linkColor = tp.linkColor;
        drawableState = tp.drawableState;
        density = tp.density;
        underlineColor = tp.underlineColor;
        underlineThickness = tp.underlineThickness;
        underlineColors = tp.underlineColors;
        underlineThicknesses = tp.underlineThicknesses;
        underlineCount = tp.underlineCount;
    }

    /**
     * Defines a custom underline for this Paint.
     * @param color underline solid color
     * @param thickness underline thickness, defined as a multiplier of the default underline
     * thickness.
     * @param thickness underline thickness
     * @hide
     */
    public void setUnderlineText(boolean isUnderlined, int color, float thickness) {
        setUnderlineText(false);
        if (isUnderlined) {
            underlineColor = color;
            underlineThickness = thickness;
    public void setUnderlineText(int color, float thickness) {
        if (color == 0) {
            // No underline
            return;
        }

        if (underlineCount == 0) {
            underlineColors = new int[DEFAULT_UNDERLINE_SIZE];
            underlineThicknesses = new float[DEFAULT_UNDERLINE_SIZE];
            underlineColors[underlineCount] = color;
            underlineThicknesses[underlineCount] = thickness;
            underlineCount++;
        } else {
            underlineColor = 0;
            if (underlineCount == underlineColors.length) {
                int[] newColors = new int[underlineColors.length + DEFAULT_UNDERLINE_SIZE];
                float[] newThickness = new float[underlineThicknesses.length
                        + DEFAULT_UNDERLINE_SIZE];
                System.arraycopy(underlineColors, 0, newColors, 0, underlineColors.length);
                System.arraycopy(
                        underlineThicknesses, 0, newThickness, 0, underlineThicknesses.length);
                underlineColors = newColors;
                underlineThicknesses = newThickness;
            }
            underlineColors[underlineCount] = color;
            underlineThicknesses[underlineCount] = thickness;
            underlineCount++;
        }
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.text.style.BackgroundColorSpan;
import android.text.style.BulletSpan;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.EasyEditSpan;
import android.text.style.LeadingMarginSpan;
import android.text.style.MetricAffectingSpan;
import android.text.style.QuoteSpan;
@@ -585,6 +586,8 @@ public class TextUtils {
    public static final int SPELL_CHECK_SPAN = 20;
    /** @hide */
    public static final int SUGGESTION_RANGE_SPAN = 21;
    /** @hide */
    public static final int EASY_EDIT_SPAN = 22;

    /**
     * Flatten a CharSequence and whatever styles can be copied across processes
@@ -748,6 +751,10 @@ public class TextUtils {
                    readSpan(p, sp, new SuggestionRangeSpan());
                    break;
                    
                case EASY_EDIT_SPAN:
                    readSpan(p, sp, new EasyEditSpan(p));
                    break;

                default:
                    throw new RuntimeException("bogus span encoding " + kind);
                }
+54 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextUtils;
import android.widget.TextView;

/**
 * Provides an easy way to edit a portion of text.
 * <p>
 * The {@link TextView} uses this span to allow the user to delete a chuck of text in one click.
 * the text. {@link TextView} removes this span as soon as the text is edited, or the cursor moves.
 */
public class EasyEditSpan implements ParcelableSpan {

    public EasyEditSpan() {
        // Empty
    }

    public EasyEditSpan(Parcel src) {
        this();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // Empty
    }

    @Override
    public int getSpanTypeId() {
        return TextUtils.EASY_EDIT_SPAN;
    }
}
Loading