Fix TabLayout crashing due to using getMaxLines()
Added a compatible shim to TextViewCompat
BUG: 24663522
Change-Id: I6ba367338a6c42ecad175c5ebe0163c3dc5a9cd2
diff --git a/design/src/android/support/design/widget/TabLayout.java b/design/src/android/support/design/widget/TabLayout.java
index afcd3b7e..2410a32 100755
--- a/design/src/android/support/design/widget/TabLayout.java
+++ b/design/src/android/support/design/widget/TabLayout.java
@@ -37,6 +37,7 @@
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
+import android.support.v4.widget.TextViewCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.internal.widget.TintManager;
import android.text.Layout;
@@ -1246,8 +1247,9 @@
final float curTextSize = mTextView.getTextSize();
final int curLineCount = mTextView.getLineCount();
+ final int curMaxLines = TextViewCompat.getMaxLines(mTextView);
- if (textSize != curTextSize || maxLines != mTextView.getMaxLines()) {
+ if (textSize != curTextSize || (curMaxLines >= 0 && maxLines != curMaxLines)) {
// We've got a new text size and/or max lines...
boolean updateTextView = true;
@@ -1294,7 +1296,7 @@
mCustomTextView = (TextView) custom.findViewById(android.R.id.text1);
if (mCustomTextView != null) {
- mDefaultMaxLines = mCustomTextView.getMaxLines();
+ mDefaultMaxLines = TextViewCompat.getMaxLines(mCustomTextView);
}
mCustomIconView = (ImageView) custom.findViewById(android.R.id.icon);
} else {
@@ -1320,7 +1322,7 @@
.inflate(R.layout.design_layout_tab_text, this, false);
addView(textView);
mTextView = textView;
- mDefaultMaxLines = mTextView.getMaxLines();
+ mDefaultMaxLines = TextViewCompat.getMaxLines(mTextView);
}
mTextView.setTextAppearance(getContext(), mTabTextAppearance);
if (mTabTextColors != null) {
diff --git a/v4/api/current.txt b/v4/api/current.txt
index 861e887..ccefe22 100644
--- a/v4/api/current.txt
+++ b/v4/api/current.txt
@@ -3449,6 +3449,8 @@
}
public class TextViewCompat {
+ method public static int getMaxLines(android.widget.TextView);
+ method public static int getMinLines(android.widget.TextView);
method public static void setCompoundDrawablesRelative(android.widget.TextView, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
method public static void setCompoundDrawablesRelativeWithIntrinsicBounds(android.widget.TextView, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
method public static void setCompoundDrawablesRelativeWithIntrinsicBounds(android.widget.TextView, int, int, int, int);
diff --git a/v4/java/android/support/v4/widget/TextViewCompat.java b/v4/java/android/support/v4/widget/TextViewCompat.java
index c31196a..d8c5385 100644
--- a/v4/java/android/support/v4/widget/TextViewCompat.java
+++ b/v4/java/android/support/v4/widget/TextViewCompat.java
@@ -29,26 +29,22 @@
public class TextViewCompat {
// Hide constructor
- private TextViewCompat() {
- }
+ private TextViewCompat() {}
interface TextViewCompatImpl {
-
- public void setCompoundDrawablesRelative(@NonNull TextView textView,
+ void setCompoundDrawablesRelative(@NonNull TextView textView,
@Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
@Nullable Drawable bottom);
-
- public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
+ void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
@Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
@Nullable Drawable bottom);
-
- public void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
+ void setCompoundDrawablesRelativeWithIntrinsicBounds(@NonNull TextView textView,
int start, int top, int end, int bottom);
-
+ int getMaxLines(TextView textView);
+ int getMinLines(TextView textView);
}
static class BaseTextViewCompatImpl implements TextViewCompatImpl {
-
@Override
public void setCompoundDrawablesRelative(@NonNull TextView textView,
@Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
@@ -69,11 +65,31 @@
textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
}
+ @Override
+ public int getMaxLines(TextView textView) {
+ return TextViewCompatDonut.getMaxLines(textView);
+ }
+
+ @Override
+ public int getMinLines(TextView textView) {
+ return TextViewCompatDonut.getMinLines(textView);
+ }
}
- static class JbMr1TextViewCompatImpl extends BaseTextViewCompatImpl {
+ static class JbTextViewCompatImpl extends BaseTextViewCompatImpl {
+ @Override
+ public int getMaxLines(TextView textView) {
+ return TextViewCompatJb.getMaxLines(textView);
+ }
@Override
+ public int getMinLines(TextView textView) {
+ return TextViewCompatJb.getMinLines(textView);
+ }
+ }
+
+ static class JbMr1TextViewCompatImpl extends JbTextViewCompatImpl {
+ @Override
public void setCompoundDrawablesRelative(@NonNull TextView textView,
@Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
@Nullable Drawable bottom) {
@@ -94,11 +110,9 @@
TextViewCompatJbMr1.setCompoundDrawablesRelativeWithIntrinsicBounds(textView,
start, top, end, bottom);
}
-
}
static class JbMr2TextViewCompatImpl extends JbMr1TextViewCompatImpl {
-
@Override
public void setCompoundDrawablesRelative(@NonNull TextView textView,
@Nullable Drawable start, @Nullable Drawable top, @Nullable Drawable end,
@@ -131,6 +145,8 @@
IMPL = new JbMr2TextViewCompatImpl();
} else if (version >= 17) {
IMPL = new JbMr1TextViewCompatImpl();
+ } else if (version >= 16) {
+ IMPL = new JbTextViewCompatImpl();
} else {
IMPL = new BaseTextViewCompatImpl();
}
@@ -200,4 +216,19 @@
IMPL.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, start, top, end, bottom);
}
+ /**
+ * Returns the maximum number of lines displayed in the given TextView, or -1 if the maximum
+ * height was set in pixels instead.
+ */
+ public static int getMaxLines(@NonNull TextView textView) {
+ return IMPL.getMaxLines(textView);
+ }
+
+ /**
+ * Returns the minimum number of lines displayed in the given TextView, or -1 if the minimum
+ * height was set in pixels instead.
+ */
+ public static int getMinLines(@NonNull TextView textView) {
+ return IMPL.getMinLines(textView);
+ }
}
diff --git a/v4/java/android/support/v4/widget/TextViewCompatDonut.java b/v4/java/android/support/v4/widget/TextViewCompatDonut.java
new file mode 100644
index 0000000..9a36e82
--- /dev/null
+++ b/v4/java/android/support/v4/widget/TextViewCompatDonut.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.widget;
+
+import android.util.Log;
+import android.widget.TextView;
+
+import java.lang.reflect.Field;
+
+class TextViewCompatDonut {
+
+ private static final String LOG_TAG = "TextViewCompatDonut";
+ private static final int LINES = 1;
+
+ private static Field sMaximumField;
+ private static boolean sMaximumFieldFetched;
+ private static Field sMaxModeField;
+ private static boolean sMaxModeFieldFetched;
+
+ private static Field sMinimumField;
+ private static boolean sMinimumFieldFetched;
+ private static Field sMinModeField;
+ private static boolean sMinModeFieldFetched;
+
+ static int getMaxLines(TextView textView) {
+ if (!sMaxModeFieldFetched) {
+ sMaxModeField = retrieveField("mMaxMode");
+ sMaxModeFieldFetched = true;
+ }
+ if (sMaxModeField != null && retrieveIntFromField(sMaxModeField, textView) == LINES) {
+ // If the max mode is using lines, we can grab the maximum value
+ if (!sMaximumFieldFetched) {
+ sMaximumField = retrieveField("mMaximum");
+ sMaximumFieldFetched = true;
+ }
+ if (sMaximumField != null) {
+ return retrieveIntFromField(sMaximumField, textView);
+ }
+ }
+ return -1;
+ }
+
+ static int getMinLines(TextView textView) {
+ if (!sMinModeFieldFetched) {
+ sMinModeField = retrieveField("mMinMode");
+ sMinModeFieldFetched = true;
+ }
+ if (sMinModeField != null && retrieveIntFromField(sMinModeField, textView) == LINES) {
+ // If the min mode is using lines, we can grab the maximum value
+ if (!sMinimumFieldFetched) {
+ sMinimumField = retrieveField("mMinimum");
+ sMinimumFieldFetched = true;
+ }
+ if (sMinimumField != null) {
+ return retrieveIntFromField(sMinimumField, textView);
+ }
+ }
+ return -1;
+ }
+
+ private static Field retrieveField(String fieldName) {
+ Field field = null;
+ try {
+ field = TextView.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ Log.e(LOG_TAG, "Could not retrieve " + fieldName + " field.");
+ }
+ return field;
+ }
+
+ private static int retrieveIntFromField(Field field, TextView textView) {
+ try {
+ return field.getInt(textView);
+ } catch (IllegalAccessException e) {
+ Log.d(LOG_TAG, "Could not retrieve value of " + field.getName() + " field.");
+ }
+ return -1;
+ }
+}
diff --git a/v4/jellybean/android/support/v4/widget/TextViewCompatJb.java b/v4/jellybean/android/support/v4/widget/TextViewCompatJb.java
new file mode 100644
index 0000000..1658874
--- /dev/null
+++ b/v4/jellybean/android/support/v4/widget/TextViewCompatJb.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.widget;
+
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.TextView;
+
+class TextViewCompatJb {
+ static int getMaxLines(TextView textView) {
+ return textView.getMaxLines();
+ }
+
+ static int getMinLines(TextView textView) {
+ return textView.getMinLines();
+ }
+}