要实现如上图效果:
注意不是将页面整体滑上去,而是让页面上滑一部分,以达到不遮挡登录按钮的效果
实现思路:
- 监听键盘的弹起与收回
- 滑动
监听键盘的弹起与收回
首先在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;
}
}