6

I'm trying to make a rounded shaped surfaceview. I've searched a lot but i couldn't find a good solution. what i'm doing right now is that, I've put the SurfaceView into a FrameLayout, then another View on top of it, either with a PNG mask, or a shape xml drawable. here it is

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:layout_width="140dp"
        android:layout_height="140dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:background="#000"
        android:orientation="vertical"
        android:visibility="visible" >

        <FrameLayout
            android:id="@+id/videorecordview"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:layout_weight=".2" >

            <SurfaceView
            android:id="@+id/surfaceView1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
        </FrameLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:background="@drawable/rounded"
        android:orientation="vertical" >
    </LinearLayout>

</RelativeLayout>

But this is not a good solution and it is also not working perfectly. I want to customize surfaceview to a rounded shape. any help would be much appreciated. Thank you :)

fadden
  • 50,104
  • 5
  • 113
  • 164
Tashen Jazbi
  • 1,034
  • 16
  • 39
  • 1
    http://stackoverflow.com/questions/26074784/how-to-make-a-view-in-android-with-rounded-corners ... try this ..Change FrameLayout to SurfaceView – sunil sunny Apr 12 '16 at 05:19
  • Thank you for your participation. @sunilsunny you can make any view rounded by using this but not surfaceview. I've already tried that :) – Tashen Jazbi Apr 12 '16 at 05:35
  • @TashenJazbi: Did you find a solution for this? I am stuck with the same implementation issue. Can you please post your solution? Thanks – nibz Nov 11 '17 at 12:28
  • @Sneha we can not change the shape of SurfaceView's Surface. Please read down the right answer :) – Tashen Jazbi Nov 12 '17 at 01:45
  • @TashenJazbi: yes right, then how did you implement this ? – nibz Nov 12 '17 at 02:02
  • @Sneha it can be done by putting circularview on top of surfaceview and then placing another view on it. its not perfect but can work to some extent :p – Tashen Jazbi Nov 12 '17 at 02:41
  • Might be the REAL answer: https://stackoverflow.com/a/31064523/1819810 And there is a full example. – Weekend Aug 08 '18 at 08:36

4 Answers4

25

A little hack. Put your surface view inside card view.

<android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/margin_normal" 
        app:cardCornerRadius="10dp"     
        app:cardPreventCornerOverlap="false">

        <SurfaceView
            android:id="@+id/surfaceView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="@dimen/margin_normal" />

    </android.support.v7.widget.CardView>

Don't forget to add this to your gradle file to use CardView

compile 'com.android.support:cardview-v7:25.0.1'

Also this two line inside card view

app:cardCornerRadius="10dp"     
app:cardPreventCornerOverlap="false"

Cheers happy coding

ralphgabb
  • 9,778
  • 2
  • 45
  • 53
  • 19
    Nice, however doesn't work when the SurfaceView is on top of another SurfaceView – aberaud Sep 03 '18 at 01:51
  • 1
    This is working indeed. Practically it is same as overriding `dispatchDraw` and clipping canvas. But I have to agree with @ralphgabb, both tricks (dispatchDraw and cardView) are not working for SurfaceView is on top of another SurfaceView. – vigilancer Jul 11 '19 at 09:41
  • 2
    It is not actually :) because in my case I need to draw SurfaceView above another SurfaceView. In all other cases your solution should work just fine. – vigilancer Jul 14 '19 at 08:13
  • 1
    you can also have a layout, like a `FrameLayout`, with a background using round corners. Then add your SurfaceView as a child of the frame layout and set `setClipToOutline` to true on the FrameLayout. It won't work on top of another SurfaceView though – Carlisg Sep 26 '19 at 07:45
  • If you're using a `Camerax PreviewView`, set the `implementationMode` of PreviewView to `compatible` which forces it to use a `TextureView` instead of a `SurfaceView` and you'll get the rounded corners. – Vikram Gupta Dec 17 '20 at 01:11
  • are there still Kitkat users? I think I only tested it on Lollipop (21) and above. – ralphgabb Jan 10 '21 at 08:05
  • @aberaud Did you find the solution? – Arjun May 15 '21 at 10:00
  • @vigilancer Did you find the solution? – Arjun May 15 '21 at 10:00
  • @Arjun Use a TextureView instead of a SurfaceView – aberaud May 15 '21 at 14:02
  • @aberaud I'm using org.webrtc.SurfaceViewRenderer in a video calling app. After changing to TextureView I cannot use methods like .init(), .setScalingType, .setZOrderMediaOverlay() or .setEnableHardwareScaler() – Arjun May 19 '21 at 08:57
  • @Arjun did u find solution – famfamfam Jun 21 '21 at 02:34
  • @famfamfam I haven't found a solution yet – Arjun Jun 24 '21 at 07:25
  • Have the same case in my app. Any idea how to do it with GLSurfaceView? – Andrey Jul 07 '21 at 11:41
  • That's an awesome idea I tried it myself setting CornerRadius to 100dp. Got a complete circle. Looks smashing. Shame it cannot work on much older firmware. Not sure if creating it via xml and using it as a background would help matters. Couldn't get it to apply a background so i guess that is not doable. – James Smith Aug 27 '21 at 11:45
  • it works fine with `TextureView`, just create `val surface = Surface(binding.textureView.surfaceTexture)` and pass this surface to `camera2` API, but in this case need to implement logic with orientation on your own – user924 May 17 '22 at 14:09
10

You can't change the shape of the SurfaceView's Surface.

A SurfaceView has two parts, the Surface and the View. The View part works like any other View. By default, it just acts as a transparent "hole", creating a window in the layout. All Views are rendered by the app onto a single layer.

The Surface part is a separate layer that sits behind the View layer (unless you explicitly change the Surface's Z order), so you only see it where it "shows through" transparent areas of the View layer. You can draw on the View layer to mask portions of the Surface, but you can't change the shape of the Surface layer itself. Layers are rectangular.

In many situations a TextureView can be used in place of a SurfaceView. TextureView offers greater flexibility because it's rendered by the app onto the View layer, but can be less efficient than SurfaceView.

More information can be found in the Android graphics architecture doc.

fadden
  • 50,104
  • 5
  • 113
  • 164
  • your answer sounds reasonable to accept it as right answer. Thank you for your participation :) – Tashen Jazbi Apr 13 '16 at 05:12
  • My use case is to display a camera preview using `CameraX` `PreviewView` on top of another surface view. The `PreviewView` uses either a `TextureView` or a `SurfaceView` which it decides during runtime. When set to explicitly use a `TextureView` (by setting `implementationMode` property to `compatible`), I am able to get rounded corners. I placed my PreviewView inside a CardView like @ralphgabb suggested. – Vikram Gupta Dec 17 '20 at 01:09
1

To achieve what you ask, it is very easy to do it. You only need to use the next XML:

<androidx.cardview.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:cardCornerRadius="12dp">
        <SurfaceView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center" />
    </androidx.cardview.widget.CardView>

And to use this CardView, add this dependency on your build.gradle app:

implementation 'androidx.cardview:cardview:1.0.0'

Nessie
  • 84
  • 4
-2

try this

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
    <gradient
        android:startColor="#FFFF0000"
        android:endColor="#80FF00FF"
        android:angle="270"/>
</shape>

<SurfaceView
    android:background="@drawable/circle"
    android:id="@+id/surfaceView1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />
Manaus
  • 397
  • 4
  • 9