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 - 在视频上创建圆形蒙版的主要内容,如果未能解决你的问题,请参考以下文章