Android - 在视频上创建圆形蒙版

Posted

技术标签:

【中文标题】Android - 在视频上创建圆形蒙版【英文标题】:Android - Creating a circular mask on video 【发布时间】:2014-01-26 21:53:05 【问题描述】:

我对 android 开发比较陌生,我想知道是否可以将 VideoView 屏蔽为形状。这是我目前所拥有的:

预期结果

用于视频查看和布局的 XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    android:background="#0088ff"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".VideoPlayerActivity" >

    <FrameLayout
        android:layout_
        android:layout_
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:background="@drawable/circular_mask"
        android:foreground="@drawable/circular_mask" >

        <VideoView
            android:id="@+id/videoView1"
            android:layout_
            android:layout_
            android:fitsSystemWindows="false"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:scrollbarAlwaysDrawVerticalTrack="false" />

        <Space
            android:layout_
            android:layout_ />

    </FrameLayout>

</RelativeLayout>

面具形状xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:padding="20dp"
    android:shape="oval" >

    <solid android:color="#FFFFFFFF" />

    <corners android:radius="10dp" />

</shape>

主java:

package com.example.webmvideo;

import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.annotation.TargetApi;
import android.app.Activity;
import android.view.Menu;
import android.widget.MediaController;
import android.widget.VideoView;
import android.util.Log;
import android.media.MediaPlayer;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MainActivity extends Activity 

    Uri srcPath = Uri.parse("android.resource://com.example.webmvideo/" + R.raw.test);

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final VideoView videoView = (VideoView) 
                findViewById(R.id.videoView1);

        videoView.setVideoURI(srcPath);

        MediaController mediaController = new MediaController(this);
        mediaController.setAnchorView(videoView);
        videoView.setMediaController(mediaController);

        videoView.setOnPreparedListener(new 
                MediaPlayer.OnPreparedListener()  
            @Override
            public void onPrepared(MediaPlayer mp)                          
                String TAG = null;
                Log.i(TAG , "Duration = " + videoView.getDuration());
            
        );     
        videoView.start();
    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    

【问题讨论】:

您是否尝试过在遮罩形状 XML 文件中将形状设置为圆形? 您正在向 Surface 发送帧,并渲染到 View(通常只是一个透明的“洞”)。 View 和 Surface 之间的混合将由系统合成器完成,因此应用程序渲染没有任何要混合的先前内容。选择一种模式,将输出像素中的 Alpha 设置为适当的透明或不透明。 嗨 Jamesbar 您是否实现了圆角 VideoView?如果您实施了手段,请分享您的想法。怎么会这样? 一个简单的方法***.com/a/28108447/3496570 【参考方案1】:

原来可以将视频剪辑成一个圆圈。你要做的是创建你自己的 SurfaceView 类并覆盖 dispatchDraw 从这里你可以调用 canvas.clipPath 并传入Path 对象,其中包含您希望将视频遮盖到的圆圈。

这是视图:

public class CircleSurface extends SurfaceView 

    private Path clipPath;

    public CircleSurface(Context context) 
        super(context);
        init();
    

    public CircleSurface(Context context, AttributeSet attrs) 
        super(context, attrs);
        init();
    

    public CircleSurface(Context context, AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        init();
    

    private void init() 
        clipPath = new Path();
        //TODO: define the circle you actually want
        clipPath.addCircle(710, 330, 250, Path.Direction.CW);
    

    @Override
    protected void dispatchDraw(Canvas canvas) 
        canvas.clipPath(clipPath);
        super.dispatchDraw(canvas);
    

这是活动的样子

public class MainActivity extends Activity implements SurfaceHolder.Callback 

    CircleSurface surface;
    MediaPlayer player;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        surface = (CircleSurface) findViewById(R.id.surface);
        SurfaceHolder holder = surface.getHolder();
        holder.addCallback(this);

        player = MediaPlayer.create(this, R.raw.yourvideo);
    


    @Override
    public void surfaceCreated(SurfaceHolder holder) 
        player.setDisplay(holder);
        player.start();
    

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
        //TODO: handle this
    

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) 
        //TODO: handle this
    

【讨论】:

不幸的是这似乎没有效果 我的错,如果你有 setZOrderMediaOverlay(true); 就不行了 为什么super.dispatchDraw()方法应该在canvas.clipPath()之后? 这里为什么不能用普通的 View 而不是 SurfaceView?【参考方案2】:

我以前做过类似这个面具的事情。您可以按照以下步骤获得所需的内容 1)准备一个你想要的形状的png图像,并用颜色0x0000000填充它 2) 使用空白布局并确保它覆盖 VideView 3) 现在,所有的触摸事件都被这个空白布局捕获 4)判断TouchEvent中包含的点的颜色,如果颜色为0x00000000则将事件传递给VideView 这是一个获取点颜色的示例,它运行有效:

// build a drawingCache and draw the mask layer to the bitmap
        Bitmap drawingCache = Bitmap.createBitmap(getWidth(), getHeight(),Bitmap.Config.ARGB_4444);
        Canvas drawingCacheCanvas = new Canvas(drawingCache);
        drawingCacheCanvas.clipRect(x, y, x + 1, y + 1); 
        draw(drawingCacheCanvas);

        int color = drawingCache.getPixel(x, y);

        if (color == getMaskColor())  
            //TODO dispatch event to VideoView and let it to handle event
        

【讨论】:

以上是关于Android - 在视频上创建圆形蒙版的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 Sprite Kit 中使用圆形(SKShapeNode)作为蒙版?

如何获得圆形图层蒙版?

圆形 CAGradientLayer 蒙版 - iOS

在android中使用纹理视图的圆形视频播放器

如何在鼠标滚轮滚动上为剪贴蒙版设置动画

圆形 CAGradientLayer 蒙版