View 主要适用于主动更新的情况,而 surfaceView 主要适用于被动更新,例如频繁的刷新。
View 在主线程中对画面进行刷新,而 surfaceView 通常会通过一个子线程来进行页面的刷新
View 在绘图时没有使用双缓冲机制,而 surfaceView 在底层实现机制上就已经实现了双缓冲机制。
总结就是,如果你的自定义 View 需要频繁刷新,或者刷新时数据处理量很大,考虑用 SurfaceView 来替代 View。
//MainAtity
package com.example.administrator.myapplication;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.media.MediaPlayer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import java.io.IOException;
import java.util.ArrayList;
import java.util.WeakHashMap;
public class MainActivity extends AppCompatActivity implements View.OnClickListener,SurfaceHolder.Callback {
MediaPlayer mediaPlayer = new MediaPlayer();
String string = "http://uvideo.spriteapp.cn/video/2019/0512/56488d0a-7465-11e9-b91b-1866daeb0df1_wpd.mp4";
private SurfaceView surface_view;
private SurfaceHolder surfaceHolder;
private SurfaceView surfaceView_danmu;
private SurfaceHolder surfaceHolder_danmu;
private SeekBar bar;
private Button bt_play;
private Button bt_pause;
private EditText et;
private Button bt_danmu;
int x=0;
ArrayList<DanMu> list=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initpalyer();
list.add(new DanMu("张志南好帅啊",0,100,Color.GREEN,10));
list.add(new DanMu("吴迪最帅好帅啊",0,200,Color.YELLOW,40));
list.add(new DanMu("高迪最可爱啊",0,300,Color.RED,10));
list.add(new DanMu("圆圈其真胖啊",0,140,Color.GRAY,30));
list.add(new DanMu("李卓好丑啊",0,150,Color.BLUE,10));
list.add(new DanMu("兔爷真高啊",0,240,Color.GREEN,10));
}
private void initpalyer() {
if (mediaPlayer != null) {
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(string);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void initView() {
surface_view = (SurfaceView) findViewById(R.id.surface_view);
surfaceHolder=surface_view.getHolder();
surfaceHolder.addCallback(this);
surfaceView_danmu=findViewById(R.id.surface_danmu);
surfaceHolder_danmu=surfaceView_danmu.getHolder();
surfaceHolder_danmu.addCallback(this);
surfaceView_danmu.setZOrderOnTop(true);
surfaceHolder_danmu.setFormat(PixelFormat.TRANSPARENT);
bar = (SeekBar) findViewById(R.id.bar);
bt_play = (Button) findViewById(R.id.bt_play);
bt_pause = (Button) findViewById(R.id.bt_pause);
et = (EditText) findViewById(R.id.et);
bt_danmu = (Button) findViewById(R.id.bt_danmu);
bt_play.setOnClickListener(this);
bt_pause.setOnClickListener(this);
bt_danmu.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_play:
break;
case R.id.bt_pause:
break;
case R.id.bt_danmu:
String string = et.getText().toString();
list.add(new DanMu(string,0,200,Color.GREEN,70));
break;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if(holder==surfaceHolder){
mediaPlayer.setDisplay(surfaceHolder);
}else if(holder==surfaceHolder_danmu){
new DanMuThread().start();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
class DanMuThread extends Thread{
@Override
public void run() {
super.run();
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(20);
paint.setTextSize(30);
while (true){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
Canvas canvas = surfaceHolder_danmu.lockCanvas();
if(canvas==null){
break;
}
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
for(int i=0;i<list.size();i++){
DanMu danMu = list.get(i);
paint.setColor(danMu.getColor());
paint.setTextSize(danMu.getSize());
int x = danMu.getX();
danMu.setX(x+=10);
canvas.drawText(danMu.getText(),danMu.getX(),danMu.getY(),paint);
}
surfaceHolder_danmu.unlockCanvasAndPost(canvas);
}
}
}
}
//实体类
package com.example.administrator.myapplication;
public class DanMu {
private String text;
private int x;
private int y;
private int color;
private int size;
public DanMu(String text, int x, int y, int color, int size) {
this.text = text;
this.x = x;
this.y = y;
this.color = color;
this.size = size;
}
public String getText() {
return text;
}
public void setText(String text) {
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 int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
//效果图

//,Main2Activity
package com.example.administrator.myapplication.day1704;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.media.MediaPlayer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import com.example.administrator.myapplication.R;
import com.google.gson.Gson;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
public class Main2Activity extends AppCompatActivity implements SurfaceHolder.Callback {
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
ArrayList<Music> list=new ArrayList<>();
MediaPlayer mediaPlayer=new MediaPlayer();
int positon=0;
Timer timer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
initView();
initMusic();
initCi();
initTimer();
}
private void initView() {
surfaceView=findViewById(R.id.surface_view);
surfaceHolder=surfaceView.getHolder();
surfaceHolder.addCallback(this);
}
private void initTimer() {
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
int currentPosition = mediaPlayer.getCurrentPosition();
if(list.size()>0){
if(currentPosition>=list.get(positon+1).getStart_time()){
positon++;
}
}
}
},0,500);
}
private void initCi() {
try {
FileInputStream fileInputStream = new FileInputStream("/sdcard/最炫民族风");
byte[] bytes=new byte[1024];
int len=0;
StringBuilder stringBuilder=new StringBuilder();
while((len=fileInputStream.read(bytes))!=-1){
stringBuilder.append(new String(bytes,0,len));
}
Gson gson = new Gson();
Bean bean = gson.fromJson(stringBuilder.toString(), Bean.class);
String lyric = bean.getLrc().getLyric();
String[] split1 = lyric.split("\n");
for(int i=0;i<split1.length;i++){
String trim = split1[i].trim();
String[] split = trim.split("]");
if(split.length>=2){
String s = split[0];
String substring1 = s.substring(1, 3);
String substring2 = s.substring(4, 6);
String substring3 = s.substring(7, 10);
long start=Integer.parseInt(substring1)*60*1000+Integer.parseInt(substring2)*1000+Integer.parseInt(substring3);
String text = split[1];
list.add(new Music(text,start));
}
}
for(int i=0;i<list.size();i++){
Log.d("ytx", "initCi: "+list.get(i));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void initMusic() {
if(mediaPlayer!=null){
mediaPlayer.reset();
try {
mediaPlayer.setDataSource("/sdcard/凤凰传奇 - 最炫民族风(Live).mp3");
} catch (IOException e) {
e.printStackTrace();
}
try {
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
new MusicThread().start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(mediaPlayer!=null){
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer=null;
}
if(timer!=null){
timer.cancel();
}
}
class MusicThread extends Thread{
@Override
public void run() {
Paint paint = new Paint();
paint.setColor(Color.YELLOW);
paint.setTextSize(50);
while (true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Canvas canvas = surfaceHolder.lockCanvas();
if(canvas==null){
break;
}
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
if(list.size()>0){
canvas.drawText(list.get(positon).getText(),200,300,paint);
}
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
//bean类
package com.example.administrator.myapplication.day1704;
class Bean {
/**
* sgc : false
* sfy : false
* qfy : false
* lyricUser : {"id":29418062,"status":0,"demand":0,"userid":12907497,"nickname":"Simfre","uptime":1441503572343}
* lrc : {"version":5,"lyric":"[by:简单de频率]\n[00:00.000] 作曲 : 张超\n[00:01.000] 作词 : 张超\n[00:22.600]苍茫的天涯是我的爱\n[00:26.280]绵绵的青山脚下花正开\n[00:30.130]什么样的节奏是最呀最摇摆\n[00:33.880]什么样的歌声才是最开怀\n[00:37.750]弯弯的河水从天上来\n[00:41.310]流向那万紫千红一片海\n[00:45.330]火辣辣的歌谣是我们的期待\n[00:48.880]一路边走边唱才是最自在\n[00:52.630]我们要唱就要唱得最痛快\n[00:56.610]你是我天边最美的云彩\n[01:00.280]让我用心把你留下来(留下来)\n[01:04.340]悠悠的唱着最炫的民族风\n[01:07.840]让爱卷走所有的尘埃\n[01:10.470](我知道)你是我心中最美的云彩\n[01:15.380]斟满美酒让你留下来(留下来)\n[01:19.380]永远都唱着最炫的民族风\n[01:22.760]是整片天空最美的姿态\n[01:26.700]哟啦啦呵啦呗\n[01:28.520]伊啦嗦啦呵啦呗呀\n[01:30.700]我听见你心中动人的天籁\n[01:34.260]登上天外云霄的舞台\n[01:37.530]\n[01:53.250]苍茫的天涯是我的爱\n[01:56.940]绵绵的青山脚下花正开\n[02:00.820]什么样的节奏是最呀最摇摆\n[02:04.570]什么样的歌声才是最开怀\n[02:08.440]弯弯的河水从天上来\n[02:12.000]流向那万紫千红一片海\n[02:15.810]火辣辣的歌谣是我们的期待\n[02:19.620]一路边走边唱才是最自在\n[02:23.310]我们要唱就要唱得最痛快\n[02:27.220]你是我天边最美的云彩\n[02:30.920]让我用心把你留下来(留下来)\n[02:34.920]悠悠的唱着最炫的民族风\n[02:38.410]让爱卷走所有的尘埃\n[02:41.410](我知道)你是我心中最美的云彩\n[02:46.210]斟满美酒让你留下来(留下来)\n[02:50.140]永远都唱着最炫的民族风\n[02:53.460]是整片天空最美的姿态\n[02:57.810]\n[03:18.290]你是我天边最美的云彩\n[03:21.910]让我用心把你留下来(留下来)\n[03:26.030]悠悠的唱着最炫的民族风\n[03:29.510]让爱卷走所有的尘埃\n[03:32.260](我知道)你是我心中最美的云彩\n[03:37.010]斟满美酒让你留下来(留下来)\n[03:41.070]永远都唱着最炫的民族风\n[03:44.570]是整片天空最美的姿态\n[03:48.990]\n[03:50.300]我听见你心中那动人的天籁\n[03:53.990]就忽如一夜春风袭来满面桃花开\n[03:57.860]我忍不住去采 我忍不住去摘\n[04:01.620]我敞开胸怀为你等待\n[04:04.340]\n[04:05.840]你是我天边最美的云彩\n[04:09.280]让我用心把你留下来\n[04:13.010]悠悠的唱着最炫的民族风\n[04:16.750]让爱卷走所有的尘埃\n[04:19.500](我知道)你是我心中最美的云彩\n[04:24.250]斟满美酒让你留下来(留下来)\n[04:28.380]永远都唱着最炫的民族风\n[04:31.750]是整片天空最美的姿态\n[04:36.190]\n"}
* klyric : {"version":0,"lyric":null}
* tlyric : {"version":0,"lyric":null}
* code : 200
*/
private boolean sgc;
private boolean sfy;
private boolean qfy;
private LyricUserBean lyricUser;
private LrcBean lrc;
private KlyricBean klyric;
private TlyricBean tlyric;
private int code;
public boolean isSgc() {
return sgc;
}
public void setSgc(boolean sgc) {
this.sgc = sgc;
}
public boolean isSfy() {
return sfy;
}
public void setSfy(boolean sfy) {
this.sfy = sfy;
}
public boolean isQfy() {
return qfy;
}
public void setQfy(boolean qfy) {
this.qfy = qfy;
}
public LyricUserBean getLyricUser() {
return lyricUser;
}
public void setLyricUser(LyricUserBean lyricUser) {
this.lyricUser = lyricUser;
}
public LrcBean getLrc() {
return lrc;
}
public void setLrc(LrcBean lrc) {
this.lrc = lrc;
}
public KlyricBean getKlyric() {
return klyric;
}
public void setKlyric(KlyricBean klyric) {
this.klyric = klyric;
}
public TlyricBean getTlyric() {
return tlyric;
}
public void setTlyric(TlyricBean tlyric) {
this.tlyric = tlyric;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public static class LyricUserBean {
/**
* id : 29418062
* status : 0
* demand : 0
* userid : 12907497
* nickname : Simfre
* uptime : 1441503572343
*/
private int id;
private int status;
private int demand;
private int userid;
private String nickname;
private long uptime;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getDemand() {
return demand;
}
public void setDemand(int demand) {
this.demand = demand;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public long getUptime() {
return uptime;
}
public void setUptime(long uptime) {
this.uptime = uptime;
}
}
public static class LrcBean {
/**
* version : 5
* lyric : [by:简单de频率]
[00:00.000] 作曲 : 张超
[00:01.000] 作词 : 张超
[00:22.600]苍茫的天涯是我的爱
[00:26.280]绵绵的青山脚下花正开
[00:30.130]什么样的节奏是最呀最摇摆
[00:33.880]什么样的歌声才是最开怀
[00:37.750]弯弯的河水从天上来
[00:41.310]流向那万紫千红一片海
[00:45.330]火辣辣的歌谣是我们的期待
[00:48.880]一路边走边唱才是最自在
[00:52.630]我们要唱就要唱得最痛快
[00:56.610]你是我天边最美的云彩
[01:00.280]让我用心把你留下来(留下来)
[01:04.340]悠悠的唱着最炫的民族风
[01:07.840]让爱卷走所有的尘埃
[01:10.470](我知道)你是我心中最美的云彩
[01:15.380]斟满美酒让你留下来(留下来)
[01:19.380]永远都唱着最炫的民族风
[01:22.760]是整片天空最美的姿态
[01:26.700]哟啦啦呵啦呗
[01:28.520]伊啦嗦啦呵啦呗呀
[01:30.700]我听见你心中动人的天籁
[01:34.260]登上天外云霄的舞台
[01:37.530]
[01:53.250]苍茫的天涯是我的爱
[01:56.940]绵绵的青山脚下花正开
[02:00.820]什么样的节奏是最呀最摇摆
[02:04.570]什么样的歌声才是最开怀
[02:08.440]弯弯的河水从天上来
[02:12.000]流向那万紫千红一片海
[02:15.810]火辣辣的歌谣是我们的期待
[02:19.620]一路边走边唱才是最自在
[02:23.310]我们要唱就要唱得最痛快
[02:27.220]你是我天边最美的云彩
[02:30.920]让我用心把你留下来(留下来)
[02:34.920]悠悠的唱着最炫的民族风
[02:38.410]让爱卷走所有的尘埃
[02:41.410](我知道)你是我心中最美的云彩
[02:46.210]斟满美酒让你留下来(留下来)
[02:50.140]永远都唱着最炫的民族风
[02:53.460]是整片天空最美的姿态
[02:57.810]
[03:18.290]你是我天边最美的云彩
[03:21.910]让我用心把你留下来(留下来)
[03:26.030]悠悠的唱着最炫的民族风
[03:29.510]让爱卷走所有的尘埃
[03:32.260](我知道)你是我心中最美的云彩
[03:37.010]斟满美酒让你留下来(留下来)
[03:41.070]永远都唱着最炫的民族风
[03:44.570]是整片天空最美的姿态
[03:48.990]
[03:50.300]我听见你心中那动人的天籁
[03:53.990]就忽如一夜春风袭来满面桃花开
[03:57.860]我忍不住去采 我忍不住去摘
[04:01.620]我敞开胸怀为你等待
[04:04.340]
[04:05.840]你是我天边最美的云彩
[04:09.280]让我用心把你留下来
[04:13.010]悠悠的唱着最炫的民族风
[04:16.750]让爱卷走所有的尘埃
[04:19.500](我知道)你是我心中最美的云彩
[04:24.250]斟满美酒让你留下来(留下来)
[04:28.380]永远都唱着最炫的民族风
[04:31.750]是整片天空最美的姿态
[04:36.190]
*/
private int version;
private String lyric;
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public String getLyric() {
return lyric;
}
public void setLyric(String lyric) {
this.lyric = lyric;
}
}
public static class KlyricBean {
/**
* version : 0
* lyric : null
*/
private int version;
private Object lyric;
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public Object getLyric() {
return lyric;
}
public void setLyric(Object lyric) {
this.lyric = lyric;
}
}
public static class TlyricBean {
/**
* version : 0
* lyric : null
*/
private int version;
private Object lyric;
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public Object getLyric() {
return lyric;
}
public void setLyric(Object lyric) {
this.lyric = lyric;
}
}
}
//实体类
package com.example.administrator.myapplication.day1704;
public class Music {
private String text;
private long start_time;
@Override
public String toString() {
return "Music{" +
"text='" + text + '\'' +
", start_time=" + start_time +
'}';
}
public Music(String text, long start_time) {
this.text = text;
this.start_time = start_time;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public long getStart_time() {
return start_time;
}
public void setStart_time(long start_time) {
this.start_time = start_time;
}
}
//效果图

本文介绍了Android中View和SurfaceView的区别与应用场景。View适合主动更新,SurfaceView适合被动频繁更新;View在主线程刷新,SurfaceView通过子线程刷新;SurfaceView还实现了双缓冲机制。文章通过具体示例展示了如何使用这两种组件。

2638

被折叠的 条评论
为什么被折叠?



