web-dev-qa-db-ja.com

ウィンドウソフト入力モードConstraintLayout

以前はソフト入力モードで問題はありませんでしたが、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>

ここに理解のための写真があります:

enter image description here

何が起こっているのか理解するにはどうすればよいですか?以前にViewTreeObserverを使用しました。

U.P.D。

私の目標は

enter image description here

キーボードが表示されたときにコンテンツが上に移動することを期待していましたが、代わりにキーボードが重なっています。

17
Scrobot

すべては実際にはレイアウトの構築方法で意図したとおりに機能します。マージンは固定距離であるため、UIは小さい画面には高すぎるだけです。レイアウトを変更して、小さなレイアウトにさらに適応させる必要があります-不要なビュー(ロゴなど)を削除済みとしてマークします(ConstraintLayoutは、「削除された」ビューを本質的に単一のポイントに折りたたまれたものと見なします。機能)、または一部のマージン寸法をより小さい値に変更します。

これを構築する通常の方法は、ハードマージンの代わりに バイアス制約 または ガイドライン を使用することです。バイアスまたはガイドライン(パーセントモード)を使用すると、寸法の変化によりよく反応する「スプリング」のような動作をより多く持つことができます。通常、レイアウトはハードマージンとバイアス/ガイドラインを組み合わせたものになります。

要約すると、オプションは次のとおりです。

  • レイアウトを変更してバイアス/ガイドライン(パーセント)制約を使用し、より応答性の高いレイアウトにする
  • キーボードを検出したときに一部のビューをGONEとしてマークします
  • その場で他のいくつかの値を変更します(フォントサイズ、マージン値...)
  • または、このケースを処理するための別のレイアウトファイルを作成します
13
Nicolas Roard

フラグメントがどのアクティビティにあるかはわかりませんが、たとえばInitChatActivityにある場合は、マニフェストにadjustResizeを追加して、ConstraintLayoutをScrollViewまたはNestedScrollViewでラップします。

Android:windowSoftInputMode="stateHidden|adjustResize"
6
r1m

私はあなたと同じ問題に遭遇しました、私たちはAndroid:windowSoftInputMode="stateAlwaysHidden|adjustResize" の中に AndroidManifest.xmlですが、実際にはアプリはadjustPanのような結果を表示し、コンテンツはソフトキーボードの上に表示されません。だから私はadjustResizeをプログラムで設定し、この問題をうまく解決しました:

この行をonCreateに追加するだけです:

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
3
drakeet