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

如何将VideoView转为圆形?及实现全屏播放后裁剪为圆形的方法

嘿,这两个关于VideoView的问题我刚好在项目里处理过,给你分享下靠谱的实现方案:

问题1:如何将VideoView转换为圆形?

VideoView本身是矩形控件,没法直接改成圆形,我们得通过画布裁剪或者遮罩层的方式来实现,下面是两种常用的可靠方案:

方案一:自定义容器裁剪(兼容全版本)

创建一个自定义的FrameLayout子类,在绘制时裁剪画布为圆形,把VideoView放在这个容器里就行:

public class CircleVideoContainer extends FrameLayout {
    private Path mCirclePath;
    private RectF mCircleRect;
    private boolean mIsCircle = true; // 控制是否裁剪为圆形

    public CircleVideoContainer(Context context) {
        super(context);
        init();
    }

    public CircleVideoContainer(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mCirclePath = new Path();
        mCircleRect = new RectF();
        setWillNotDraw(false); // 必须开启,否则onDraw不会执行
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 取宽高中的最小值做直径,保证是正圆
        int diameter = Math.min(w, h);
        mCircleRect.set(
            (w - diameter) / 2,
            (h - diameter) / 2,
            (w + diameter) / 2,
            (h + diameter) / 2
        );
        mCirclePath.addOval(mCircleRect, Path.Direction.CW);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mIsCircle) {
            canvas.clipPath(mCirclePath); // 裁剪出圆形区域
        }
        super.onDraw(canvas);
    }

    // 提供开关方法,方便后续动态切换
    public void setCircleMode(boolean isCircle) {
        mIsCircle = isCircle;
        invalidate();
    }
}

然后在布局里这样用:

<com.yourpackage.CircleVideoContainer
    android:id="@+id/video_container"
    android:layout_width="250dp"
    android:layout_height="250dp"
    android:layout_gravity="center">

    <VideoView
        android:id="@+id/video_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"/>

</com.yourpackage.CircleVideoContainer>

方案二:遮罩层实现(API 16+)

给VideoView设置一个圆形的遮罩层,通过PorterDuff混合模式只显示圆内的内容:

// 创建圆形遮罩
ShapeDrawable circleMask = new ShapeDrawable(new OvalShape());
circleMask.getPaint().setColor(Color.BLACK);
// 用DST_IN模式,只保留遮罩覆盖的区域
circleMask.getPaint().setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

// 给VideoView设置遮罩
videoView.setForeground(circleMask);

如果是API 23以上,还可以更简单:

  1. 新建一个圆形的drawable文件circle_background.xml:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@android:color/transparent"/>
</shape>
  1. 给VideoView设置背景并开启裁剪:
videoView.setBackgroundResource(R.drawable.circle_background);
videoView.setClipToOutline(true);

注意:不管哪种方案,都要保证VideoView的宽高一致,否则会变成椭圆;如果需要兼容低版本,优先用自定义容器的方案。

问题2:全屏播放后一段时间裁剪为圆形

这个需求需要分两步实现:先全屏播放,延迟指定时间后切换为圆形显示,结合上面的自定义容器方案,具体步骤如下:

1. 实现全屏播放逻辑

private void enterFullscreen() {
    // 隐藏状态栏和导航栏
    getWindow().setFlags(
        WindowManager.LayoutParams.FLAG_FULLSCREEN,
        WindowManager.LayoutParams.FLAG_FULLSCREEN
    );
    // 隐藏ActionBar(如果有的话)
    if (getSupportActionBar() != null) {
        getSupportActionBar().hide();
    }

    // 把VideoView设置为全屏尺寸
    ViewGroup.LayoutParams params = mVideoView.getLayoutParams();
    params.width = ViewGroup.LayoutParams.MATCH_PARENT;
    params.height = ViewGroup.LayoutParams.MATCH_PARENT;
    mVideoView.setLayoutParams(params);

    // 关闭容器的圆形裁剪(初始状态全屏不裁剪)
    mVideoContainer.setCircleMode(false);
}

2. 延迟切换为圆形显示

用Handler来实现延迟任务,比如延迟5秒后切换:

private void startDelayToCircleMode() {
    new Handler(Looper.getMainLooper()).postDelayed(() -> {
        // 切换为圆形模式
        mVideoContainer.setCircleMode(true);

        // 调整VideoView的尺寸为圆形大小(比如250dp)
        int circleSize = getResources().getDimensionPixelSize(R.dimen.circle_video_size);
        ViewGroup.LayoutParams params = mVideoView.getLayoutParams();
        params.width = circleSize;
        params.height = circleSize;
        params.gravity = Gravity.CENTER; // 居中显示
        mVideoView.setLayoutParams(params);

        // 恢复状态栏和ActionBar(可选,根据需求调整)
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        if (getSupportActionBar() != null) {
            getSupportActionBar().show();
        }
    }, 5000); // 5秒延迟,可根据需求修改时间
}

3. 调用流程

在播放视频的时候,先调用全屏方法,再启动延迟任务:

// 初始化VideoView并设置视频路径
mVideoView.setVideoURI(Uri.parse("your_video_path"));
mVideoView.start();

// 进入全屏播放
enterFullscreen();
// 启动延迟切换任务
startDelayToCircleMode();

小提示:如果担心内存泄漏,可以用View.postDelayed()或者Coroutines代替Handler,效果是一样的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:52:21