Open Qixingchen opened 6 years ago
同样遇到这个问题。
这些 TextInputLayout 的第一层崩溃都在一个魅族自己添加的以 Mz 后缀的方法上。
这个事情最终确定为:只要使用 TextInputLayout 包裹 TextInputEditText (谷歌推荐的组合,能够更好地适配 extra UI),在魅族部分系统上就会闪退。据说 TextInputLayout + AppCompatEditText。
我这边遇到更多魅族设备存在这个问题,包括 M5s。
大意就是说,魅族已经修复这个问题了,但由于固件下沉很慢,实际上效果很不尽人意。
按照现在的状况,大概率最终 28.0.0 正式版也会有这个问题,因为这事根本没法和谷歌反馈,总不能说:你们去买台魅族旧设备来试试,它们不兼容你们最新的 support 库 😥。
如果魅族的开发同学能够一起来写一个 workaround 提交给谷歌 support library,或许可以避免这个问题之后更大范围的影响。因为大家都是升级后遇到线上崩溃才后知后觉,而且还要探究折腾一番才知道是源于魅族系统的修改所致。
我这里有一个(可能的)解决方案,同时不会有log警告和功能不全:
问题是出在getHint()
这里。魅族可能如果mHint
和getHint()
不一致就会引起错误,所以我们在旧版本上面用反射获取mHint
的值。
package android.support.design.widget
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.widget.TextView
class FixedTextInputEditText(context: Context, attrs: AttributeSet?) : TextInputEditText(context, attrs) {
override fun getHint(): CharSequence? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return super.getHint()
}
return try {
getSuperHintHack()
} catch (e: Exception) {
super.getHint()
}
}
private fun getSuperHintHack(): CharSequence? {
val f = TextView::class.java.getDeclaredField("mHint")
f.isAccessible = true
return f.get(this) as? CharSequence
}
}
我这里有一个(可能的)解决方案,同时不会有log警告和功能不全: 问题是出在
getHint()
这里。魅族可能如果mHint
和getHint()
不一致就会引起错误,所以我们在旧版本上面用反射获取mHint
的值。package android.support.design.widget import android.content.Context import android.os.Build import android.util.AttributeSet import android.widget.TextView class FixedTextInputEditText(context: Context, attrs: AttributeSet?) : TextInputEditText(context, attrs) { override fun getHint(): CharSequence? { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { return super.getHint() } return try { getSuperHintHack() } catch (e: Exception) { super.getHint() } } private fun getSuperHintHack(): CharSequence? { val f = TextView::class.java.getDeclaredField("mHint") f.isAccessible = true return f.get(this) as? CharSequence } }
Greetings from Russian developers =) Thank you for this solution, it really works. I`am using MX6 as my main device and found that issue while testing new project. Only your type of workaround helped me.
我这里有一个(可能的)解决方案,同时不会有log警告和功能不全: 问题是出在
getHint()
这里。魅族可能如果mHint
和getHint()
不一致就会引起错误,所以我们在旧版本上面用反射获取mHint
的值。package android.support.design.widget import android.content.Context import android.os.Build import android.util.AttributeSet import android.widget.TextView class FixedTextInputEditText(context: Context, attrs: AttributeSet?) : TextInputEditText(context, attrs) { override fun getHint(): CharSequence? { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { return super.getHint() } return try { getSuperHintHack() } catch (e: Exception) { super.getHint() } } private fun getSuperHintHack(): CharSequence? { val f = TextView::class.java.getDeclaredField("mHint") f.isAccessible = true return f.get(this) as? CharSequence } }
And another thanks from Ukrainian developers :) Can confirm that it works. Great workaround!
package android.support.design.widget
import android.content.Context;
import android.os.Build;
import android.support.design.widget.TextInputEditText;
import android.util.AttributeSet;
import android.widget.TextView;
import java.lang.reflect.Field;
public class FixedTextInputEditText extends TextInputEditText {
public FixedTextInputEditText(Context context) {
super(context);
}
public FixedTextInputEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FixedTextInputEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public CharSequence getHint() {
String manufacturer = Build.MANUFACTURER.toUpperCase();
if (!manufacturer.contains("MEIZU") || Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return super.getHint();
}else{
try {
return getSuperHintHack();
}catch (Exception e){
return super.getHint();
}
}
}
private CharSequence getSuperHintHack() throws NoSuchFieldException, IllegalAccessException {
Field hintField = TextView.class.getDeclaredField("mHint");
hintField.setAccessible(true);
return (CharSequence) hintField.get(this);
}
}
Java version of the code from @mariotaku , code specific for Meizu devices only, I think it's safer this way, for the problems the java reflection can bring.
Good job @mariotaku
Thanks for the explanations and workarounds!
In my own project, I've tried out a different workaround, which doesn't use reflection. It's still a bit hacky though :smile:
TextInputEditText.mHint
will be the same as TextInputEditText.getHint()
)private void hackFixHintsForMeizu(TextInputEditText... editTexts) {
String manufacturer = Build.MANUFACTURER.toUpperCase(Locale.US);
if (manufacturer.contains("MEIZU")) {
for (TextInputEditText editText : editTexts) {
editText.setHintTextColor(Color.TRANSPARENT);
editText.setHint(editText.getHint());
}
}
}
把 TextInputEditTexts
换成 AppCompatEditText
可以避免这个问题
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="...">
<android.support.v7.widget.AppCompatEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.TextInputLayout>
This was just fixed in the material components for Android lib, see: https://github.com/material-components/material-components-android/pull/358
这个issue是不是已经被修复了?我在mx6上重现不出来
涉及的 Android API:(请尽可能全面的列举或描述涉及到的 API) TextInputLayout 内嵌 TextInputEditText 例如:
MX6 6.0
将
android.support.design.widget.TextInputEditText
更换为android.support.v7.widget.AppCompatEditText
不再闪退 相关 so 链接: https://stackoverflow.com/questions/51891415/nullpointerexception-on-meizu-devices-in-editor-updatecursorpositionmz/52001305