软键盘遮挡问题

3,536 阅读1分钟

1.gif

要实现如上图效果: 注意不是将页面整体滑上去,而是让页面上滑一部分,以达到不遮挡登录按钮的效果

实现思路:

  1. 监听键盘的弹起与收回
  2. 滑动

监听键盘的弹起与收回

首先在Manifest文件中对相应的Activity配置属性windowSoftInputMode,让Activity能够在键盘弹起和收回时有所响应。

<activity
    android:name=".ui.activitys.login.LoginPwdActivity"
    android:launchMode="singleTask"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateHidden|adjustPan" />

监听方法:

/**
 * Register soft input changed listener.
 *
 * @param activity The activity.
 * @param listener The soft input changed listener.
 */
public static void registerSoftInputChangedListener(final Activity activity,
                                                    final OnSoftInputChangedListener listener) {
    final int flags = activity.getWindow().getAttributes().flags;
    if ((flags & WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) != 0) {
        activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
    }
    final View contentView = activity.findViewById(android.R.id.content);
    sContentViewInvisibleHeightPre = getContentViewInvisibleHeight(activity);
    onSoftInputChangedListener = listener;
    onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (onSoftInputChangedListener != null) {
                int height = getContentViewInvisibleHeight(activity);
                if (sContentViewInvisibleHeightPre != height) {
                    onSoftInputChangedListener.onSoftInputChanged(height);
                    sContentViewInvisibleHeightPre = height;
                }
            }
        }
    };
    contentView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}

private static int getContentViewInvisibleHeight(final Activity activity) {
    final View contentView = activity.findViewById(android.R.id.content);
    final Rect outRect = new Rect();
    contentView.getWindowVisibleDisplayFrame(outRect);
    return contentView.getBottom() - outRect.bottom;
}

/**
 * Register soft input changed listener.
 *
 * @param activity The activity.
 */
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static void unregisterSoftInputChangedListener(final Activity activity) {
    final View contentView = activity.findViewById(android.R.id.content);
    contentView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
    onSoftInputChangedListener = null;
    onGlobalLayoutListener = null;
}

public interface OnSoftInputChangedListener {
    void onSoftInputChanged(int height);
}

滑动

利用view的topMargin来实现滑动动画

final ViewWrapper wrapper = new ViewWrapper(scrollview);
        SoftInputUtil.registerSoftInputChangedListener(this,
                new SoftInputUtil.OnSoftInputChangedListener() {
                    @Override
                    public void onSoftInputChanged(int height) {
                        HhixLog.e(TAG, SoftInputUtil.isSoftInputVisible(LoginPwdActivity.this) + ",height:" + height + ",tip bottom:" + tvTips.getBottom());
                        versionTv.setVisibility(SoftInputUtil.isSoftInputVisible(LoginPwdActivity.this) ? View.GONE : View.VISIBLE);
                        if (SoftInputUtil.isSoftInputVisible(LoginPwdActivity.this)) {
                            distance = height - (IMApplication.getInstance().screenSize.screenHeight - tipsBottom - UIUtils.dip2px(IMApplication.getInstance(), 24));
                            if (distance > 0) {
                                ivWelcome.setVisibility(View.INVISIBLE);
                                ObjectAnimator animator = ObjectAnimator.ofInt(wrapper, "topMargin", 0, -distance);
                                animator.setDuration(200).start();
                            }
                        } else {
                            if (distance > 0) {
                                ivWelcome.setVisibility(View.VISIBLE);
                                ObjectAnimator animator = ObjectAnimator.ofInt(wrapper, "topMargin", -distance, 0);
                                animator.setDuration(200).start();
                            }
                        }
                    }
                });

/**
 * Return whether soft input is visible.
 * <p>The minimum height is 200</p>
 *
 * @param activity The activity.
 * @return {@code true}: yes<br>{@code false}: no
 */
public static boolean isSoftInputVisible(final Activity activity) {
    return isSoftInputVisible(activity, 200);
}

/**
 * Return whether soft input is visible.
 *
 * @param activity             The activity.
 * @param minHeightOfSoftInput The minimum height of soft input.
 * @return {@code true}: yes<br>{@code false}: no
 */
public static boolean isSoftInputVisible(final Activity activity,
                                         final int minHeightOfSoftInput) {
    return getContentViewInvisibleHeight(activity) >= minHeightOfSoftInput;
}

class ViewWrapper {

    private View mTarget;
    private FrameLayout.LayoutParams mParams;

    public ViewWrapper(View target) {
        mTarget = target;
        mParams = (FrameLayout.LayoutParams) mTarget.getLayoutParams();
    }

    public void setTopMargin(int topMargin) {
        mParams.setMargins(0, topMargin, 0, 0);
        mTarget.setLayoutParams(mParams);
        mTarget.requestLayout();
    }

    public int getTopMargin() {
        return mParams.topMargin;
    }

}