软键盘适配
软键盘有时会导致页面布局体验差,解决方法之一是最外层嵌套ScrollView,马马虎虎,下面是最优解
原文地址软键盘适配
public class KeyboardLayout extends FrameLayout { private KeyboardLayoutListener mListener; private boolean mIsKeyboardActive = false; //输入法是否激活 private int mKeyboardHeight = 0; // 输入法高度 public KeyboardLayout(Context context) { this(context, null, 0); } public KeyboardLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public KeyboardLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 监听布局变化 getViewTreeObserver().addOnGlobalLayoutListener(new KeyboardOnGlobalChangeListener()); } public void setKeyboardListener(KeyboardLayoutListener listener) { mListener = listener; } public KeyboardLayoutListener getKeyboardListener() { return mListener; } public boolean isKeyboardActive() { return mIsKeyboardActive; } /** * 获取输入法高度 * * @return */ public int getKeyboardHeight() { return mKeyboardHeight; } public interface KeyboardLayoutListener { /** * @param isActive 输入法是否激活 * @param keyboardHeight 输入法面板高度 */ void onKeyboardStateChanged(boolean isActive, int keyboardHeight); } private class KeyboardOnGlobalChangeListener implements ViewTreeObserver.OnGlobalLayoutListener { int mScreenHeight = 0; private int getScreenHeight() { if (mScreenHeight > 0) { return mScreenHeight; } mScreenHeight = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay().getHeight(); return mScreenHeight; } @Override public void onGlobalLayout() { Rect rect = new Rect(); // 获取当前页面窗口的显示范围 ((Activity) getContext()).getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); int screenHeight = getScreenHeight(); int keyboardHeight = screenHeight - rect.bottom; // 输入法的高度 boolean isActive = false; if (Math.abs(keyboardHeight) > screenHeight / 4) { isActive = true; // 超过屏幕五分之一则表示弹出了输入法 mKeyboardHeight = keyboardHeight; } mIsKeyboardActive = isActive; if (mListener != null) { mListener.onKeyboardStateChanged(isActive, keyboardHeight); } } } }
<?xml version="1.0" encoding="utf-8"?> <com.maweiqi.recyclerview.KeyboardLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.widget.NestedScrollView android:id="@+id/scroll_view" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/ll_parent" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="200dp" android:background="#0000ff"/> <EditText android:id="@+id/account" android:layout_width="match_parent" android:layout_height="match_parent"/> <EditText android:layout_width="match_parent" android:layout_height="match_parent"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="确定"/> </LinearLayout> </android.support.v4.widget.NestedScrollView> </com.maweiqi.recyclerview.KeyboardLayout>
工具类
public class KeyboardUtil { private static final String TAG = "KeyboardUtil"; public static void assistActivity(Activity activity, int viewId) { new KeyboardUtil(activity, viewId); } private View mChildOfContent; private NestedScrollView mScrollView; private RelativeLayout.LayoutParams relativeLayoutParams; private KeyboardUtil(Activity activity, int viewId) { FrameLayout content = (FrameLayout) activity .findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); mScrollView = (NestedScrollView) content.findViewById(viewId); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); } private void possiblyResizeChildOfContent() { int contentHeight = mChildOfContent.getRootView().getHeight(); int curDisplayHeight = computeUsableHeight(); if (contentHeight - curDisplayHeight > contentHeight / 4) { Log.e(TAG, "possiblyResizeChildOfContent: 1" ); mScrollView.scrollTo(0,600); // mScrollView.fullScroll(ScrollView.FOCUS_DOWN); } else { Log.e(TAG, "possiblyResizeChildOfContent: 2" ); } } /** * 获取屏幕可显示区域高度 * * @return */ private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return r.height(); } }
清单文件配置
android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
activity调用
//键盘不遮挡按钮 private void setScroll() { KeyboardUtil.assistActivity(this, R.id.scroll_view); //这个是别人给我的工具类,只用这个会有 parent.setOnTouchListener(new View.OnTouchListener() { //parent为Editext外面那层布局 @Override public boolean onTouch(View v, MotionEvent event) { parent.setFocusable(true); parent.setFocusableInTouchMode(true); parent.requestFocus(); InputMethodManager imm = (InputMethodManager) MainActivity.this .getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(account.getWindowToken(), 0); //隐藏键盘,account为Editext,随便一个就好 return false; } }); scroll.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { //scroll为parent外面那层布局()最好用NestedScrollView,ScrollView会有版本问题 @Override public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { v.scrollTo(0,450); //这个是滑动距离,随便大一点就好 } }); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现