Android - Creating a circular mask on video

老子叫甜甜 提交于 2019-12-29 05:20:17

问题


I'm relatively new to Android development, and I was wondering if it's possible to mask a VideoView into a shape. This is what I have so far:

Expected Result

My XML for video view and layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    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_width="250dp"
        android:layout_height="250dp"
        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_width="fill_parent"
            android:layout_height="fill_parent"
            android:fitsSystemWindows="false"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:scrollbarAlwaysDrawVerticalTrack="false" />

        <Space
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </FrameLayout>

</RelativeLayout>

Mask shape 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>

Main 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;
    }
}

回答1:


Turns out it is possible to clip a video into a circle. What you're going to want to do is create your own SurfaceView class and override dispatchDraw from here you can call canvas.clipPath and pass in a Path object that contains the circle you want the video to be masked to.

Here's the view:

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);
    }
}

Here's what the activity might look like

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
    }
}



回答2:


I've done something like this mask before. you can get what you want as following steps
1) prepare a png image with the shape you want and fill it with color 0x0000000
2) use a blank layout and make sure it covers the VideView
3) now, all touchevents are captured by this blank layout
4) judge the points' colors which are contained in TouchEvent, if the color is 0x00000000 then pass the event to VideView

here is a example to get a point's color, and it runs efficently:

// 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
        }


来源:https://stackoverflow.com/questions/21001721/android-creating-a-circular-mask-on-video

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!