You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免部分视图被键盘顶起?锁定VideoView并让EditText随键盘上移

解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:39:55