核心点一:键盘监听:SoftKeyboardStateWatcher
package com.bjx.community_home.chat;
import android.content.Context;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewTreeObserver;
import java.util.LinkedList;
import java.util.List;
public class SoftKeyboardStateWatcher implements ViewTreeObserver.OnGlobalLayoutListener {
public interface SoftKeyboardStateListener {
void onSoftKeyboardOpened(int keyboardHeightInPx);
void onSoftKeyboardClosed();
}
private final List<SoftKeyboardStateListener> listeners = new LinkedList<>();
private final View activityRootView;
private int lastSoftKeyboardHeightInPx;
private boolean isSoftKeyboardOpened;
private Context mContext;
//使用时用这个构造方法
public SoftKeyboardStateWatcher(View activityRootView, Context context) {
this(activityRootView, false);
this.mContext = context;
}
private SoftKeyboardStateWatcher(View activityRootView) {
this(activityRootView, false);
}
private SoftKeyboardStateWatcher(View activityRootView, boolean isSoftKeyboardOpened) {
this.activityRootView = activityRootView;
this.isSoftKeyboardOpened = isSoftKeyboardOpened;
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
}
@Override
public void onGlobalLayout() {
final Rect r = new Rect();
activityRootView.getWindowVisibleDisplayFrame(r);
final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (!isSoftKeyboardOpened && heightDiff > dpToPx(mContext, 200)) {
isSoftKeyboardOpened = true;
notifyOnSoftKeyboardOpened(heightDiff);
} else if (isSoftKeyboardOpened && heightDiff < dpToPx(mContext, 200)) {
isSoftKeyboardOpened = false;
notifyOnSoftKeyboardClosed();
}
}
public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) {
this.isSoftKeyboardOpened = isSoftKeyboardOpened;
}
public boolean isSoftKeyboardOpened() {
return isSoftKeyboardOpened;
}
/**
* Default value is zero {@code 0}.
*
* @return last saved keyboard height in px
*/
public int getLastSoftKeyboardHeightInPx() {
return lastSoftKeyboardHeightInPx;
}
public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
listeners.add(listener);
}
public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
listeners.remove(listener);
}
/**
* @param keyboardHeightInPx 可能是包含状态栏的高度和底部虚拟按键的高度
*/
private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) {
this.lastSoftKeyboardHeightInPx = keyboardHeightInPx;
for (SoftKeyboardStateListener listener : listeners) {
if (listener != null) {
listener.onSoftKeyboardOpened(keyboardHeightInPx);
}
}
}
private void notifyOnSoftKeyboardClosed() {
for (SoftKeyboardStateListener listener : listeners) {
if (listener != null) {
listener.onSoftKeyboardClosed();
}
}
}
private static float dpToPx(Context context, float valueInDp) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}
}
kotlin使用:
//键盘监听
val softKeyBoardListener = SoftKeyboardStateWatcher(binding.root, this)
softKeyBoardListener.addSoftKeyboardStateListener(object : SoftKeyboardStateWatcher.SoftKeyboardStateListener {
override fun onSoftKeyboardClosed() {
}
override fun onSoftKeyboardOpened(keyboardHeightInPx: Int) {
if (keyboardHeightInPx > 100) {
mRecyclerView.scrollToPosition(adapter.list.size - 1)
}
}
})
采坑1:
LinearLayoutManager 设置 stackFromEnd = true 列表RecyclerView高度为match_parent 你会发现item条目都在下方(网上的这个方法用于解决RecyclerView随键盘自动上滑问题,没想到这是个坑啊)