Loading api/current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -377,9 +377,11 @@ package android { field public static final int drawSelectorOnTop = 16843004; // 0x10100fc field public static final int drawable = 16843161; // 0x1010199 field public static final int drawableBottom = 16843118; // 0x101016e field public static final int drawableEnd = 16843687; // 0x10103a7 field public static final int drawableLeft = 16843119; // 0x101016f field public static final int drawablePadding = 16843121; // 0x1010171 field public static final int drawableRight = 16843120; // 0x1010170 field public static final int drawableStart = 16843686; // 0x10103a6 field public static final int drawableTop = 16843117; // 0x101016d field public static final int drawingCacheQuality = 16842984; // 0x10100e8 field public static final int dropDownAnchor = 16843363; // 0x1010263 Loading Loading @@ -26421,7 +26423,9 @@ package android.widget { method protected void onTextChanged(java.lang.CharSequence, int, int, int); method public boolean onTextContextMenuItem(int); method public void removeTextChangedListener(android.text.TextWatcher); method protected void resetResolvedDrawables(); method protected void resetResolvedLayoutDirection(); method protected void resolveDrawables(); method public void setAllCaps(boolean); method public final void setAutoLinkMask(int); method public void setCompoundDrawablePadding(int); core/java/android/widget/TextView.java +399 −7 Original line number Diff line number Diff line Loading @@ -260,9 +260,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener class Drawables { final Rect mCompoundRect = new Rect(); Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight; int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight; int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight; Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight, mDrawableStart, mDrawableEnd; int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight, mDrawableSizeStart, mDrawableSizeEnd; int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight, mDrawableHeightStart, mDrawableHeightEnd; int mDrawablePadding; } private Drawables mDrawables; Loading Loading @@ -352,6 +355,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener INHERIT, GRAVITY, TEXT_START, TEXT_END, CENTER, VIEW_START, VIEW_END; } private boolean bResolvedDrawables = false; /* * Kick-start the font cache for the zygote process (to pay the cost of * initializing freetype for our default font only once). Loading Loading @@ -494,7 +499,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int buffertype = 0; boolean selectallonfocus = false; Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null; drawableBottom = null, drawableStart = null, drawableEnd = null; int drawablePadding = 0; int ellipsize = -1; boolean singleLine = false; Loading Loading @@ -571,6 +576,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener drawableBottom = a.getDrawable(attr); break; case com.android.internal.R.styleable.TextView_drawableStart: drawableStart = a.getDrawable(attr); break; case com.android.internal.R.styleable.TextView_drawableEnd: drawableEnd = a.getDrawable(attr); break; case com.android.internal.R.styleable.TextView_drawablePadding: drawablePadding = a.getDimensionPixelSize(attr, drawablePadding); break; Loading Loading @@ -980,6 +993,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setCompoundDrawablesWithIntrinsicBounds( drawableLeft, drawableTop, drawableRight, drawableBottom); setRelativeDrawablesIfNeeded(drawableStart, drawableEnd); setCompoundDrawablePadding(drawablePadding); // Same as setSingleLine(), but make sure the transformation method and the maximum number Loading Loading @@ -1105,6 +1119,42 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setTypeface(tf, styleIndex); } private void setRelativeDrawablesIfNeeded(Drawable start, Drawable end) { boolean hasRelativeDrawables = (start != null) || (end != null); if (hasRelativeDrawables) { Drawables dr = mDrawables; if (dr == null) { mDrawables = dr = new Drawables(); } final Rect compoundRect = dr.mCompoundRect; int[] state = getDrawableState(); if (start != null) { start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight()); start.setState(state); start.copyBounds(compoundRect); start.setCallback(this); dr.mDrawableStart = start; dr.mDrawableSizeStart = compoundRect.width(); dr.mDrawableHeightStart = compoundRect.height(); } else { dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0; } if (end != null) { end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight()); end.setState(state); end.copyBounds(compoundRect); end.setCallback(this); dr.mDrawableEnd = end; dr.mDrawableSizeEnd = compoundRect.width(); dr.mDrawableHeightEnd = compoundRect.height(); } else { dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0; } } } @Override public void setEnabled(boolean enabled) { if (enabled == isEnabled()) { Loading Loading @@ -1410,6 +1460,40 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } /** * Returns the start padding of the view, plus space for the start * Drawable if any. * * @hide */ public int getCompoundPaddingStart() { resolveDrawables(); switch(getResolvedLayoutDirection()) { default: case LAYOUT_DIRECTION_LTR: return getCompoundPaddingLeft(); case LAYOUT_DIRECTION_RTL: return getCompoundPaddingRight(); } } /** * Returns the end padding of the view, plus space for the end * Drawable if any. * * @hide */ public int getCompoundPaddingEnd() { resolveDrawables(); switch(getResolvedLayoutDirection()) { default: case LAYOUT_DIRECTION_LTR: return getCompoundPaddingRight(); case LAYOUT_DIRECTION_RTL: return getCompoundPaddingLeft(); } } /** * Returns the extended top padding of the view, including both the * top Drawable if any and any extra space to keep more than maxLines Loading Loading @@ -1492,6 +1576,26 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return getCompoundPaddingRight(); } /** * Returns the total start padding of the view, including the start * Drawable if any. * * @hide */ public int getTotalPaddingStart() { return getCompoundPaddingStart(); } /** * Returns the total end padding of the view, including the end * Drawable if any. * * @hide */ public int getTotalPaddingEnd() { return getCompoundPaddingEnd(); } /** * Returns the total top padding of the view, including the top * Drawable if any, the extra space to keep more than maxLines Loading Loading @@ -1678,6 +1782,185 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setCompoundDrawables(left, top, right, bottom); } /** * Sets the Drawables (if any) to appear to the start of, above, * to the end of, and below the text. Use null if you do not * want a Drawable there. The Drawables must already have had * {@link Drawable#setBounds} called. * * @attr ref android.R.styleable#TextView_drawableStart * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableEnd * @attr ref android.R.styleable#TextView_drawableBottom * * @hide */ public void setCompoundDrawablesRelative(Drawable start, Drawable top, Drawable end, Drawable bottom) { Drawables dr = mDrawables; final boolean drawables = start != null || top != null || end != null || bottom != null; if (!drawables) { // Clearing drawables... can we free the data structure? if (dr != null) { if (dr.mDrawablePadding == 0) { mDrawables = null; } else { // We need to retain the last set padding, so just clear // out all of the fields in the existing structure. if (dr.mDrawableStart != null) dr.mDrawableStart.setCallback(null); dr.mDrawableStart = null; if (dr.mDrawableTop != null) dr.mDrawableTop.setCallback(null); dr.mDrawableTop = null; if (dr.mDrawableEnd != null) dr.mDrawableEnd.setCallback(null); dr.mDrawableEnd = null; if (dr.mDrawableBottom != null) dr.mDrawableBottom.setCallback(null); dr.mDrawableBottom = null; dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0; dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0; dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0; dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0; } } } else { if (dr == null) { mDrawables = dr = new Drawables(); } if (dr.mDrawableStart != start && dr.mDrawableStart != null) { dr.mDrawableStart.setCallback(null); } dr.mDrawableStart = start; if (dr.mDrawableTop != top && dr.mDrawableTop != null) { dr.mDrawableTop.setCallback(null); } dr.mDrawableTop = top; if (dr.mDrawableEnd != end && dr.mDrawableEnd != null) { dr.mDrawableEnd.setCallback(null); } dr.mDrawableEnd = end; if (dr.mDrawableBottom != bottom && dr.mDrawableBottom != null) { dr.mDrawableBottom.setCallback(null); } dr.mDrawableBottom = bottom; final Rect compoundRect = dr.mCompoundRect; int[] state; state = getDrawableState(); if (start != null) { start.setState(state); start.copyBounds(compoundRect); start.setCallback(this); dr.mDrawableSizeStart = compoundRect.width(); dr.mDrawableHeightStart = compoundRect.height(); } else { dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0; } if (end != null) { end.setState(state); end.copyBounds(compoundRect); end.setCallback(this); dr.mDrawableSizeEnd = compoundRect.width(); dr.mDrawableHeightEnd = compoundRect.height(); } else { dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0; } if (top != null) { top.setState(state); top.copyBounds(compoundRect); top.setCallback(this); dr.mDrawableSizeTop = compoundRect.height(); dr.mDrawableWidthTop = compoundRect.width(); } else { dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0; } if (bottom != null) { bottom.setState(state); bottom.copyBounds(compoundRect); bottom.setCallback(this); dr.mDrawableSizeBottom = compoundRect.height(); dr.mDrawableWidthBottom = compoundRect.width(); } else { dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0; } } resolveDrawables(); invalidate(); requestLayout(); } /** * Sets the Drawables (if any) to appear to the start of, above, * to the end of, and below the text. Use 0 if you do not * want a Drawable there. The Drawables' bounds will be set to * their intrinsic bounds. * * @param start Resource identifier of the start Drawable. * @param top Resource identifier of the top Drawable. * @param end Resource identifier of the end Drawable. * @param bottom Resource identifier of the bottom Drawable. * * @attr ref android.R.styleable#TextView_drawableStart * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableEnd * @attr ref android.R.styleable#TextView_drawableBottom * * @hide */ public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end, int bottom) { resetResolvedDrawables(); final Resources resources = getContext().getResources(); setCompoundDrawablesRelativeWithIntrinsicBounds( start != 0 ? resources.getDrawable(start) : null, top != 0 ? resources.getDrawable(top) : null, end != 0 ? resources.getDrawable(end) : null, bottom != 0 ? resources.getDrawable(bottom) : null); } /** * Sets the Drawables (if any) to appear to the start of, above, * to the end of, and below the text. Use null if you do not * want a Drawable there. The Drawables' bounds will be set to * their intrinsic bounds. * * @attr ref android.R.styleable#TextView_drawableStart * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableEnd * @attr ref android.R.styleable#TextView_drawableBottom * * @hide */ public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top, Drawable end, Drawable bottom) { resetResolvedDrawables(); if (start != null) { start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight()); } if (end != null) { end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight()); } if (top != null) { top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight()); } if (bottom != null) { bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight()); } setCompoundDrawablesRelative(start, top, end, bottom); } /** * Returns drawables for the left, top, right, and bottom borders. */ Loading @@ -1692,6 +1975,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } /** * Returns drawables for the start, top, end, and bottom borders. * * @hide */ public Drawable[] getCompoundDrawablesRelative() { final Drawables dr = mDrawables; if (dr != null) { return new Drawable[] { dr.mDrawableStart, dr.mDrawableTop, dr.mDrawableEnd, dr.mDrawableBottom }; } else { return new Drawable[] { null, null, null, null }; } } /** * Sets the size of the padding between the compound drawables and * the text. Loading Loading @@ -2495,6 +2794,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (dr.mDrawableRight != null && dr.mDrawableRight.isStateful()) { dr.mDrawableRight.setState(state); } if (dr.mDrawableStart != null && dr.mDrawableStart.isStateful()) { dr.mDrawableStart.setState(state); } if (dr.mDrawableEnd != null && dr.mDrawableEnd.isStateful()) { dr.mDrawableEnd.setState(state); } } } Loading Loading @@ -3546,7 +3851,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mErrorWasChanged = true; final Drawables dr = mDrawables; if (dr != null) { setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon, dr.mDrawableBottom); switch (getResolvedLayoutDirection()) { default: case LAYOUT_DIRECTION_LTR: setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon, dr.mDrawableBottom); break; case LAYOUT_DIRECTION_RTL: setCompoundDrawables(icon, dr.mDrawableTop, dr.mDrawableRight, dr.mDrawableBottom); break; } } else { setCompoundDrawables(null, null, icon, null); } Loading Loading @@ -4048,6 +4363,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mSelectionModifierCursorController != null) { observer.addOnTouchModeChangeListener(mSelectionModifierCursorController); } // Resolve drawables as the layout direction has been resolved resolveDrawables(); } @Override Loading Loading @@ -4077,6 +4395,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } hideControllers(); resetResolvedDrawables(); } @Override Loading Loading @@ -4111,7 +4431,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final boolean verified = super.verifyDrawable(who); if (!verified && mDrawables != null) { return who == mDrawables.mDrawableLeft || who == mDrawables.mDrawableTop || who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom; who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom || who == mDrawables.mDrawableStart || who == mDrawables.mDrawableEnd; } return verified; } Loading @@ -4132,6 +4453,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mDrawables.mDrawableBottom != null) { mDrawables.mDrawableBottom.jumpToCurrentState(); } if (mDrawables.mDrawableStart != null) { mDrawables.mDrawableStart.jumpToCurrentState(); } if (mDrawables.mDrawableEnd != null) { mDrawables.mDrawableEnd.jumpToCurrentState(); } } } Loading Loading @@ -4192,7 +4519,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mDrawables != null) { final Drawables drawables = mDrawables; if (who == drawables.mDrawableLeft || who == drawables.mDrawableRight || who == drawables.mDrawableTop || who == drawables.mDrawableBottom) { who == drawables.mDrawableTop || who == drawables.mDrawableBottom || who == drawables.mDrawableStart || who == drawables.mDrawableEnd) { return getResolvedLayoutDirection(); } } Loading @@ -4211,6 +4539,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (dr.mDrawableTop != null) dr.mDrawableTop.mutate().setAlpha(alpha); if (dr.mDrawableRight != null) dr.mDrawableRight.mutate().setAlpha(alpha); if (dr.mDrawableBottom != null) dr.mDrawableBottom.mutate().setAlpha(alpha); if (dr.mDrawableStart != null) dr.mDrawableStart.mutate().setAlpha(alpha); if (dr.mDrawableEnd != null) dr.mDrawableEnd.mutate().setAlpha(alpha); } return true; } Loading Loading @@ -10275,6 +10605,68 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return (dir == Character.DIRECTIONALITY_LEFT_TO_RIGHT); } /** * Subclasses will need to override this method to implement their own way of resolving * drawables depending on the layout direction. * * A call to the super method will be required from the subclasses implementation. * */ protected void resolveDrawables() { // No need to resolve twice if (bResolvedDrawables) { return; } // No drawable to resolve if (mDrawables == null) { return; } // No relative drawable to resolve if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) { bResolvedDrawables = true; return; } Drawables dr = mDrawables; switch(getResolvedLayoutDirection()) { case LAYOUT_DIRECTION_RTL: if (dr.mDrawableStart != null) { dr.mDrawableRight = dr.mDrawableStart; dr.mDrawableSizeRight = dr.mDrawableSizeStart; dr.mDrawableHeightRight = dr.mDrawableHeightStart; } if (dr.mDrawableEnd != null) { dr.mDrawableLeft = dr.mDrawableEnd; dr.mDrawableSizeLeft = dr.mDrawableSizeEnd; dr.mDrawableHeightLeft = dr.mDrawableHeightEnd; } break; case LAYOUT_DIRECTION_LTR: default: if (dr.mDrawableStart != null) { dr.mDrawableLeft = dr.mDrawableStart; dr.mDrawableSizeLeft = dr.mDrawableSizeStart; dr.mDrawableHeightLeft = dr.mDrawableHeightStart; } if (dr.mDrawableEnd != null) { dr.mDrawableRight = dr.mDrawableEnd; dr.mDrawableSizeRight = dr.mDrawableSizeEnd; dr.mDrawableHeightRight = dr.mDrawableHeightEnd; } break; } bResolvedDrawables = true; } protected void resetResolvedDrawables() { bResolvedDrawables = false; } @ViewDebug.ExportedProperty(category = "text") private CharSequence mText; private CharSequence mTransformed; Loading core/res/res/values/attrs.xml +4 −0 Original line number Diff line number Diff line Loading @@ -3015,6 +3015,10 @@ <attr name="drawableLeft" format="reference|color" /> <!-- The drawable to be drawn to the right of the text. --> <attr name="drawableRight" format="reference|color" /> <!-- The drawable to be drawn to the start of the text. --> <attr name="drawableStart" format="reference|color" /> <!-- The drawable to be drawn to the end of the text. --> <attr name="drawableEnd" format="reference|color" /> <!-- The padding between the drawables and the text. --> <attr name="drawablePadding" format="dimension" /> <!-- Extra spacing between lines of text. --> Loading core/res/res/values/public.xml +3 −0 Original line number Diff line number Diff line Loading @@ -1826,4 +1826,7 @@ <public type="color" name="holo_purple" /> <public type="color" name="holo_blue_bright" /> <public type="attr" name="drawableStart" /> <public type="attr" name="drawableEnd" /> </resources> Loading
api/current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -377,9 +377,11 @@ package android { field public static final int drawSelectorOnTop = 16843004; // 0x10100fc field public static final int drawable = 16843161; // 0x1010199 field public static final int drawableBottom = 16843118; // 0x101016e field public static final int drawableEnd = 16843687; // 0x10103a7 field public static final int drawableLeft = 16843119; // 0x101016f field public static final int drawablePadding = 16843121; // 0x1010171 field public static final int drawableRight = 16843120; // 0x1010170 field public static final int drawableStart = 16843686; // 0x10103a6 field public static final int drawableTop = 16843117; // 0x101016d field public static final int drawingCacheQuality = 16842984; // 0x10100e8 field public static final int dropDownAnchor = 16843363; // 0x1010263 Loading Loading @@ -26421,7 +26423,9 @@ package android.widget { method protected void onTextChanged(java.lang.CharSequence, int, int, int); method public boolean onTextContextMenuItem(int); method public void removeTextChangedListener(android.text.TextWatcher); method protected void resetResolvedDrawables(); method protected void resetResolvedLayoutDirection(); method protected void resolveDrawables(); method public void setAllCaps(boolean); method public final void setAutoLinkMask(int); method public void setCompoundDrawablePadding(int);
core/java/android/widget/TextView.java +399 −7 Original line number Diff line number Diff line Loading @@ -260,9 +260,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener class Drawables { final Rect mCompoundRect = new Rect(); Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight; int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight; int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight; Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight, mDrawableStart, mDrawableEnd; int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight, mDrawableSizeStart, mDrawableSizeEnd; int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight, mDrawableHeightStart, mDrawableHeightEnd; int mDrawablePadding; } private Drawables mDrawables; Loading Loading @@ -352,6 +355,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener INHERIT, GRAVITY, TEXT_START, TEXT_END, CENTER, VIEW_START, VIEW_END; } private boolean bResolvedDrawables = false; /* * Kick-start the font cache for the zygote process (to pay the cost of * initializing freetype for our default font only once). Loading Loading @@ -494,7 +499,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int buffertype = 0; boolean selectallonfocus = false; Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null; drawableBottom = null, drawableStart = null, drawableEnd = null; int drawablePadding = 0; int ellipsize = -1; boolean singleLine = false; Loading Loading @@ -571,6 +576,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener drawableBottom = a.getDrawable(attr); break; case com.android.internal.R.styleable.TextView_drawableStart: drawableStart = a.getDrawable(attr); break; case com.android.internal.R.styleable.TextView_drawableEnd: drawableEnd = a.getDrawable(attr); break; case com.android.internal.R.styleable.TextView_drawablePadding: drawablePadding = a.getDimensionPixelSize(attr, drawablePadding); break; Loading Loading @@ -980,6 +993,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setCompoundDrawablesWithIntrinsicBounds( drawableLeft, drawableTop, drawableRight, drawableBottom); setRelativeDrawablesIfNeeded(drawableStart, drawableEnd); setCompoundDrawablePadding(drawablePadding); // Same as setSingleLine(), but make sure the transformation method and the maximum number Loading Loading @@ -1105,6 +1119,42 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setTypeface(tf, styleIndex); } private void setRelativeDrawablesIfNeeded(Drawable start, Drawable end) { boolean hasRelativeDrawables = (start != null) || (end != null); if (hasRelativeDrawables) { Drawables dr = mDrawables; if (dr == null) { mDrawables = dr = new Drawables(); } final Rect compoundRect = dr.mCompoundRect; int[] state = getDrawableState(); if (start != null) { start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight()); start.setState(state); start.copyBounds(compoundRect); start.setCallback(this); dr.mDrawableStart = start; dr.mDrawableSizeStart = compoundRect.width(); dr.mDrawableHeightStart = compoundRect.height(); } else { dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0; } if (end != null) { end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight()); end.setState(state); end.copyBounds(compoundRect); end.setCallback(this); dr.mDrawableEnd = end; dr.mDrawableSizeEnd = compoundRect.width(); dr.mDrawableHeightEnd = compoundRect.height(); } else { dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0; } } } @Override public void setEnabled(boolean enabled) { if (enabled == isEnabled()) { Loading Loading @@ -1410,6 +1460,40 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } /** * Returns the start padding of the view, plus space for the start * Drawable if any. * * @hide */ public int getCompoundPaddingStart() { resolveDrawables(); switch(getResolvedLayoutDirection()) { default: case LAYOUT_DIRECTION_LTR: return getCompoundPaddingLeft(); case LAYOUT_DIRECTION_RTL: return getCompoundPaddingRight(); } } /** * Returns the end padding of the view, plus space for the end * Drawable if any. * * @hide */ public int getCompoundPaddingEnd() { resolveDrawables(); switch(getResolvedLayoutDirection()) { default: case LAYOUT_DIRECTION_LTR: return getCompoundPaddingRight(); case LAYOUT_DIRECTION_RTL: return getCompoundPaddingLeft(); } } /** * Returns the extended top padding of the view, including both the * top Drawable if any and any extra space to keep more than maxLines Loading Loading @@ -1492,6 +1576,26 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return getCompoundPaddingRight(); } /** * Returns the total start padding of the view, including the start * Drawable if any. * * @hide */ public int getTotalPaddingStart() { return getCompoundPaddingStart(); } /** * Returns the total end padding of the view, including the end * Drawable if any. * * @hide */ public int getTotalPaddingEnd() { return getCompoundPaddingEnd(); } /** * Returns the total top padding of the view, including the top * Drawable if any, the extra space to keep more than maxLines Loading Loading @@ -1678,6 +1782,185 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setCompoundDrawables(left, top, right, bottom); } /** * Sets the Drawables (if any) to appear to the start of, above, * to the end of, and below the text. Use null if you do not * want a Drawable there. The Drawables must already have had * {@link Drawable#setBounds} called. * * @attr ref android.R.styleable#TextView_drawableStart * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableEnd * @attr ref android.R.styleable#TextView_drawableBottom * * @hide */ public void setCompoundDrawablesRelative(Drawable start, Drawable top, Drawable end, Drawable bottom) { Drawables dr = mDrawables; final boolean drawables = start != null || top != null || end != null || bottom != null; if (!drawables) { // Clearing drawables... can we free the data structure? if (dr != null) { if (dr.mDrawablePadding == 0) { mDrawables = null; } else { // We need to retain the last set padding, so just clear // out all of the fields in the existing structure. if (dr.mDrawableStart != null) dr.mDrawableStart.setCallback(null); dr.mDrawableStart = null; if (dr.mDrawableTop != null) dr.mDrawableTop.setCallback(null); dr.mDrawableTop = null; if (dr.mDrawableEnd != null) dr.mDrawableEnd.setCallback(null); dr.mDrawableEnd = null; if (dr.mDrawableBottom != null) dr.mDrawableBottom.setCallback(null); dr.mDrawableBottom = null; dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0; dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0; dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0; dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0; } } } else { if (dr == null) { mDrawables = dr = new Drawables(); } if (dr.mDrawableStart != start && dr.mDrawableStart != null) { dr.mDrawableStart.setCallback(null); } dr.mDrawableStart = start; if (dr.mDrawableTop != top && dr.mDrawableTop != null) { dr.mDrawableTop.setCallback(null); } dr.mDrawableTop = top; if (dr.mDrawableEnd != end && dr.mDrawableEnd != null) { dr.mDrawableEnd.setCallback(null); } dr.mDrawableEnd = end; if (dr.mDrawableBottom != bottom && dr.mDrawableBottom != null) { dr.mDrawableBottom.setCallback(null); } dr.mDrawableBottom = bottom; final Rect compoundRect = dr.mCompoundRect; int[] state; state = getDrawableState(); if (start != null) { start.setState(state); start.copyBounds(compoundRect); start.setCallback(this); dr.mDrawableSizeStart = compoundRect.width(); dr.mDrawableHeightStart = compoundRect.height(); } else { dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0; } if (end != null) { end.setState(state); end.copyBounds(compoundRect); end.setCallback(this); dr.mDrawableSizeEnd = compoundRect.width(); dr.mDrawableHeightEnd = compoundRect.height(); } else { dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0; } if (top != null) { top.setState(state); top.copyBounds(compoundRect); top.setCallback(this); dr.mDrawableSizeTop = compoundRect.height(); dr.mDrawableWidthTop = compoundRect.width(); } else { dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0; } if (bottom != null) { bottom.setState(state); bottom.copyBounds(compoundRect); bottom.setCallback(this); dr.mDrawableSizeBottom = compoundRect.height(); dr.mDrawableWidthBottom = compoundRect.width(); } else { dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0; } } resolveDrawables(); invalidate(); requestLayout(); } /** * Sets the Drawables (if any) to appear to the start of, above, * to the end of, and below the text. Use 0 if you do not * want a Drawable there. The Drawables' bounds will be set to * their intrinsic bounds. * * @param start Resource identifier of the start Drawable. * @param top Resource identifier of the top Drawable. * @param end Resource identifier of the end Drawable. * @param bottom Resource identifier of the bottom Drawable. * * @attr ref android.R.styleable#TextView_drawableStart * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableEnd * @attr ref android.R.styleable#TextView_drawableBottom * * @hide */ public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end, int bottom) { resetResolvedDrawables(); final Resources resources = getContext().getResources(); setCompoundDrawablesRelativeWithIntrinsicBounds( start != 0 ? resources.getDrawable(start) : null, top != 0 ? resources.getDrawable(top) : null, end != 0 ? resources.getDrawable(end) : null, bottom != 0 ? resources.getDrawable(bottom) : null); } /** * Sets the Drawables (if any) to appear to the start of, above, * to the end of, and below the text. Use null if you do not * want a Drawable there. The Drawables' bounds will be set to * their intrinsic bounds. * * @attr ref android.R.styleable#TextView_drawableStart * @attr ref android.R.styleable#TextView_drawableTop * @attr ref android.R.styleable#TextView_drawableEnd * @attr ref android.R.styleable#TextView_drawableBottom * * @hide */ public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top, Drawable end, Drawable bottom) { resetResolvedDrawables(); if (start != null) { start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight()); } if (end != null) { end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight()); } if (top != null) { top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight()); } if (bottom != null) { bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight()); } setCompoundDrawablesRelative(start, top, end, bottom); } /** * Returns drawables for the left, top, right, and bottom borders. */ Loading @@ -1692,6 +1975,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } /** * Returns drawables for the start, top, end, and bottom borders. * * @hide */ public Drawable[] getCompoundDrawablesRelative() { final Drawables dr = mDrawables; if (dr != null) { return new Drawable[] { dr.mDrawableStart, dr.mDrawableTop, dr.mDrawableEnd, dr.mDrawableBottom }; } else { return new Drawable[] { null, null, null, null }; } } /** * Sets the size of the padding between the compound drawables and * the text. Loading Loading @@ -2495,6 +2794,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (dr.mDrawableRight != null && dr.mDrawableRight.isStateful()) { dr.mDrawableRight.setState(state); } if (dr.mDrawableStart != null && dr.mDrawableStart.isStateful()) { dr.mDrawableStart.setState(state); } if (dr.mDrawableEnd != null && dr.mDrawableEnd.isStateful()) { dr.mDrawableEnd.setState(state); } } } Loading Loading @@ -3546,7 +3851,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mErrorWasChanged = true; final Drawables dr = mDrawables; if (dr != null) { setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon, dr.mDrawableBottom); switch (getResolvedLayoutDirection()) { default: case LAYOUT_DIRECTION_LTR: setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon, dr.mDrawableBottom); break; case LAYOUT_DIRECTION_RTL: setCompoundDrawables(icon, dr.mDrawableTop, dr.mDrawableRight, dr.mDrawableBottom); break; } } else { setCompoundDrawables(null, null, icon, null); } Loading Loading @@ -4048,6 +4363,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mSelectionModifierCursorController != null) { observer.addOnTouchModeChangeListener(mSelectionModifierCursorController); } // Resolve drawables as the layout direction has been resolved resolveDrawables(); } @Override Loading Loading @@ -4077,6 +4395,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } hideControllers(); resetResolvedDrawables(); } @Override Loading Loading @@ -4111,7 +4431,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final boolean verified = super.verifyDrawable(who); if (!verified && mDrawables != null) { return who == mDrawables.mDrawableLeft || who == mDrawables.mDrawableTop || who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom; who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom || who == mDrawables.mDrawableStart || who == mDrawables.mDrawableEnd; } return verified; } Loading @@ -4132,6 +4453,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mDrawables.mDrawableBottom != null) { mDrawables.mDrawableBottom.jumpToCurrentState(); } if (mDrawables.mDrawableStart != null) { mDrawables.mDrawableStart.jumpToCurrentState(); } if (mDrawables.mDrawableEnd != null) { mDrawables.mDrawableEnd.jumpToCurrentState(); } } } Loading Loading @@ -4192,7 +4519,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mDrawables != null) { final Drawables drawables = mDrawables; if (who == drawables.mDrawableLeft || who == drawables.mDrawableRight || who == drawables.mDrawableTop || who == drawables.mDrawableBottom) { who == drawables.mDrawableTop || who == drawables.mDrawableBottom || who == drawables.mDrawableStart || who == drawables.mDrawableEnd) { return getResolvedLayoutDirection(); } } Loading @@ -4211,6 +4539,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (dr.mDrawableTop != null) dr.mDrawableTop.mutate().setAlpha(alpha); if (dr.mDrawableRight != null) dr.mDrawableRight.mutate().setAlpha(alpha); if (dr.mDrawableBottom != null) dr.mDrawableBottom.mutate().setAlpha(alpha); if (dr.mDrawableStart != null) dr.mDrawableStart.mutate().setAlpha(alpha); if (dr.mDrawableEnd != null) dr.mDrawableEnd.mutate().setAlpha(alpha); } return true; } Loading Loading @@ -10275,6 +10605,68 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return (dir == Character.DIRECTIONALITY_LEFT_TO_RIGHT); } /** * Subclasses will need to override this method to implement their own way of resolving * drawables depending on the layout direction. * * A call to the super method will be required from the subclasses implementation. * */ protected void resolveDrawables() { // No need to resolve twice if (bResolvedDrawables) { return; } // No drawable to resolve if (mDrawables == null) { return; } // No relative drawable to resolve if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) { bResolvedDrawables = true; return; } Drawables dr = mDrawables; switch(getResolvedLayoutDirection()) { case LAYOUT_DIRECTION_RTL: if (dr.mDrawableStart != null) { dr.mDrawableRight = dr.mDrawableStart; dr.mDrawableSizeRight = dr.mDrawableSizeStart; dr.mDrawableHeightRight = dr.mDrawableHeightStart; } if (dr.mDrawableEnd != null) { dr.mDrawableLeft = dr.mDrawableEnd; dr.mDrawableSizeLeft = dr.mDrawableSizeEnd; dr.mDrawableHeightLeft = dr.mDrawableHeightEnd; } break; case LAYOUT_DIRECTION_LTR: default: if (dr.mDrawableStart != null) { dr.mDrawableLeft = dr.mDrawableStart; dr.mDrawableSizeLeft = dr.mDrawableSizeStart; dr.mDrawableHeightLeft = dr.mDrawableHeightStart; } if (dr.mDrawableEnd != null) { dr.mDrawableRight = dr.mDrawableEnd; dr.mDrawableSizeRight = dr.mDrawableSizeEnd; dr.mDrawableHeightRight = dr.mDrawableHeightEnd; } break; } bResolvedDrawables = true; } protected void resetResolvedDrawables() { bResolvedDrawables = false; } @ViewDebug.ExportedProperty(category = "text") private CharSequence mText; private CharSequence mTransformed; Loading
core/res/res/values/attrs.xml +4 −0 Original line number Diff line number Diff line Loading @@ -3015,6 +3015,10 @@ <attr name="drawableLeft" format="reference|color" /> <!-- The drawable to be drawn to the right of the text. --> <attr name="drawableRight" format="reference|color" /> <!-- The drawable to be drawn to the start of the text. --> <attr name="drawableStart" format="reference|color" /> <!-- The drawable to be drawn to the end of the text. --> <attr name="drawableEnd" format="reference|color" /> <!-- The padding between the drawables and the text. --> <attr name="drawablePadding" format="dimension" /> <!-- Extra spacing between lines of text. --> Loading
core/res/res/values/public.xml +3 −0 Original line number Diff line number Diff line Loading @@ -1826,4 +1826,7 @@ <public type="color" name="holo_purple" /> <public type="color" name="holo_blue_bright" /> <public type="attr" name="drawableStart" /> <public type="attr" name="drawableEnd" /> </resources>