两个surfaceview的重叠效果类似直播效果中的视频和讲义实践

[TOC]

效果图

首先还是不废话,直接上一张图,有图才有真相,不然大家看半天才发现不是我想要的效果,所以这样浪费大家的时间了

实际应用场景可多了,比如后面是显示相机的数据,前面是一个画板,直播的视频和讲义展示

布局

布局就很简单了,直接让两个surfaceView重叠在一起

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
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00f"
tools:context="cn.woblog.testsurfaceview.MainActivity">
<SurfaceView
android:id="@+id/sv"
android:layout_width="match_parent"
android:layout_height="400dp" />
<RelativeLayout
android:id="@+id/rl"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<SurfaceView
android:id="@+id/sv_mini"
android:layout_width="200dp"
android:layout_height="200dp"
android:clickable="false"
android:focusable="false" />
</RelativeLayout>
</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
sv = (SurfaceView) findViewById(R.id.sv);
sfh = sv.getHolder();
//对 surfaceView 进行操作
sfh.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = sfh.lockCanvas(new Rect(0, 0, 600, 600));
//2.开画
Paint p = new Paint();
p.setColor(Color.RED);
Rect aa = new Rect(0, 0, 600, 600);
c.drawRect(aa, p);
//3. 解锁画布 更新提交屏幕显示内容
sfh.unlockCanvasAndPost(c);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});

如果到这一步,这两个界面肯定是不会有上图的效果,而是第一个会覆盖第二个,下面是关键代码了

1
2
sv_mini.setZOrderOnTop(true);
holder.setFormat(PixelFormat.TRANSPARENT);

把最上面的那个surface设置为最上面,并且然他透明,如果不设置透明,那么只能看到顶部的那个surfaceView,其他地方是黑色的。到这里基本解决了然两个surfaceView重叠显示,下面我们来加入拖动效果

使用layout方法

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
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public boolean onTouch(View v, MotionEvent event) {
int ea = event.getAction();
switch (ea) {
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
/**
* layout(l,t,r,b)
* l Left position, relative to parent
t Top position, relative to parent
r Right position, relative to parent
b Bottom position, relative to parent
* */
case MotionEvent.ACTION_MOVE:
int dx = (int) event.getRawX() - lastX;
int dy = (int) event.getRawY() - lastY;
int left = v.getLeft() + dx;
int top = v.getTop() + dy;
int right = v.getRight() + dx;
int bottom = v.getBottom() + dy;
if (left < 0) {
left = 0;
right = left + v.getWidth();
}
if (right > screenWidth) {
right = screenWidth;
left = right - v.getWidth();
}
if (top < 0) {
top = 0;
bottom = top + v.getHeight();
}
if (bottom > screenHeight) {
bottom = screenHeight;
top = bottom - v.getHeight();
}
v.layout(left, top, right, bottom);
Log.i("", "position:" + left + ", " + top + ", " + right + ", " + bottom);
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}

使用margin

带添加~

完整代码

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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
package cn.woblog.testsurfaceview;
import android.annotation.TargetApi;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
public static final String TAG = "TAG";
private SurfaceView sv;
private SurfaceView sv_mini;
private SurfaceHolder sfh;
private SurfaceHolder holder;
private RelativeLayout rl;
private int lastX;
private int lastY;
private int screenWidth;
private int screenHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DisplayMetrics dm = getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels - 50;
getSupportActionBar().hide();
sv = (SurfaceView) findViewById(R.id.sv);
rl = (RelativeLayout) findViewById(R.id.rl);
rl.setOnTouchListener(this);
sfh = sv.getHolder();
//对 surfaceView 进行操作
sfh.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = sfh.lockCanvas(new Rect(0, 0, 600, 600));
//2.开画
Paint p = new Paint();
p.setColor(Color.RED);
Rect aa = new Rect(0, 0, 600, 600);
c.drawRect(aa, p);
//3. 解锁画布 更新提交屏幕显示内容
sfh.unlockCanvasAndPost(c);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});// 自动运行surfaceCreated以及surfaceChanged
sv_mini = (SurfaceView) findViewById(R.id.sv_mini);
// sv.setZOrderOnTop(false);
//这两个方法差不多,设置了就会浮现到顶部,但是,后面的看不见,要像下面设置为透明
sv_mini.setZOrderOnTop(true);
sv_mini.setZOrderMediaOverlay(true);
holder = sv_mini.getHolder();
holder.setFormat(PixelFormat.TRANSPARENT);
sfh.setFormat(PixelFormat.TRANSPARENT);
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = holder.lockCanvas(new Rect(0, 0, 400, 400));
//2.开画
Paint p = new Paint();
p.setColor(Color.BLUE);
Rect aa = new Rect(0, 0, 400, 400);
c.drawRect(aa, p);
//3. 解锁画布 更新提交屏幕显示内容
holder.unlockCanvasAndPost(c);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public boolean onTouch(View v, MotionEvent event) {
int ea = event.getAction();
switch (ea) {
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
/**
* layout(l,t,r,b)
* l Left position, relative to parent
t Top position, relative to parent
r Right position, relative to parent
b Bottom position, relative to parent
* */
case MotionEvent.ACTION_MOVE:
int dx = (int) event.getRawX() - lastX;
int dy = (int) event.getRawY() - lastY;
int left = v.getLeft() + dx;
int top = v.getTop() + dy;
int right = v.getRight() + dx;
int bottom = v.getBottom() + dy;
if (left < 0) {
left = 0;
right = left + v.getWidth();
}
if (right > screenWidth) {
right = screenWidth;
left = right - v.getWidth();
}
if (top < 0) {
top = 0;
bottom = top + v.getHeight();
}
if (bottom > screenHeight) {
bottom = screenHeight;
top = bottom - v.getHeight();
}
v.layout(left, top, right, bottom);
Log.i("", "position:" + left + ", " + top + ", " + right + ", " + bottom);
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}

Demo地址下一期会从源码的角度解析为什么会有上述问题存在,敬请期待

任苹蜻 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
坚持原创技术分享,您的支持将鼓励我继续创作!

热评文章