如何制作圆形SurfaceView

7

我想制作一个圆形的SurfaceView,搜索了很多但没有找到一个好的解决方案。目前我的处理方式是将SurfaceView放入FrameLayout中,然后在其上面添加另外一个View,可以使用PNG遮罩或者是形状XML drawable。下面是代码:

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

但这不是一个好的解决方案,也不能完美地工作。我想自定义SurfaceView成为圆形形状。任何帮助将不胜感激。谢谢 :)


1
尝试这个...将FrameLayout更改为SurfaceView。 - Sunil Sunny
感谢您的参与。@sunilsunny,您可以使用此方法使任何视图变为圆角,但不包括SurfaceView。我已经尝试过了 :) - Tashen Jazbi
@TashenJazbi:你找到解决方案了吗?我也遇到了同样的实现问题。你能否发帖分享一下你的解决方案?谢谢 - user2234
@Sneha,我们无法更改SurfaceView的Surface的形状。请向下阅读正确答案 :) - Tashen Jazbi
可能是真正的答案:https://dev59.com/m2Ei5IYBdhLWcg3wuuUk#31064523,而且还有一个完整的示例。 - Weekend
显示剩余2条评论
4个回答

28

一个小技巧。将你的SurfaceView放进CardView里面。

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

别忘了将这行代码添加到你的gradle文件中,以使用CardView

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

还有这两行文字在卡片视图内

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

祝编码愉快


21
不错,但是当SurfaceView处于另一个SurfaceView之上时就无法工作。 - aberaud
1
这确实起作用了。实际上,它与覆盖dispatchDraw和剪辑画布是相同的。但我必须同意@ralphgabb的观点,因为无论是dispatchDraw还是cardView,都无法在SurfaceView位于另一个SurfaceView之上时正常工作。 - vigilancer
2
这并不是实际情况 :) 因为在我的情况下,我需要在另一个SurfaceView上面绘制SurfaceView。在所有其他情况下,您的解决方案应该完全可行。 - vigilancer
1
你可以像使用FrameLayout一样,创建一个带有圆角背景的布局。然后将你的SurfaceView作为FrameLayout的子视图,并在FrameLayout上设置setClipToOutline为true。但是它不能在另一个SurfaceView之上工作。 - Carlisg
还有人在使用Kitkat吗?我想我只在Lollipop(21)及以上的版本上测试过。 - ralphgabb
显示剩余11条评论

10

你不能改变SurfaceView的Surface的形状。

SurfaceView由两个部分组成,即Surface和View。视图(View)部分与任何其他视图(View)一样工作。默认情况下,它只充当一个透明的“孔”,在布局中创建一个窗口,所有视图都是由应用程序呈现在单个图层上的。

Surface部分是一个单独的图层,位于View层后面(除非你显式地更改了Surface的Z顺序),因此你只能在View层的透明区域中看到它。“你可以在View层上绘制来遮盖Surface的某些部分,但你不能改变Surface层本身的形状。图层是矩形的。

在许多情况下,可以使用TextureView代替SurfaceView。TextureView提供了更大的灵活性,因为它是由应用程序呈现在View层上的,但可能比SurfaceView效率低。

更多信息可以在Android 图形架构文档中找到。


您的回答听起来合理,我们接受它作为正确答案。谢谢您的参与 :) - Tashen Jazbi
我的使用情况是在另一个SurfaceView的顶部使用CameraX PreviewView来显示相机预览。PreviewView在运行时使用TextureView或SurfaceView,具体取决于它自己的决策。当设置为显式使用TextureView(通过将implementationMode属性设置为compatible)时,我能够获得圆角。我像@ralphgabb建议的那样将我的PreviewView放在CardView中。 - Vikram Gupta

2
要实现您的要求,非常容易做到。 您只需要使用下一个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>

要使用这个CardView,需要在你的 build.gradle 应用程序添加以下依赖项:

implementation 'androidx.cardview:cardview:1.0.0'


(注意:保留HTML标签,请勿写解释)

-2

试一下这个

<?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" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接