diff --git a/src/com/android/settings/widget/DonutView.java b/src/com/android/settings/widget/DonutView.java index 4fb3c5b2464..c5ac40bde79 100644 --- a/src/com/android/settings/widget/DonutView.java +++ b/src/com/android/settings/widget/DonutView.java @@ -37,6 +37,7 @@ import android.text.style.RelativeSizeSpan; import android.util.AttributeSet; import android.view.View; +import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.Utils; @@ -173,19 +174,13 @@ public class DonutView extends View { final float centerY = getHeight() / 2; final float totalHeight = getTextHeight(mTextPaint) + getTextHeight(mBigNumberPaint); final float startY = centerY + totalHeight / 2; - final float fontProportion = getResources().getDimension( - R.dimen.storage_donut_view_percent_sign_size) / - getResources().getDimension(R.dimen.storage_donut_view_percent_text_size); // Support from Android P final String localizedPercentSign = new DecimalFormatSymbols().getPercentString(); - final int startIndex = mPercentString.indexOf(localizedPercentSign); - final int endIndex = startIndex + localizedPercentSign.length(); // The first line y-coordinates start at (total height - all TextPaint height) / 2 canvas.save(); - final Spannable percentStringSpan = new SpannableString(mPercentString); - percentStringSpan.setSpan(new RelativeSizeSpan(fontProportion), - startIndex, endIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE); + final Spannable percentStringSpan = + getPercentageStringSpannable(getResources(), mPercentString, localizedPercentSign); final StaticLayout percentStringLayout = new StaticLayout(percentStringSpan, mBigNumberPaint, getWidth(), Layout.Alignment.ALIGN_CENTER, 1, 0, false); canvas.translate(0, (getHeight() - totalHeight) / 2); @@ -235,6 +230,30 @@ public class DonutView extends View { invalidate(); } + @VisibleForTesting + static Spannable getPercentageStringSpannable( + Resources resources, String percentString, String percentageSignString) { + final float fontProportion = + resources.getDimension(R.dimen.storage_donut_view_percent_sign_size) + / resources.getDimension(R.dimen.storage_donut_view_percent_text_size); + final Spannable percentStringSpan = new SpannableString(percentString); + int startIndex = percentString.indexOf(percentageSignString); + int endIndex = startIndex + percentageSignString.length(); + + // Fallback to no small string if we can't find the percentage sign. + if (startIndex < 0) { + startIndex = 0; + endIndex = percentString.length(); + } + + percentStringSpan.setSpan( + new RelativeSizeSpan(fontProportion), + startIndex, + endIndex, + Spanned.SPAN_EXCLUSIVE_INCLUSIVE); + return percentStringSpan; + } + private float getTextHeight(TextPaint paint) { // Technically, this should be the cap height, but I can live with the descent - ascent. return paint.descent() - paint.ascent(); diff --git a/tests/robotests/src/com/android/settings/widget/DonutViewTest.java b/tests/robotests/src/com/android/settings/widget/DonutViewTest.java new file mode 100644 index 00000000000..3b8bdceeb93 --- /dev/null +++ b/tests/robotests/src/com/android/settings/widget/DonutViewTest.java @@ -0,0 +1,19 @@ +package com.android.settings.widget; + +import android.content.Context; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class DonutViewTest { + @Test + public void getPercentageStringSpannable_doesntCrashForMissingPercentage() { + Context context = RuntimeEnvironment.application; + + DonutView.getPercentageStringSpannable(context.getResources(), "50%", "h"); + } +}