Skip to content

Commit 9a04856

Browse files
author
Fabrice Di Meglio
committed
Other improvements for bug #6427629 Clean up layout direction APIs
- hide isLayoutRtl() from public API - canResolveXXX() is now smarter: use recursion to get its returned value - in ViewGroup, if resolution cannot be done then dont ask resolution for its children - in ViewGroup, addViewInner() needs to ask to resolve the child. This is needed for example by ListView which is using the same measurespec before and after its childs being attached. It also take care of the general case where a measure pass is done when not attached to a parent (and thus asking for resolution that will "fail" if we are using IHNERIT) and never done again. That would lead to never do a resolution. - some code refactoring Change-Id: I120dd2fef7397944f5ba8deff0686b108dc827d2
1 parent 0b17115 commit 9a04856

File tree

3 files changed

+115
-83
lines changed

3 files changed

+115
-83
lines changed

api/current.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25038,7 +25038,6 @@ package android.view {
2503825038
method public boolean isInEditMode();
2503925039
method public boolean isInTouchMode();
2504025040
method public boolean isLayoutRequested();
25041-
method public boolean isLayoutRtl();
2504225041
method public boolean isLongClickable();
2504325042
method public boolean isOpaque();
2504425043
method protected boolean isPaddingOffsetRequired();

core/java/android/view/View.java

Lines changed: 80 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5859,6 +5859,8 @@ public int getLayoutDirection() {
58595859
* layout attribute and/or the inherited value from the parent
58605860
*
58615861
* @return true if the layout is right-to-left.
5862+
*
5863+
* @hide
58625864
*/
58635865
@ViewDebug.ExportedProperty(category = "layout")
58645866
public boolean isLayoutRtl() {
@@ -11591,9 +11593,11 @@ public void onRtlPropertiesChanged() {
1159111593
* Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
1159211594
* that the parent directionality can and will be resolved before its children.
1159311595
*
11596+
* @return true if resolution has been done, false otherwise.
11597+
*
1159411598
* @hide
1159511599
*/
11596-
public void resolveLayoutDirection() {
11600+
public boolean resolveLayoutDirection() {
1159711601
// Clear any previous layout direction resolution
1159811602
mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
1159911603

@@ -11604,15 +11608,13 @@ public void resolveLayoutDirection() {
1160411608
case LAYOUT_DIRECTION_INHERIT:
1160511609
// We cannot resolve yet. LTR is by default and let the resolution happen again
1160611610
// later to get the correct resolved value
11607-
if (!canResolveLayoutDirection()) return;
11608-
11609-
ViewGroup viewGroup = ((ViewGroup) mParent);
11611+
if (!canResolveLayoutDirection()) return false;
1161011612

11611-
// We cannot resolve yet on the parent too. LTR is by default and let the
11612-
// resolution happen again later
11613-
if (!viewGroup.canResolveLayoutDirection()) return;
11613+
View parent = ((View) mParent);
11614+
// Parent has not yet resolved, LTR is still the default
11615+
if (!parent.isLayoutDirectionResolved()) return false;
1161411616

11615-
if (viewGroup.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
11617+
if (parent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
1161611618
mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
1161711619
}
1161811620
break;
@@ -11632,6 +11634,7 @@ public void resolveLayoutDirection() {
1163211634

1163311635
// Set to resolved
1163411636
mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
11637+
return true;
1163511638
}
1163611639

1163711640
/**
@@ -11642,10 +11645,10 @@ public void resolveLayoutDirection() {
1164211645
* @hide
1164311646
*/
1164411647
public boolean canResolveLayoutDirection() {
11645-
switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
11646-
PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
11648+
switch (getRawLayoutDirection()) {
1164711649
case LAYOUT_DIRECTION_INHERIT:
11648-
return (mParent != null) && (mParent instanceof ViewGroup);
11650+
return (mParent != null) && (mParent instanceof ViewGroup) &&
11651+
((ViewGroup) mParent).canResolveLayoutDirection();
1164911652
default:
1165011653
return true;
1165111654
}
@@ -16622,9 +16625,11 @@ public int getTextDirection() {
1662216625
/**
1662316626
* Resolve the text direction.
1662416627
*
16628+
* @return true if resolution has been done, false otherwise.
16629+
*
1662516630
* @hide
1662616631
*/
16627-
public void resolveTextDirection() {
16632+
public boolean resolveTextDirection() {
1662816633
// Reset any previous text direction resolution
1662916634
mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
1663016635

@@ -16633,29 +16638,35 @@ public void resolveTextDirection() {
1663316638
final int textDirection = getRawTextDirection();
1663416639
switch(textDirection) {
1663516640
case TEXT_DIRECTION_INHERIT:
16636-
if (canResolveTextDirection()) {
16637-
ViewGroup viewGroup = ((ViewGroup) mParent);
16638-
16639-
// Set current resolved direction to the same value as the parent's one
16640-
final int parentResolvedDirection = viewGroup.getTextDirection();
16641-
switch (parentResolvedDirection) {
16642-
case TEXT_DIRECTION_FIRST_STRONG:
16643-
case TEXT_DIRECTION_ANY_RTL:
16644-
case TEXT_DIRECTION_LTR:
16645-
case TEXT_DIRECTION_RTL:
16646-
case TEXT_DIRECTION_LOCALE:
16647-
mPrivateFlags2 |=
16648-
(parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
16649-
break;
16650-
default:
16651-
// Default resolved direction is "first strong" heuristic
16652-
mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16653-
}
16654-
} else {
16641+
if (!canResolveTextDirection()) {
1665516642
// We cannot do the resolution if there is no parent, so use the default one
1665616643
mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
1665716644
// Resolution will need to happen again later
16658-
return;
16645+
return false;
16646+
}
16647+
16648+
View parent = ((View) mParent);
16649+
// Parent has not yet resolved, so we still return the default
16650+
if (!parent.isTextDirectionResolved()) {
16651+
mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16652+
// Resolution will need to happen again later
16653+
return false;
16654+
}
16655+
16656+
// Set current resolved direction to the same value as the parent's one
16657+
final int parentResolvedDirection = parent.getTextDirection();
16658+
switch (parentResolvedDirection) {
16659+
case TEXT_DIRECTION_FIRST_STRONG:
16660+
case TEXT_DIRECTION_ANY_RTL:
16661+
case TEXT_DIRECTION_LTR:
16662+
case TEXT_DIRECTION_RTL:
16663+
case TEXT_DIRECTION_LOCALE:
16664+
mPrivateFlags2 |=
16665+
(parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
16666+
break;
16667+
default:
16668+
// Default resolved direction is "first strong" heuristic
16669+
mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
1665916670
}
1666016671
break;
1666116672
case TEXT_DIRECTION_FIRST_STRONG:
@@ -16677,6 +16688,7 @@ public void resolveTextDirection() {
1667716688

1667816689
// Set to resolved
1667916690
mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
16691+
return true;
1668016692
}
1668116693

1668216694
/**
@@ -16687,7 +16699,8 @@ public void resolveTextDirection() {
1668716699
private boolean canResolveTextDirection() {
1668816700
switch (getRawTextDirection()) {
1668916701
case TEXT_DIRECTION_INHERIT:
16690-
return (mParent != null) && (mParent instanceof ViewGroup);
16702+
return (mParent != null) && (mParent instanceof View) &&
16703+
((View) mParent).canResolveTextDirection();
1669116704
default:
1669216705
return true;
1669316706
}
@@ -16817,9 +16830,11 @@ public int getTextAlignment() {
1681716830
/**
1681816831
* Resolve the text alignment.
1681916832
*
16833+
* @return true if resolution has been done, false otherwise.
16834+
*
1682016835
* @hide
1682116836
*/
16822-
public void resolveTextAlignment() {
16837+
public boolean resolveTextAlignment() {
1682316838
// Reset any previous text alignment resolution
1682416839
mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
1682516840

@@ -16829,32 +16844,37 @@ public void resolveTextAlignment() {
1682916844
switch (textAlignment) {
1683016845
case TEXT_ALIGNMENT_INHERIT:
1683116846
// Check if we can resolve the text alignment
16832-
if (canResolveTextAlignment() && mParent instanceof View) {
16833-
View view = (View) mParent;
16834-
16835-
final int parentResolvedTextAlignment = view.getTextAlignment();
16836-
switch (parentResolvedTextAlignment) {
16837-
case TEXT_ALIGNMENT_GRAVITY:
16838-
case TEXT_ALIGNMENT_TEXT_START:
16839-
case TEXT_ALIGNMENT_TEXT_END:
16840-
case TEXT_ALIGNMENT_CENTER:
16841-
case TEXT_ALIGNMENT_VIEW_START:
16842-
case TEXT_ALIGNMENT_VIEW_END:
16843-
// Resolved text alignment is the same as the parent resolved
16844-
// text alignment
16845-
mPrivateFlags2 |=
16846-
(parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
16847-
break;
16848-
default:
16849-
// Use default resolved text alignment
16850-
mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16851-
}
16852-
}
16853-
else {
16847+
if (!canResolveTextAlignment()) {
1685416848
// We cannot do the resolution if there is no parent so use the default
1685516849
mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
1685616850
// Resolution will need to happen again later
16857-
return;
16851+
return false;
16852+
}
16853+
View parent = (View) mParent;
16854+
16855+
// Parent has not yet resolved, so we still return the default
16856+
if (!parent.isTextAlignmentResolved()) {
16857+
mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16858+
// Resolution will need to happen again later
16859+
return false;
16860+
}
16861+
16862+
final int parentResolvedTextAlignment = parent.getTextAlignment();
16863+
switch (parentResolvedTextAlignment) {
16864+
case TEXT_ALIGNMENT_GRAVITY:
16865+
case TEXT_ALIGNMENT_TEXT_START:
16866+
case TEXT_ALIGNMENT_TEXT_END:
16867+
case TEXT_ALIGNMENT_CENTER:
16868+
case TEXT_ALIGNMENT_VIEW_START:
16869+
case TEXT_ALIGNMENT_VIEW_END:
16870+
// Resolved text alignment is the same as the parent resolved
16871+
// text alignment
16872+
mPrivateFlags2 |=
16873+
(parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
16874+
break;
16875+
default:
16876+
// Use default resolved text alignment
16877+
mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
1685816878
}
1685916879
break;
1686016880
case TEXT_ALIGNMENT_GRAVITY:
@@ -16877,6 +16897,7 @@ public void resolveTextAlignment() {
1687716897

1687816898
// Set the resolved
1687916899
mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
16900+
return true;
1688016901
}
1688116902

1688216903
/**
@@ -16887,7 +16908,8 @@ public void resolveTextAlignment() {
1688716908
private boolean canResolveTextAlignment() {
1688816909
switch (getRawTextAlignment()) {
1688916910
case TEXT_DIRECTION_INHERIT:
16890-
return (mParent != null);
16911+
return (mParent != null) && (mParent instanceof View) &&
16912+
((View) mParent).canResolveTextAlignment();
1689116913
default:
1689216914
return true;
1689316915
}

core/java/android/view/ViewGroup.java

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3382,6 +3382,11 @@ private void addViewInner(View child, int index, LayoutParams params,
33823382
ai.mKeepScreenOn = lastKeepOn;
33833383
}
33843384

3385+
if (child.isLayoutDirectionInherited()) {
3386+
child.resetResolvedLayoutDirection();
3387+
child.resolveRtlPropertiesIfNeeded();
3388+
}
3389+
33853390
onViewAdded(child);
33863391

33873392
if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
@@ -5256,48 +5261,54 @@ public void requestTransitionStart(LayoutTransition transition) {
52565261
* @hide
52575262
*/
52585263
@Override
5259-
public void resolveLayoutDirection() {
5260-
super.resolveLayoutDirection();
5261-
5262-
int count = getChildCount();
5263-
for (int i = 0; i < count; i++) {
5264-
final View child = getChildAt(i);
5265-
if (child.isLayoutDirectionInherited()) {
5266-
child.resolveLayoutDirection();
5264+
public boolean resolveLayoutDirection() {
5265+
final boolean result = super.resolveLayoutDirection();
5266+
if (result) {
5267+
int count = getChildCount();
5268+
for (int i = 0; i < count; i++) {
5269+
final View child = getChildAt(i);
5270+
if (child.isLayoutDirectionInherited()) {
5271+
child.resolveLayoutDirection();
5272+
}
52675273
}
52685274
}
5275+
return result;
52695276
}
52705277

52715278
/**
52725279
* @hide
52735280
*/
52745281
@Override
5275-
public void resolveTextDirection() {
5276-
super.resolveTextDirection();
5277-
5278-
int count = getChildCount();
5279-
for (int i = 0; i < count; i++) {
5280-
final View child = getChildAt(i);
5281-
if (child.isTextDirectionInherited()) {
5282-
child.resolveTextDirection();
5282+
public boolean resolveTextDirection() {
5283+
final boolean result = super.resolveTextDirection();
5284+
if (result) {
5285+
int count = getChildCount();
5286+
for (int i = 0; i < count; i++) {
5287+
final View child = getChildAt(i);
5288+
if (child.isTextDirectionInherited()) {
5289+
child.resolveTextDirection();
5290+
}
52835291
}
52845292
}
5293+
return result;
52855294
}
52865295

52875296
/**
52885297
* @hide
52895298
*/
52905299
@Override
5291-
public void resolveTextAlignment() {
5292-
super.resolveTextAlignment();
5293-
5294-
int count = getChildCount();
5295-
for (int i = 0; i < count; i++) {
5296-
final View child = getChildAt(i);
5297-
if (child.isTextAlignmentInherited()) {
5298-
child.resolveTextAlignment();
5300+
public boolean resolveTextAlignment() {
5301+
final boolean result = super.resolveTextAlignment();
5302+
if (result) {
5303+
int count = getChildCount();
5304+
for (int i = 0; i < count; i++) {
5305+
final View child = getChildAt(i);
5306+
if (child.isTextAlignmentInherited()) {
5307+
child.resolveTextAlignment();
5308+
}
52995309
}
53005310
}
5311+
return result;
53015312
}
53025313

53035314
/**

0 commit comments

Comments
 (0)