Skip to content

Commit 4d931ac

Browse files
Fabrice Di MeglioAndroid (Google) Code Review
authored andcommitted
Merge "Fix for bug #7417949 TextView / EditText error Drawable is not put on the left in RTL mode" into jb-mr1.1-dev
2 parents d85b8d5 + bb0cbae commit 4d931ac

22 files changed

+178
-73
lines changed

core/java/android/widget/Editor.java

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -309,13 +309,15 @@ public void setError(CharSequence error, Drawable icon) {
309309
}
310310

311311
private void setErrorIcon(Drawable icon) {
312-
final Drawables dr = mTextView.mDrawables;
313-
if (dr != null) {
314-
mTextView.setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon,
315-
dr.mDrawableBottom);
316-
} else {
317-
mTextView.setCompoundDrawables(null, null, icon, null);
312+
Drawables dr = mTextView.mDrawables;
313+
if (dr == null) {
314+
mTextView.mDrawables = dr = new Drawables();
318315
}
316+
dr.setErrorDrawable(icon, mTextView);
317+
318+
mTextView.resetResolvedDrawables();
319+
mTextView.invalidate();
320+
mTextView.requestLayout();
319321
}
320322

321323
private void hideError() {
@@ -329,7 +331,7 @@ private void hideError() {
329331
}
330332

331333
/**
332-
* Returns the Y offset to make the pointy top of the error point
334+
* Returns the X offset to make the pointy top of the error point
333335
* at the middle of the error icon.
334336
*/
335337
private int getErrorX() {
@@ -340,8 +342,23 @@ private int getErrorX() {
340342
final float scale = mTextView.getResources().getDisplayMetrics().density;
341343

342344
final Drawables dr = mTextView.mDrawables;
343-
return mTextView.getWidth() - mErrorPopup.getWidth() - mTextView.getPaddingRight() -
344-
(dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
345+
346+
final int layoutDirection = mTextView.getLayoutDirection();
347+
int errorX;
348+
int offset;
349+
switch (layoutDirection) {
350+
default:
351+
case View.LAYOUT_DIRECTION_LTR:
352+
offset = - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
353+
errorX = mTextView.getWidth() - mErrorPopup.getWidth() -
354+
mTextView.getPaddingRight() + offset;
355+
break;
356+
case View.LAYOUT_DIRECTION_RTL:
357+
offset = (dr != null ? dr.mDrawableSizeLeft : 0) / 2 - (int) (25 * scale + 0.5f);
358+
errorX = mTextView.getPaddingLeft() + offset;
359+
break;
360+
}
361+
return errorX;
345362
}
346363

347364
/**
@@ -358,16 +375,27 @@ private int getErrorY() {
358375
mTextView.getCompoundPaddingBottom() - compoundPaddingTop;
359376

360377
final Drawables dr = mTextView.mDrawables;
361-
int icontop = compoundPaddingTop +
362-
(vspace - (dr != null ? dr.mDrawableHeightRight : 0)) / 2;
378+
379+
final int layoutDirection = mTextView.getLayoutDirection();
380+
int height;
381+
switch (layoutDirection) {
382+
default:
383+
case View.LAYOUT_DIRECTION_LTR:
384+
height = (dr != null ? dr.mDrawableHeightRight : 0);
385+
break;
386+
case View.LAYOUT_DIRECTION_RTL:
387+
height = (dr != null ? dr.mDrawableHeightLeft : 0);
388+
break;
389+
}
390+
391+
int icontop = compoundPaddingTop + (vspace - height) / 2;
363392

364393
/*
365394
* The "2" is the distance between the point and the top edge
366395
* of the background.
367396
*/
368397
final float scale = mTextView.getResources().getDisplayMetrics().density;
369-
return icontop + (dr != null ? dr.mDrawableHeightRight : 0) - mTextView.getHeight() -
370-
(int) (2 * scale + 0.5f);
398+
return icontop + height - mTextView.getHeight() - (int) (2 * scale + 0.5f);
371399
}
372400

373401
void createInputContentTypeIfNeeded() {
@@ -3726,7 +3754,7 @@ private static class ErrorPopup extends PopupWindow {
37263754
super(v, width, height);
37273755
mView = v;
37283756
// Make sure the TextView has a background set as it will be used the first time it is
3729-
// shown and positionned. Initialized with below background, which should have
3757+
// shown and positioned. Initialized with below background, which should have
37303758
// dimensions identical to the above version for this to work (and is more likely).
37313759
mPopupInlineErrorBackgroundId = getResourceId(mPopupInlineErrorBackgroundId,
37323760
com.android.internal.R.styleable.Theme_errorMessageBackground);

core/java/android/widget/TextView.java

Lines changed: 136 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -284,15 +284,144 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
284284
private TextUtils.TruncateAt mEllipsize;
285285

286286
static class Drawables {
287+
final static int DRAWABLE_NONE = -1;
288+
final static int DRAWABLE_RIGHT = 0;
289+
final static int DRAWABLE_LEFT = 1;
290+
287291
final Rect mCompoundRect = new Rect();
292+
288293
Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight,
289-
mDrawableStart, mDrawableEnd;
294+
mDrawableStart, mDrawableEnd, mDrawableError, mDrawableTemp;
295+
290296
int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight,
291-
mDrawableSizeStart, mDrawableSizeEnd;
297+
mDrawableSizeStart, mDrawableSizeEnd, mDrawableSizeError, mDrawableSizeTemp;
298+
292299
int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight,
293-
mDrawableHeightStart, mDrawableHeightEnd;
300+
mDrawableHeightStart, mDrawableHeightEnd, mDrawableHeightError, mDrawableHeightTemp;
301+
294302
int mDrawablePadding;
303+
304+
int mDrawableSaved = DRAWABLE_NONE;
305+
306+
public void resolveWithLayoutDirection(int layoutDirection) {
307+
switch(layoutDirection) {
308+
case LAYOUT_DIRECTION_RTL:
309+
if (mDrawableStart != null) {
310+
mDrawableRight = mDrawableStart;
311+
312+
mDrawableSizeRight = mDrawableSizeStart;
313+
mDrawableHeightRight = mDrawableHeightStart;
314+
}
315+
if (mDrawableEnd != null) {
316+
mDrawableLeft = mDrawableEnd;
317+
318+
mDrawableSizeLeft = mDrawableSizeEnd;
319+
mDrawableHeightLeft = mDrawableHeightEnd;
320+
}
321+
break;
322+
323+
case LAYOUT_DIRECTION_LTR:
324+
default:
325+
if (mDrawableStart != null) {
326+
mDrawableLeft = mDrawableStart;
327+
328+
mDrawableSizeLeft = mDrawableSizeStart;
329+
mDrawableHeightLeft = mDrawableHeightStart;
330+
}
331+
if (mDrawableEnd != null) {
332+
mDrawableRight = mDrawableEnd;
333+
334+
mDrawableSizeRight = mDrawableSizeEnd;
335+
mDrawableHeightRight = mDrawableHeightEnd;
336+
}
337+
break;
338+
}
339+
applyErrorDrawableIfNeeded(layoutDirection);
340+
updateDrawablesLayoutDirection(layoutDirection);
341+
}
342+
343+
private void updateDrawablesLayoutDirection(int layoutDirection) {
344+
if (mDrawableLeft != null) {
345+
mDrawableLeft.setLayoutDirection(layoutDirection);
346+
}
347+
if (mDrawableRight != null) {
348+
mDrawableRight.setLayoutDirection(layoutDirection);
349+
}
350+
if (mDrawableTop != null) {
351+
mDrawableTop.setLayoutDirection(layoutDirection);
352+
}
353+
if (mDrawableBottom != null) {
354+
mDrawableBottom.setLayoutDirection(layoutDirection);
355+
}
356+
}
357+
358+
public void setErrorDrawable(Drawable dr, TextView tv) {
359+
if (mDrawableError != dr && mDrawableError != null) {
360+
mDrawableError.setCallback(null);
361+
}
362+
mDrawableError = dr;
363+
364+
final Rect compoundRect = mCompoundRect;
365+
int[] state = tv.getDrawableState();
366+
367+
if (mDrawableError != null) {
368+
mDrawableError.setState(state);
369+
mDrawableError.copyBounds(compoundRect);
370+
mDrawableError.setCallback(tv);
371+
mDrawableSizeError = compoundRect.width();
372+
mDrawableHeightError = compoundRect.height();
373+
} else {
374+
mDrawableSizeError = mDrawableHeightError = 0;
375+
}
376+
}
377+
378+
private void applyErrorDrawableIfNeeded(int layoutDirection) {
379+
// first restore the initial state if needed
380+
switch (mDrawableSaved) {
381+
case DRAWABLE_LEFT:
382+
mDrawableLeft = mDrawableTemp;
383+
mDrawableSizeLeft = mDrawableSizeTemp;
384+
mDrawableHeightLeft = mDrawableHeightTemp;
385+
break;
386+
case DRAWABLE_RIGHT:
387+
mDrawableRight = mDrawableTemp;
388+
mDrawableSizeRight = mDrawableSizeTemp;
389+
mDrawableHeightRight = mDrawableHeightTemp;
390+
break;
391+
case DRAWABLE_NONE:
392+
default:
393+
}
394+
// then, if needed, assign the Error drawable to the correct location
395+
if (mDrawableError != null) {
396+
switch(layoutDirection) {
397+
case LAYOUT_DIRECTION_RTL:
398+
mDrawableSaved = DRAWABLE_LEFT;
399+
400+
mDrawableTemp = mDrawableLeft;
401+
mDrawableSizeTemp = mDrawableSizeLeft;
402+
mDrawableHeightTemp = mDrawableHeightLeft;
403+
404+
mDrawableLeft = mDrawableError;
405+
mDrawableSizeLeft = mDrawableSizeError;
406+
mDrawableHeightLeft = mDrawableHeightError;
407+
break;
408+
case LAYOUT_DIRECTION_LTR:
409+
default:
410+
mDrawableSaved = DRAWABLE_RIGHT;
411+
412+
mDrawableTemp = mDrawableRight;
413+
mDrawableSizeTemp = mDrawableSizeRight;
414+
mDrawableHeightTemp = mDrawableHeightRight;
415+
416+
mDrawableRight = mDrawableError;
417+
mDrawableSizeRight = mDrawableSizeError;
418+
mDrawableHeightRight = mDrawableHeightError;
419+
break;
420+
}
421+
}
422+
}
295423
}
424+
296425
Drawables mDrawables;
297426

298427
private CharWrapper mCharWrapper;
@@ -8263,70 +8392,18 @@ public void onResolveDrawables(int layoutDirection) {
82638392
return;
82648393
}
82658394
mLastLayoutDirection = layoutDirection;
8266-
// No drawable to resolve
8267-
if (mDrawables == null) {
8268-
return;
8269-
}
8270-
// No relative drawable to resolve
8271-
if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) {
8272-
return;
8273-
}
8274-
8275-
Drawables dr = mDrawables;
8276-
switch(layoutDirection) {
8277-
case LAYOUT_DIRECTION_RTL:
8278-
if (dr.mDrawableStart != null) {
8279-
dr.mDrawableRight = dr.mDrawableStart;
8280-
8281-
dr.mDrawableSizeRight = dr.mDrawableSizeStart;
8282-
dr.mDrawableHeightRight = dr.mDrawableHeightStart;
8283-
}
8284-
if (dr.mDrawableEnd != null) {
8285-
dr.mDrawableLeft = dr.mDrawableEnd;
82868395

8287-
dr.mDrawableSizeLeft = dr.mDrawableSizeEnd;
8288-
dr.mDrawableHeightLeft = dr.mDrawableHeightEnd;
8289-
}
8290-
break;
8291-
8292-
case LAYOUT_DIRECTION_LTR:
8293-
default:
8294-
if (dr.mDrawableStart != null) {
8295-
dr.mDrawableLeft = dr.mDrawableStart;
8296-
8297-
dr.mDrawableSizeLeft = dr.mDrawableSizeStart;
8298-
dr.mDrawableHeightLeft = dr.mDrawableHeightStart;
8299-
}
8300-
if (dr.mDrawableEnd != null) {
8301-
dr.mDrawableRight = dr.mDrawableEnd;
8302-
8303-
dr.mDrawableSizeRight = dr.mDrawableSizeEnd;
8304-
dr.mDrawableHeightRight = dr.mDrawableHeightEnd;
8305-
}
8306-
break;
8307-
}
8308-
updateDrawablesLayoutDirection(dr, layoutDirection);
8309-
}
8310-
8311-
private void updateDrawablesLayoutDirection(Drawables dr, int layoutDirection) {
8312-
if (dr.mDrawableLeft != null) {
8313-
dr.mDrawableLeft.setLayoutDirection(layoutDirection);
8314-
}
8315-
if (dr.mDrawableRight != null) {
8316-
dr.mDrawableRight.setLayoutDirection(layoutDirection);
8317-
}
8318-
if (dr.mDrawableTop != null) {
8319-
dr.mDrawableTop.setLayoutDirection(layoutDirection);
8320-
}
8321-
if (dr.mDrawableBottom != null) {
8322-
dr.mDrawableBottom.setLayoutDirection(layoutDirection);
8396+
// Resolve drawables
8397+
if (mDrawables != null) {
8398+
mDrawables.resolveWithLayoutDirection(layoutDirection);
83238399
}
83248400
}
83258401

83268402
/**
83278403
* @hide
83288404
*/
83298405
protected void resetResolvedDrawables() {
8406+
super.resetResolvedDrawables();
83308407
mLastLayoutDirection = -1;
83318408
}
83328409

2.33 KB
Loading
2.35 KB
Loading
940 Bytes
Loading
932 Bytes
Loading
915 Bytes
Loading
919 Bytes
Loading
1.09 KB
Loading
1.12 KB
Loading

0 commit comments

Comments
 (0)