0%

【转】如何实现TextureView或者SurfaceView预览框为圆角

如何让 SurfaceView 或者 TextureView 实现圆角呢?这篇文章正好解决此问题,转载一手。其实主要是基于 ViewOutlineProvider 这个组件专门用于裁剪 View 的边界,注意使用 ViewOutlineProvider 时必须API >= 21。不光可以实现圆角裁剪,还可以实现轮廓、阴影等很多效果,这个如果后面用到了再补充。

项目中,视频预览界面框为圆角;但发现是使用的 Renderer 渲染的方法进行的,的确可以有圆角效果。

但有个问题是:我的视频源与要显示视频的预览框的长宽比率不同,预览框需要满屏看到视频源,如果不做处理,视频源只能通过压缩来显示。造成了视频的变形,如果不拉伸处理,那么就进行裁剪处理,需要对视频进行Matrix操作,如移动,伸缩处理。进行这些处理后,渲染的圆角效果就不再出现了。所以通过Renderer来进行圆角效果,不但复杂而且并不可靠。

通过网上的搜索可以找到 Android5.0后,一个类 ViewOutlineProvider;基于 View 自身的setClipToOutline(boolean clipToOutline) 和 setOutlineProvider(ViewOutlineProvider provider) 方法实现了该需求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import android.graphics.Outline;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewOutlineProvider;

public class TextureVideoViewOutlineProvider extends ViewOutlineProvider {
private float mRadius;

public TextureVideoViewOutlineProvider(float radius) {
this.mRadius = radius;
}

@Override
public void getOutline(View view, Outline outline) {
Rect rect = new Rect();
view.getGlobalVisibleRect(rect);
int leftMargin = 0;
int topMargin = 0;
Rect selfRect = new Rect(leftMargin, topMargin,
rect.right - rect.left - leftMargin, rect.bottom - rect.top - topMargin);
outline.setRoundRect(selfRect, mRadius);
}
}
1
2
mView.setOutlineProvider(new TextureVideoViewOutlineProvider(radius));
mView.setClipToOutline(true);

任何 View 都可通过此方法达到圆角效果。

下面是我自己试了一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<SurfaceView
android:id="@+id/preview_surface"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerInParent="true"
/>
</RelativeLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.graphics.Outline;
import android.graphics.Rect;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewOutlineProvider;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {
private Camera mCamera; // 相机
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCamera = android.hardware.Camera.open();
SurfaceView mPreview = findViewById(R.id.preview_surface);
mPreview.setOutlineProvider(new TextureVideoViewOutlineProvider(
DensityUtil.dip2px(this, 150)));
mPreview.setClipToOutline(true);

mPreview.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(mPreview.getHolder());
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
}

@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

}
});
}

@Override
protected void onResume() {
super.onResume();
if(mCamera != null) {
mCamera.startPreview();
}
}

@Override
protected void onPause() {
super.onPause();
if(mCamera != null) {
mCamera.stopPreview();
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if(mCamera != null) {
mCamera.release();
}
}
}

class TextureVideoViewOutlineProvider extends ViewOutlineProvider {
private final float mRadius;

public TextureVideoViewOutlineProvider(float radius) {
this.mRadius = radius;
}

@Override
public void getOutline(View view, Outline outline) {
Rect rect = new Rect();
view.getGlobalVisibleRect(rect);
int leftMargin = 0;
int topMargin = 0;
Rect selfRect = new Rect(leftMargin, topMargin,
rect.right - rect.left - leftMargin,
rect.bottom - rect.top - topMargin);
outline.setRoundRect(selfRect, mRadius);
}
}

class DensityUtil {
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}

public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
}

  • 本文作者: Tim
  • 本文链接: https://zouchanglin.cn/963813148.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!