我收到许多与密码可见性相关的崩溃。 更奇怪的是它在某些设备上崩溃并非全部。
我在诺基亚5,三星音符4和s7,Honor 5C和9,Redmi Note 4和4,Moto E和G play和moto M都进行了测试。
JavaCode
EditText loEtPassword = (EditText) findViewById(R.id.etPassword);
loEtPassword.setTransformationMethod(new PasswordTransformationMethod()); // Java internal class.
loEtPassword.setOnEditorActionListener(new DoneOnEditorActionListener(loBtnLogin)); // custom class.
验证
public static class LoginUser {
public String lsEmail, lsPassword, lsIMEINumber, lsJsonParameter;
}
LoginUser loLoginUser = new LoginUser();
loLoginUser.lsEmail = loEtEmail.getText().toString().trim();
loLoginUser.lsPassword = loEtPassword.getText().toString();
if (validate(loLoginUser)) {
//cont...
}
private boolean validate(LoginUser foLoginUser) {
final EditText loEtPassword = (EditText) findViewById(R.id.etPassword);
boolean lbIsValid = true;
if (foLoginUser.lsPassword.length() <= 0) {
loEtPassword.setError("Please enter Password");
loEtPassword.requestFocus();
lbIsValid = false;
}
return lbIsValid;
}
XML文件
<android.support.design.widget.TextInputLayout
android:id="@+id/ilPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="@color/textColorGray"
app:hintEnabled="false"
app:passwordToggleEnabled="true"
app:passwordToggleTint="@color/textColorGray">
<EditText
android:id="@+id/etPassword"
style="@style/editTextStyle"
android:layout_marginBottom="@dimen/MarginBetweenView"
android:backgroundTint="@color/textColorGray"
android:drawableLeft="@drawable/ic_password"
android:drawableStart="@drawable/ic_password"
android:drawablePadding="@dimen/MarginBetweenInnerView"
android:hint="@string/HINT_PASSWORD"
android:imeOptions="actionDone"
android:inputType="textEmailAddress" />
</android.support.design.widget.TextInputLayout>
设计
摇篮
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "com.packageName"
minSdkVersion 14
targetSdkVersion 25
multiDexEnabled true
versionName '7.2'
versionCode 96
}
dexOptions {
javaMaxHeapSize "4g"
preDexLibraries = false
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
}
}
productFlavors {
}
}
dependencies {
compile files('libs/gcm.jar')
compile 'com.android.support:support-v4:27.1.0'
compile 'com.android.support:appcompat-v7:27.1.0'
compile 'com.android.support:design:27.1.0'
compile 'com.google.android.gms:play-services-analytics:11.8.0'
compile('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') {
transitive = true
}
compile 'com.google.firebase:firebase-core:11.8.0'
}
apply plugin: 'com.google.gms.google-services'
参考快照 - 过去24小时内发生了21次崩溃。
崩溃日志
Caused by java.lang.NullPointerException
Attempt to invoke virtual method 'void android.support.design.widget.CheckableImageButton.setChecked(boolean)' on a null object reference arrow_right
android.support.design.widget.TextInputLayout.passwordVisibilityToggleRequested (Unknown Source:1339)
android.support.design.widget.TextInputLayout.onRestoreInstanceState (Unknown Source:1033)
android.view.View.dispatchRestoreInstanceState (View.java:15777)
android.view.ViewGroup.dispatchRestoreInstanceState (ViewGroup.java:3233)
android.support.design.widget.TextInputLayout.dispatchRestoreInstanceState (Unknown Source:1041)
android.view.ViewGroup.dispatchRestoreInstanceState (ViewGroup.java:3239)
android.view.ViewGroup.dispatchRestoreInstanceState (ViewGroup.java:3239)
android.view.ViewGroup.dispatchRestoreInstanceState (ViewGroup.java:3239)
android.view.ViewGroup.dispatchRestoreInstanceState (ViewGroup.java:3239)
android.view.View.restoreHierarchyState (View.java:15755)
com.android.internal.policy.PhoneWindow.restoreHierarchyState (PhoneWindow.java:2106)
android.app.Activity.onRestoreInstanceState (Activity.java:1098)
android.app.Activity.performRestoreInstanceState (Activity.java:1053)
android.app.Instrumentation.callActivityOnRestoreInstanceState (Instrumentation.java:1175)
android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2714)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2802)
android.app.ActivityThread.-wrap12 (ActivityThread.java)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1549)
android.os.Handler.dispatchMessage (Handler.java:102)
android.os.Looper.loop (Looper.java:163)
android.app.ActivityThread.main (ActivityThread.java:6361)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:904)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:794)
任何人都可以帮助如何防止这个错误吗?
我需要升级targetSdkVersion
吗?
如果有任何替代解决方案,请建议,因为如果我更改目标sdk版本,那么我必须在我的应用程序中更新大量代码。
答案 0 :(得分:1)
我通过简单地将EditText的inputType
(或我的案例中的TextInputEditText)更改为textPassword
来解决这个问题。所以你应该试试这个:
<EditText
android:id="@+id/etPassword"
...
android:inputType="textPassword" />
我认为您并不是要将其设置为textEmailAddress
。
答案 1 :(得分:1)
由于以上答案均无济于事,所以我自己花了一些时间解决此问题。我发现方向改变时可能会发生崩溃(也许还有更多情况)。
最初,使用反射解决方案很难看。提取指示密码可见性的布尔值,并在方向更改后切换可见性。但是后来我注意到,即使不再出现崩溃,我的解决方案也不是解决此崩溃的原因。因此,我开始逐步地对代码进行注释,以查找所谓的 solution 解决方案。
解决方案是修改AndroidManifest。意想不到的。
我注意到添加android:configChanges
属性可以解决此问题。可悲的是,我无法确切解释它如何解决该问题。解决方案是偶然发现的。如果orientation
的值不能解决问题,请尝试different values。
<activity
android:configChanges="orientation"
android:name="com.example.activity.LoginActivity"
android:screenOrientation="sensor" />
对于较旧版本的SDK,我必须扩展TextInputLayout
才能解决此问题。使用configChanges
修复无法在此处解决问题。
此解决方案适用于新旧设备,因此我建议坚持使用它。
import com.google.android.material.textfield.TextInputLayout;
public class PasswordTextInputLayout extends TextInputLayout {
public PasswordTextInputLayout(Context context) {
super(context);
}
public PasswordTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PasswordTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* We have to change "password visibility toggle enabled"
* state twice in order to recreate private {@link TextInputLayout#passwordToggleView}.
* Calling {@link TextInputLayout#setPasswordVisibilityToggleEnabled(boolean)}
* we also invoke {@link TextInputLayout#updatePasswordToggleView}.
* Which recreates passwordToggleView if it is equals to null.
* UI performance is not affected.
*
* @param state saved when screen configuration has changed (e.g. orientation change).
*/
@Override
protected void onRestoreInstanceState(Parcelable state) {
setPasswordVisibilityToggleEnabled(false);
setPasswordVisibilityToggleEnabled(true);
super.onRestoreInstanceState(state);
}
}
简单。代替标签<com.google.android.material.textfield.TextInputLayout>
,请使用<com.example.view.PasswordTextInputLayout>
。
<com.example.view.PasswordTextInputLayout
... >
<com.google.android.material.textfield.TextInputEditText
...
/>
</com.example.view.PasswordTextInputLayout>
好像是活动或片段将其状态保存到Bundle
后(即您在savedInstanceState
中看到的Activity#onCreate
),后来又用它来还原状态TextInputLayout
失败了正确地做。 passwordToggleView
未正确还原。一种解决方案是在可见性切换之前,添加TextInputLayout#onRestoreInstanceState
方法调用updatePasswordToggleView
或进行适当的更改以重新创建passwordToggleView
。
答案 2 :(得分:0)
使用以下代码:
if(loEtPassword.getText().toString().trim().equalsIgnoreCase("")){
loEtPassword.setError("Please enter Password");
loEtPassword.requestFocus();
lbIsValid = false;
}