diff options
| author | 2013-03-21 18:22:38 -0700 | |
|---|---|---|
| committer | 2013-03-22 13:46:08 -0700 | |
| commit | f4efad05515ae8bd8c826e2832be62a701e1c6e5 (patch) | |
| tree | 2934e1a5f6e9348378b1bcee71247e9e2e2152d6 | |
| parent | 605c5af9c8d36aab16fb9d2313fecc57301104bd (diff) | |
Fix bug #8200928 ExpandableListView should be RTL-aware
- add indicatorStart/indicatorEnd and childIndicatorStart/childIndicatorEnd properties
Change-Id: I1ee67e47798bbcb31670cc9afde3ccac68338d94
| -rw-r--r-- | api/current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/widget/ExpandableListView.java | 193 | ||||
| -rw-r--r-- | core/res/res/values/attrs.xml | 10 |
3 files changed, 185 insertions, 20 deletions
diff --git a/api/current.txt b/api/current.txt index f2fcbd6b7b67..53a803ca41ab 100644 --- a/api/current.txt +++ b/api/current.txt @@ -28563,8 +28563,10 @@ package android.widget { method public void setChildDivider(android.graphics.drawable.Drawable); method public void setChildIndicator(android.graphics.drawable.Drawable); method public void setChildIndicatorBounds(int, int); + method public void setChildIndicatorBoundsRelative(int, int); method public void setGroupIndicator(android.graphics.drawable.Drawable); method public void setIndicatorBounds(int, int); + method public void setIndicatorBoundsRelative(int, int); method public void setOnChildClickListener(android.widget.ExpandableListView.OnChildClickListener); method public void setOnGroupClickListener(android.widget.ExpandableListView.OnGroupClickListener); method public void setOnGroupCollapseListener(android.widget.ExpandableListView.OnGroupCollapseListener); diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java index 0dd567b344bb..7b81aa84fe1b 100644 --- a/core/java/android/widget/ExpandableListView.java +++ b/core/java/android/widget/ExpandableListView.java @@ -36,6 +36,8 @@ import android.widget.ExpandableListConnector.PositionMetadata; import java.util.ArrayList; +import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; + /** * A view that shows items in a vertically scrolling two-level list. This * differs from the {@link ListView} by allowing two levels: groups which can @@ -76,6 +78,10 @@ import java.util.ArrayList; * @attr ref android.R.styleable#ExpandableListView_childIndicatorLeft * @attr ref android.R.styleable#ExpandableListView_childIndicatorRight * @attr ref android.R.styleable#ExpandableListView_childDivider + * @attr ref android.R.styleable#ExpandableListView_indicatorStart + * @attr ref android.R.styleable#ExpandableListView_indicatorEnd + * @attr ref android.R.styleable#ExpandableListView_childIndicatorStart + * @attr ref android.R.styleable#ExpandableListView_childIndicatorEnd */ public class ExpandableListView extends ListView { @@ -134,6 +140,12 @@ public class ExpandableListView extends ListView { /** Right bound for drawing the indicator. */ private int mIndicatorRight; + /** Start bound for drawing the indicator. */ + private int mIndicatorStart; + + /** End bound for drawing the indicator. */ + private int mIndicatorEnd; + /** * Left bound for drawing the indicator of a child. Value of * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorLeft. @@ -147,11 +159,28 @@ public class ExpandableListView extends ListView { private int mChildIndicatorRight; /** + * Start bound for drawing the indicator of a child. Value of + * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorStart. + */ + private int mChildIndicatorStart; + + /** + * End bound for drawing the indicator of a child. Value of + * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorEnd. + */ + private int mChildIndicatorEnd; + + /** * Denotes when a child indicator should inherit this bound from the generic * indicator bounds */ public static final int CHILD_INDICATOR_INHERIT = -1; - + + /** + * Denotes an undefined value for an indicator + */ + private static final int INDICATOR_UNDEFINED = -2; + /** The indicator drawn next to a group. */ private Drawable mGroupIndicator; @@ -202,30 +231,118 @@ public class ExpandableListView extends ListView { super(context, attrs, defStyle); TypedArray a = - context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ExpandableListView, defStyle, - 0); - - mGroupIndicator = a - .getDrawable(com.android.internal.R.styleable.ExpandableListView_groupIndicator); - mChildIndicator = a - .getDrawable(com.android.internal.R.styleable.ExpandableListView_childIndicator); - mIndicatorLeft = a - .getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorLeft, 0); - mIndicatorRight = a - .getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorRight, 0); + context.obtainStyledAttributes(attrs, + com.android.internal.R.styleable.ExpandableListView, defStyle, 0); + + mGroupIndicator = a.getDrawable( + com.android.internal.R.styleable.ExpandableListView_groupIndicator); + mChildIndicator = a.getDrawable( + com.android.internal.R.styleable.ExpandableListView_childIndicator); + mIndicatorLeft = a.getDimensionPixelSize( + com.android.internal.R.styleable.ExpandableListView_indicatorLeft, 0); + mIndicatorRight = a.getDimensionPixelSize( + com.android.internal.R.styleable.ExpandableListView_indicatorRight, 0); if (mIndicatorRight == 0 && mGroupIndicator != null) { mIndicatorRight = mIndicatorLeft + mGroupIndicator.getIntrinsicWidth(); } mChildIndicatorLeft = a.getDimensionPixelSize( - com.android.internal.R.styleable.ExpandableListView_childIndicatorLeft, CHILD_INDICATOR_INHERIT); + com.android.internal.R.styleable.ExpandableListView_childIndicatorLeft, + CHILD_INDICATOR_INHERIT); mChildIndicatorRight = a.getDimensionPixelSize( - com.android.internal.R.styleable.ExpandableListView_childIndicatorRight, CHILD_INDICATOR_INHERIT); - mChildDivider = a.getDrawable(com.android.internal.R.styleable.ExpandableListView_childDivider); - + com.android.internal.R.styleable.ExpandableListView_childIndicatorRight, + CHILD_INDICATOR_INHERIT); + mChildDivider = a.getDrawable( + com.android.internal.R.styleable.ExpandableListView_childDivider); + + if (!isRtlCompatibilityMode()) { + mIndicatorStart = a.getDimensionPixelSize( + com.android.internal.R.styleable.ExpandableListView_indicatorStart, + INDICATOR_UNDEFINED); + mIndicatorEnd = a.getDimensionPixelSize( + com.android.internal.R.styleable.ExpandableListView_indicatorEnd, + INDICATOR_UNDEFINED); + + mChildIndicatorStart = a.getDimensionPixelSize( + com.android.internal.R.styleable.ExpandableListView_childIndicatorStart, + CHILD_INDICATOR_INHERIT); + mChildIndicatorEnd = a.getDimensionPixelSize( + com.android.internal.R.styleable.ExpandableListView_childIndicatorEnd, + CHILD_INDICATOR_INHERIT); + } + a.recycle(); } - - + + /** + * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or + * RTL not supported) + */ + private boolean isRtlCompatibilityMode() { + final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; + return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport(); + } + + /** + * Return true if the application tag in the AndroidManifest has set "supportRtl" to true + */ + private boolean hasRtlSupport() { + return mContext.getApplicationInfo().hasRtlSupport(); + } + + public void onRtlPropertiesChanged(int layoutDirection) { + resolveIndicator(); + resolveChildIndicator(); + } + + /** + * Resolve start/end indicator. start/end indicator always takes precedence over left/right + * indicator when defined. + */ + private void resolveIndicator() { + final boolean isLayoutRtl = isLayoutRtl(); + if (isLayoutRtl) { + if (mIndicatorStart >= 0) { + mIndicatorRight = mIndicatorStart; + } + if (mIndicatorEnd >= 0) { + mIndicatorLeft = mIndicatorEnd; + } + } else { + if (mIndicatorStart >= 0) { + mIndicatorLeft = mIndicatorStart; + } + if (mIndicatorEnd >= 0) { + mIndicatorRight = mIndicatorEnd; + } + } + if (mIndicatorRight == 0 && mGroupIndicator != null) { + mIndicatorRight = mIndicatorLeft + mGroupIndicator.getIntrinsicWidth(); + } + } + + /** + * Resolve start/end child indicator. start/end child indicator always takes precedence over + * left/right child indicator when defined. + */ + private void resolveChildIndicator() { + final boolean isLayoutRtl = isLayoutRtl(); + if (isLayoutRtl) { + if (mChildIndicatorStart >= CHILD_INDICATOR_INHERIT) { + mChildIndicatorRight = mChildIndicatorStart; + } + if (mChildIndicatorEnd >= CHILD_INDICATOR_INHERIT) { + mChildIndicatorLeft = mChildIndicatorEnd; + } + } else { + if (mChildIndicatorStart >= CHILD_INDICATOR_INHERIT) { + mChildIndicatorLeft = mChildIndicatorStart; + } + if (mChildIndicatorEnd >= CHILD_INDICATOR_INHERIT) { + mChildIndicatorRight = mChildIndicatorEnd; + } + } + } + @Override protected void dispatchDraw(Canvas canvas) { // Draw children, etc. @@ -1053,8 +1170,26 @@ public class ExpandableListView extends ListView { public void setChildIndicatorBounds(int left, int right) { mChildIndicatorLeft = left; mChildIndicatorRight = right; + resolveChildIndicator(); } - + + /** + * Sets the relative drawing bounds for the child indicator. For either, you can + * specify {@link #CHILD_INDICATOR_INHERIT} to use inherit from the general + * indicator's bounds. + * + * @see #setIndicatorBounds(int, int) + * @param start The start position (relative to the start bounds of this View) + * to start drawing the indicator. + * @param end The end position (relative to the end bounds of this + * View) to end the drawing of the indicator. + */ + public void setChildIndicatorBoundsRelative(int start, int end) { + mChildIndicatorStart = start; + mChildIndicatorEnd = end; + resolveChildIndicator(); + } + /** * Sets the indicator to be drawn next to a group. * @@ -1084,8 +1219,26 @@ public class ExpandableListView extends ListView { public void setIndicatorBounds(int left, int right) { mIndicatorLeft = left; mIndicatorRight = right; + resolveIndicator(); } - + + /** + * Sets the relative drawing bounds for the indicators (at minimum, the group indicator + * is affected by this; the child indicator is affected by this if the + * child indicator bounds are set to inherit). + * + * @see #setChildIndicatorBounds(int, int) + * @param start The start position (relative to the start bounds of this View) + * to start drawing the indicator. + * @param end The end position (relative to the end bounds of this + * View) to end the drawing of the indicator. + */ + public void setIndicatorBoundsRelative(int start, int end) { + mIndicatorStart = start; + mIndicatorEnd = end; + resolveIndicator(); + } + /** * Extra menu information specific to an {@link ExpandableListView} provided * to the diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 4a1d12d4d748..c1969f4273c0 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2709,6 +2709,16 @@ below and above child items.) The height of this will be the same as the height of the normal list item divider. --> <attr name="childDivider" format="reference|color" /> + <!-- The start bound for an item's indicator. To specify a start bound specific to children, + use childIndicatorStart. --> + <attr name="indicatorStart" format="dimension" /> + <!-- The end bound for an item's indicator. To specify a right bound specific to children, + use childIndicatorEnd. --> + <attr name="indicatorEnd" format="dimension" /> + <!-- The start bound for a child's indicator. --> + <attr name="childIndicatorStart" format="dimension" /> + <!-- The end bound for a child's indicator. --> + <attr name="childIndicatorEnd" format="dimension" /> </declare-styleable> <declare-styleable name="Gallery"> <attr name="gravity" /> |