I am trying to display a ExoPlayerView inside a circle, overlaying another ExoPlayer (picture in picture):
I have tried putting the 2nd player inside a frame with rounded corners (both this answer and this one) but the player will always escape the parent frame and draw the video's full rectangle.
I found this solution which uses a GLSurfaceView, however this solution uses the classic MediaPlayer and not ExoPlayer.
You need to create a custom container for it. try this and put you player view in it.
public class RoundFrameLayout extends FrameLayout {
private final Path clip = new Path();
private int posX;
private int posY;
private int radius;
public RoundFrameLayout(Context context) {
this(context,null);
}
public RoundFrameLayout(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public RoundFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// We can use outlines on 21 and up for anti-aliased clipping.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setClipToOutline(true);
}
}
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
posX = Math.round((float) width / 2);
posY = Math.round((float) height / 2);
// noinspection NumericCastThatLosesPrecision
radius = (int) Math.floor((float) Math.min(width, height) / 2);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setOutlineProvider(new OutlineProvider(posX, posY, radius));
} else {
clip.reset();
clip.addCircle(posX, posY, radius, Direction.CW);
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
// Not needed on 21 and up since we're clipping to the outline instead.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
canvas.clipPath(clip);
}
super.dispatchDraw(canvas);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// Don't pass touch events that occur outside of our clip to the children.
float distanceX = Math.abs(event.getX() - posX);
float distanceY = Math.abs(event.getY() - posY);
double distance = Math.hypot(distanceX, distanceY);
return distance > radius;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
static class OutlineProvider extends ViewOutlineProvider {
final int left;
final int top;
final int right;
final int bottom;
OutlineProvider(int posX, int posY, int radius) {
left = posX - radius;
top = posY - radius;
right = posX + radius;
bottom = posY + radius;
}
@Override
public void getOutline(View view, Outline outline) {
outline.setOval(left, top, right, bottom);
}
}
}
For the one that's supposed to have rounded corners, you can set in the layout XML file this about it:
app:surface_type="texture_view"
Found this solution here.
The drawback of using this is mainly performance and battery usage (written here) :
Should I use SurfaceView or TextureView? SurfaceView has a number of benefits over TextureView for video playback:
Significantly lower power consumption on many devices. More accurate frame timing, resulting in smoother video playback. Support for secure output when playing DRM protected content. SurfaceView should therefore be preferred over TextureView where possible. TextureView should be used only if SurfaceView does not meet your needs. One example is where smooth animations or scrolling of the video surface is required prior to Android N (see How do I get smooth animation/scrolling of video?). For this case, it’s preferable to use TextureView only when SDK_INT is less than 24 (Android N) and SurfaceView otherwise.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With