View 主要适用于主动更新的状况,而 surfaceView 主要适用于被动更新,例如频繁的刷新。
View 在主线程中对画面进行刷新,而 surfaceView 一般会经过一个子线程来进行页面的刷新
View 在绘图时没有使用双缓冲机制,而 surfaceView 在底层实现机制上就已经实现了双缓冲机制。
总结就是,若是你的自定义 View 须要频繁刷新,或者刷新时数据处理量很大,考虑用 SurfaceView 来替代 View。
//MainAtityjava
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); } } } }
//实体类android
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; } }
//效果图canvas
//,Main2Activityapp
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类ide
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; } }
//效果图ui