早期软输入模式没有问题,但在包含ConstraintLayout
后,当键盘出现时,片段内容不会向上移动。
清单
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ru.pinspb.pinsupport">
<uses-feature
android:name="android.software.leanback"
android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission
android:name="ru.pinspb.pinsupport.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="ru.pinspb.pinsupport.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:name=".PinApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme.NoActionBar">
<activity
android:name=".auth.ui.HomeActivity"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".front.ui.FrontActivity"
android:launchMode="singleTop" />
<activity
android:name=".chats.ui.InitChatActivity"
android:launchMode="singleTop"
android:windowSoftInputMode="stateHidden" />
</application>
</manifest>
片段
public class AuthFragment extends Fragment implements ValidationListener {
private static final String TAG = AuthFragment.class.toString();
// UI references.
@NotEmpty @Email @BindView(R.id.email) EditText email;
@NotEmpty @BindView(R.id.password) EditText password;
@BindView(R.id.auth_sign_in) Button signIn;
@BindView(R.id.remember_me) CheckBox remember;
@BindView(R.id.forgot) TextView forgot;
@BindView(R.id.error) TextView errorField;
@Inject @ApplicationContext
Context context;
private Validator validator;
private onAuthenticateEventListener authenticatableEventListener;
private String error = Constants.EMPTY_STRING;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
authenticatableEventListener = (onAuthenticateEventListener) activity;
} catch (ClassCastException e) {
e.printStackTrace();
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View render = inflater.inflate(R.layout.fragment_auth, container, false);
ButterKnife.bind(this, render);
final View activityRootView = render.findViewById(R.id.activity_root);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > Helper.dpToPx(container.getContext(), 200)) { // if more than 200 dp, it's probably a keyboard...
Log.d(TAG, "heightDiff: " + heightDiff);
}
});
return render;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
errorField.setText(this.error);
if(this.error.equals(Constants.EMPTY_STRING)) {
errorField.setVisibility(View.GONE);
} else {
errorField.setVisibility(View.VISIBLE);
}
// Set up the login form.
password.setOnEditorActionListener((textView, id, keyEvent) -> {
if (id == R.id.login || id == EditorInfo.IME_NULL) {
attemptLogin();
return true;
}
return false;
});
validator = new Validator(this);
validator.setValidationListener(this);
signIn.setOnClickListener(v -> validator.validate());
}
/**
* Attempts to sign in or register the account specified by the login form.
* If there are form errors (invalid email, missing fields, etc.), the
* errors are presented and no actual login attempt is made.
*/
private void attemptLogin() {
// Store values at the time of the login attempt.
String email = this.email.getText().toString();
String password = this.password.getText().toString();
Bundle bundle = new Bundle();
bundle.putString("email", email);
bundle.putString("password", password);
authenticatableEventListener.sendAuthRequest(bundle);
}
@Override
public void onValidationSucceeded() {
attemptLogin();
}
@Override
public void onValidationFailed(List<ValidationError> errors) {
for (ValidationError error : errors) {
Log.d(TAG, "onValidationFailed: " + error.getCollatedErrorMessage(context));
View view = error.getView();
String message = error.getCollatedErrorMessage(context);
// Display error messages ;)
if (view instanceof EditText) {
((EditText) view).setError(message);
} else {
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
}
}
public void setErrors(String text) {
this.error = text;
}
public interface onAuthenticateEventListener {
void sendAuthRequest(Bundle params);
void showErrors(String error);
}
}
布局
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:background="@color/bg"
android:id="@+id/activity_root">
<!-- Login progress -->
<ProgressBar
android:id="@+id/login_progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="@+id/activity_root"
tools:layout_constraintLeft_creator="1"
app:layout_constraintTop_toTopOf="@+id/activity_root"
tools:layout_constraintTop_creator="1"
app:layout_constraintRight_toLeftOf="@+id/activity_root"
tools:layout_constraintRight_creator="1"
app:layout_constraintBottom_toTopOf="@+id/activity_root"
tools:layout_constraintBottom_creator="1" />
<ImageView
android:layout_width="120dp"
android:layout_height="80dp"
android:id="@+id/logo"
app:srcCompat="@drawable/logo_pin_support"
android:contentDescription="@string/contentDiscription"
app:layout_constraintLeft_toLeftOf="@+id/activity_root"
tools:layout_constraintLeft_creator="1"
app:layout_constraintTop_toTopOf="@+id/activity_root"
android:layout_marginTop="56dp"
tools:layout_constraintTop_creator="1"
app:layout_constraintRight_toRightOf="@+id/activity_root"
tools:layout_constraintRight_creator="1" />
<EditText
android:id="@+id/email"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/auth.email"
android:inputType="textEmailAddress"
android:maxLines="1"
android:drawablePadding="10dp"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:textSize="@dimen/auth.sizes"
android:autoLink="none"
android:focusableInTouchMode="true"
tools:ignore="RtlHardcoded"
app:layout_constraintLeft_toLeftOf="@+id/activity_root"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@+id/error"
android:layout_marginTop="8dp"
app:layout_constraintRight_toRightOf="@+id/activity_root"
android:layout_marginEnd="16dp"
app:layout_constraintHorizontal_bias="0.56" />
<EditText
android:id="@+id/password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/auth.password"
android:imeActionId="@+id/login"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:drawablePadding="10dp"
android:textSize="@dimen/auth.sizes"
android:paddingTop="20dp"
android:paddingBottom="20dp"
tools:ignore="MissingConstraints,RtlHardcoded"
app:layout_constraintLeft_toLeftOf="@+id/email"
app:layout_constraintTop_toBottomOf="@+id/email"
app:layout_constraintRight_toRightOf="@+id/email"
app:layout_constraintHorizontal_bias="0.0" />
<TextView
android:text="@string/auth.title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="27sp"
android:textColor="@color/greyish_brown"
android:id="@+id/textView"
tools:ignore="MissingConstraints"
app:layout_constraintLeft_toLeftOf="@+id/activity_root"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@+id/logo"
android:layout_marginTop="24dp"
app:layout_constraintRight_toRightOf="@+id/activity_root"
android:layout_marginEnd="16dp" />
<CheckBox
android:text="@string/auth.remember"
android:layout_width="0dp"
android:layout_height="32dp"
android:id="@+id/remember_me"
style="@android:style/Widget.Holo.Light.CompoundButton.CheckBox"
android:checked="true"
android:textSize="@dimen/auth.sizes"
android:textColor="@color/warm_grey"
app:layout_constraintLeft_toLeftOf="@+id/activity_root"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@+id/password"
android:layout_marginTop="27dp"
app:layout_constraintRight_toRightOf="@+id/activity_root"
android:layout_marginEnd="16dp"
app:layout_constraintHorizontal_bias="0.0" />
<Button
android:text="@string/auth.submit"
android:layout_width="152dp"
android:layout_height="51dp"
android:id="@+id/auth_sign_in"
android:background="@drawable/round_button"
tools:ignore="MissingConstraints"
android:textColor="@color/white"
android:textSize="@dimen/auth.sizes"
app:layout_constraintLeft_toLeftOf="@+id/activity_root"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@+id/remember_me"
android:layout_marginTop="46dp"
app:layout_constraintRight_toRightOf="@+id/activity_root"
android:layout_marginEnd="16dp" />
<TextView
android:text="@string/auth.forgot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/forgot"
android:textColor="@color/pinkish_grey"
app:layout_constraintLeft_toLeftOf="@+id/auth_sign_in"
app:layout_constraintTop_toBottomOf="@+id/auth_sign_in"
android:layout_marginTop="16dp"
app:layout_constraintRight_toRightOf="@+id/auth_sign_in" />
<TextView
android:text="error"
android:layout_width="wrap_content"
android:layout_height="16dp"
android:id="@+id/error"
android:textColor="@color/lipstick"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="@+id/textView"
app:layout_constraintTop_toBottomOf="@+id/textView"
android:layout_marginTop="16dp"
app:layout_constraintRight_toRightOf="@+id/textView" />
</android.support.constraint.ConstraintLayout>
以下是理解的图片:
我如何理解发生了什么?我之前使用过ViewTreeObserver。
U.P.D。
我的目标是
我预计当键盘出现时内容会向上移动,但键盘会重叠。
答案 0 :(得分:11)
所有内容实际上都与您的布局构建方式一致 - 边距是固定距离,因此您的UI对于较小的屏幕来说太高了。您需要修改布局以更好地适应小布局 - 将不必要的视图(例如徽标)标记为已消失(ConstraintLayout将“已消失”视图视为折叠为单个点,实质上是 - 因此布局仍然工作),或将一些边距尺寸更改为较小的值。
构建此功能的常用方法是使用bias constraints或guidelines,而不是硬边距。使用偏差或指南(以百分比模式)将允许您具有更多类似“弹簧”的行为,以更好地对尺寸变化做出反应。通常情况下,布局将是硬边距和偏见/指导的混合。
总而言之,您的选择是:
GONE
答案 1 :(得分:6)
我不确定你的片段所处的Activity是什么,但是如果它在例如InitChatActivity中,只需将adjustResize添加到清单中,并将ConstraintLayout包装在ScrollView或NestedScrollView中:
android:windowSoftInputMode="stateHidden|adjustResize"
答案 2 :(得分:3)
我遇到了同样的问题,我们在android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
中声明了AndroidManifest.xml
,但实际上App显示的结果如adjustPan
,内容已经消失在软的顶部键盘。所以我以编程方式设置adjustResize
,成功地解决了这个问题:
只需将此行添加到onCreate
:
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);