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

如何在RecyclerView的onBindViewHolder中设置VideoView高度为200dp?

我之前也踩过这个坑!RecyclerView里的VideoView因为自身的测量逻辑和列表项复用的特性,直接用setLayoutParams()或者XML设高度经常会被覆盖,给你几个亲测有效的方案:

方案1:给VideoView套一层父容器(最简单直接)

VideoView会默认根据视频的宽高比自动调整自身大小,直接给它设高度很容易被这个逻辑冲掉。解决思路是用一个容器把它包起来,固定容器的高度,再让VideoView填充满容器,通过scaleType控制视频的拉伸/压缩方式。

示例XML布局

<!-- 父容器固定200dp高度 -->
<FrameLayout
    android:id="@+id/video_container"
    android:layout_width="match_parent"
    android:layout_height="200dp">

    <VideoView
        android:id="@+id/video_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop" /> 
    <!-- scaleType可选值:
         fitXY = 强制拉伸填满容器
         centerCrop = 保持比例裁剪填充满
         fitCenter = 保持比例居中显示(会留黑边)
    -->
</FrameLayout>

代码中动态调整(如果需要)

如果要在onBindViewHolder里动态改高度,直接给父容器设置参数就行:

FrameLayout videoContainer = holder.itemView.findViewById(R.id.video_container);
ViewGroup.LayoutParams params = videoContainer.getLayoutParams();
// 把200dp转成像素值,也可以提前在dimens.xml里定义
params.height = getResources().getDimensionPixelSize(R.dimen.video_height_200dp);
videoContainer.setLayoutParams(params);
方案2:自定义VideoView,重写测量逻辑

如果不想套容器,可以自定义一个VideoView,强制它使用我们指定的高度,忽略视频的默认比例约束。

自定义View代码

public class FixedHeightVideoView extends VideoView {
    private int mFixedHeight;

    public FixedHeightVideoView(Context context) {
        super(context);
    }

    public FixedHeightVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 支持从XML属性读取固定高度
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FixedHeightVideoView);
        mFixedHeight = a.getDimensionPixelSize(R.styleable.FixedHeightVideoView_fixedHeight, 0);
        a.recycle();
    }

    // 提供动态设置高度的方法
    public void setFixedHeight(int height) {
        mFixedHeight = height;
        requestLayout();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mFixedHeight > 0) {
            // 强制使用我们指定的高度,宽度跟随父布局
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(mFixedHeight, MeasureSpec.EXACTLY);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

使用方式

在XML里直接用自定义View:

<com.yourpackage.FixedHeightVideoView
    android:id="@+id/video_view"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:fixedHeight="200dp" />

或者在onBindViewHolder里动态设置:

FixedHeightVideoView videoView = holder.itemView.findViewById(R.id.video_view);
int fixedHeight = getResources().getDimensionPixelSize(R.dimen.video_height_200dp);
videoView.setFixedHeight(fixedHeight);
videoView.setVideoPath(yourVideoUrl);
方案3:用TextureView替代VideoView(最灵活)

VideoView的底层是TextureView,但它的封装太死,不如直接用TextureView配合MediaPlayer来控制,完全掌握尺寸的主动权。

示例布局

<TextureView
    android:id="@+id/texture_view"
    android:layout_width="match_parent"
    android:layout_height="200dp" />

代码实现(关键部分)

// 在onBindViewHolder里初始化播放逻辑
TextureView textureView = holder.itemView.findViewById(R.id.texture_view);
MediaPlayer mediaPlayer = new MediaPlayer();
try {
    mediaPlayer.setDataSource(yourVideoUrl);
    mediaPlayer.setSurface(new Surface(textureView.getSurfaceTexture()));
    mediaPlayer.prepareAsync();
    mediaPlayer.setOnPreparedListener(mp -> {
        mp.start();
        // 还可以在这里通过矩阵调整视频的显示比例,比如拉伸、裁剪
    });
} catch (IOException e) {
    e.printStackTrace();
}

// 重要!在列表项复用时释放资源,避免内存泄漏
@Override
public void onViewRecycled(@NonNull ViewHolder holder) {
    super.onViewRecycled(holder);
    if (holder.mediaPlayer != null) {
        holder.mediaPlayer.stop();
        holder.mediaPlayer.release();
        holder.mediaPlayer = null;
    }
}

注意事项

不管用哪种方案,都要处理RecyclerView的复用问题:在onViewRecycled或者onBindViewHolder里重置视频的状态(停止播放、释放资源),不然复用的时候会出现视频串流、卡顿甚至崩溃的情况。

内容的提问来源于stack exchange,提问作者Arpit Gupta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:28:38