SurfaceView发送弹幕
SurfaceView介绍简单介绍
通常情况程序的View和用户响应都是在同一个线程中处理的,这也是为什么处理长时间事件(例如访问网络)需要放到另外的线程中去(防止阻塞当前UI线程的操作和绘制)。但是在其他线程中却不能修改UI元素,例如用后台线程更新自定义View(调用View的在自定义View中的onDraw函数)是不允许的。
如果需要在另外的线程绘制界面、需要迅速的更新界面,或者渲染UI界面需要较长的时间,这种情况就要使用SurfaceView了。SurfaceView中包含一个Surface对象,而Surface是可以在后台线程中绘制的。
SurfaceView的性质决定了其比较适合一些场景:需要界面迅速更新、对帧率要求较高的情况。
使用SurfaceView需要注意以下几点情况:
(1)SurfaceView和SurfaceHolder.Callback函数都从当前SurfaceView窗口线程中调用(一般而言就是程序的主线程)。
(2)有关资源状态要注意和绘制线程之间的同步。
(3)在绘制线程中必须先合法的获取Surface才能开始绘制内容,在SurfaceHolder.Callback.surfaceCreated() 和SurfaceHolder.Callback.surfaceDestroyed()之间的状态为合法的,在Surface类型为SURFACE_TYPE_PUSH_BUFFERS时是不合法的。
(4)额外的绘制线程会消耗系统的资源,在使用SurfaceView的时候要注意这点。
发送弹幕代码
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
SurfaceView surfaceView;
SurfaceHolder holder;
EditText et;
Button bt;
int y = 0;
ArrayList<Barrage> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = findViewById(R.id.bt);
et = findViewById(R.id.et);
list.add(new Barrage(0,100,"鸡你太美"));
list.add(new Barrage(0,120,"鸡你太美"));
list.add(new Barrage(0,170,"鸡你太美"));
list.add(new Barrage(0,50,"鸡你太美"));
//找到控件id
surfaceView = findViewById(R.id.sf);
//获取holder
holder = surfaceView.getHolder();
//回调找打生命周期
holder.addCallback(this);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String text = et.getText().toString();
int height = surfaceView.getHeight();
y = (int) (Math.random()*height);
Barrage barrage = new Barrage(0, y, text);
list.add(barrage);
}
});
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
new MyThread().start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
class MyThread extends Thread{
@Override
public void run() {
Paint paint = new Paint();
paint.setTextSize(60);
while (true){
Canvas canvas = holder.lockCanvas();
if (canvas == null){
break;
}
canvas.drawColor(Color.WHITE);
for (int i = 0; i < list.size(); i++) {
int a = (int) (Math.random()*255);
int b = (int) (Math.random()*255);
int c = (int) (Math.random()*255);
paint.setColor(Color.rgb(a,b,c));
int x = list.get(i).getX();
list.get(i).setX(x+=10);
canvas.drawText(list.get(i).getText(),list.get(i).getX(),list.get(i).getY(),paint);
}
holder.unlockCanvasAndPost(canvas);
}
}
}
}
这里我们需要一个弹幕的类
里边包括文字 和坐标方便进行弹幕的发送
package com.example.day05_surfaceview;
public class Barrage {
int x;
int y;
String text;
public Barrage(int x, int y, String text) {
this.x = x;
this.y = y;
this.text = text;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}