如何避免部分视图被键盘顶起?锁定VideoView并让EditText随键盘上移
我之前也踩过这个坑——VideoView作为SurfaceView的子类,它的窗口是独立于Activity布局的,所以默认的adjustResize和adjustPan经常不生效。结合你的需求(直播图标、浏览量、VideoView固定,EditText随键盘上移),给你几个靠谱的解决方案:
方案1:调整布局结构+正确配置windowSoftInputMode
这是最直接的方法,核心是把VideoView固定在顶部区域,EditText放在底部,同时让Activity的窗口正确响应键盘弹出。
步骤1:配置Activity的窗口属性
在AndroidManifest.xml里给对应的Activity添加:
<activity android:name=".YourVideoActivity" android:windowSoftInputMode="adjustResize|stateHidden" />
adjustResize会让Activity布局重新计算可用空间,stateHidden让键盘默认隐藏,避免启动时就弹出。
步骤2:用ConstraintLayout构建布局
把VideoView和相关控件(直播图标、浏览量)放在一个固定位置的容器里,EditText绑定在底部:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <!-- 固定在顶部的Video容器 --> <FrameLayout android:id="@+id/video_container" android:layout_width="match_parent" android:layout_height="240dp" <!-- 固定高度,或者用0dp配合比例 --> app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"> <VideoView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- 直播图标 --> <ImageView android:id="@+id/live_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_live_badge" android:layout_marginStart="16dp" android:layout_marginTop="16dp"/> <!-- 浏览量计数器 --> <TextView android:id="@+id/view_count_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="1.2万次观看" android:textColor="#FFFFFF" android:background="#80000000" android:paddingHorizontal="8dp" android:paddingVertical="4dp" android:layout_gravity="bottom|end" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp"/> </FrameLayout> <!-- 底部的EditText,会随键盘上移 --> <EditText android:id="@+id/comment_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="说点什么..." android:paddingHorizontal="16dp" android:paddingVertical="12dp" android:background="#F5F5F5" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout>
这个布局里,Video容器被约束在父布局顶部,高度固定,所以键盘弹出时,底部的EditText会被顶上去,而Video区域位置完全不变。
方案2:替换VideoView为TextureView(解决SurfaceView的特殊机制)
如果方案1还是不行,那就是SurfaceView的独立窗口导致的——它不受Activity布局调整的影响。这时候可以用TextureView代替VideoView,因为TextureView是普通View的子类,会完全遵守布局规则。
布局中替换为TextureView
<TextureView android:id="@+id/texture_video" android:layout_width="match_parent" android:layout_height="match_parent" />
代码中用MediaPlayer播放视频
TextureView textureView = findViewById(R.id.texture_video); textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { private MediaPlayer mediaPlayer; @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { Surface surfaceObj = new Surface(surface); mediaPlayer = new MediaPlayer(); try { // 设置视频数据源,可以是本地路径或网络URL mediaPlayer.setDataSource(getApplicationContext(), Uri.parse("your_video_url")); mediaPlayer.setSurface(surfaceObj); mediaPlayer.setLooping(true); // 可选,循环播放 mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(MediaPlayer::start); } catch (IOException e) { e.printStackTrace(); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { // 可以在这里调整视频比例 if (mediaPlayer != null) { float videoRatio = (float) mediaPlayer.getVideoWidth() / mediaPlayer.getVideoHeight(); float viewRatio = (float) width / height; Matrix matrix = new Matrix(); matrix.setScale(videoRatio / viewRatio, 1, width / 2f, height / 2f); textureView.setTransform(matrix); } } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { if (mediaPlayer != null) { mediaPlayer.stop(); mediaPlayer.release(); } return true; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) {} });
替换后,TextureView会像普通View一样响应adjustResize,EditText上移的同时,Video区域完全固定。
方案3:手动监听键盘事件调整EditText(备选)
如果以上方案都不适用,可以手动监听键盘的弹出/收起,动态调整EditText的位置:
final View activityRootView = findViewById(android.R.id.content); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect r = new Rect(); activityRootView.getWindowVisibleDisplayFrame(r); int screenHeight = activityRootView.getRootView().getHeight(); int keyboardHeight = screenHeight - r.bottom; // 键盘弹出时,调整EditText的translationY if (keyboardHeight > screenHeight * 0.15) { // 判定键盘弹出的阈值 findViewById(R.id.comment_input).setTranslationY(-keyboardHeight); } else { findViewById(R.id.comment_input).setTranslationY(0); } } });
这个方法通过计算屏幕可用区域的变化来判断键盘状态,然后手动移动EditText,适合一些复杂布局场景。
内容的提问来源于stack exchange,提问作者einschneidend

