SurfaceView
程序员文章站
2022-03-29 19:29:08
...
SurfaceView
一.使用SurfaceView播放视频
1.布局
<LinearLayout 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"
android:orientation="vertical">
<SurfaceView
android:layout_width="match_parent"
android:layout_height="400dp"
android:id="@+id/surfaceview"></SurfaceView>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:id="@+id/progressbar"></SeekBar>
</LinearLayout>
2.MainActivity代码
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private SurfaceView surfaceview;
private SeekBar progressbar;
MediaPlayer mediaPlayer = new MediaPlayer();
SurfaceHolder surfaceHolder;
Timer timer = new Timer();
String video;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceview = (SurfaceView) findViewById(R.id.surfaceview);
progressbar = (SeekBar) findViewById(R.id.progressbar);
surfaceHolder = surfaceview.getHolder();
surfaceHolder.addCallback(this);
Intent intent = getIntent();
// video = intent.getStringExtra("video");
Toast.makeText(this,""+video,Toast.LENGTH_SHORT).show();
try {
initplayer();
} catch (IOException e) {
e.printStackTrace();
}
progressbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (b){
mediaPlayer.seekTo(seekBar.getProgress());
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
private void initplayer() throws IOException {
if (mediaPlayer!=null){
mediaPlayer.reset();
mediaPlayer.setDataSource("http://tvideo.spriteapp.cn/video/2019/0910/5d7691e370b3c_wpd.mp4");
mediaPlayer.setDataSource(video);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
int videoWidth = mediaPlayer.getVideoWidth();
}
});
timer.schedule(new TimerTask() {
@Override
public void run() {
int duration = mediaPlayer.getDuration();
int currentPosition = mediaPlayer.getCurrentPosition();
int i = currentPosition * 100 / duration;
progressbar.setProgress(i);
}
},0,1000);
}
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d("zyj", "创建了: ");
mediaPlayer.setDisplay(surfaceHolder);
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
Log.d("zyj", "改变了: ");
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d("zyj", "销毁了: ");
if (mediaPlayer!=null){
mediaPlayer.release();
mediaPlayer=null;
}
if (timer!=null){
timer.cancel();
}
}
}
二.使用SurfaceView绘制各种图形
1.绘制各种图形
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private SurfaceView surfaceview;
private SurfaceHolder surfaceHolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceview = (SurfaceView) findViewById(R.id.surfaceview);
surfaceHolder = surfaceview.getHolder();
surfaceHolder.addCallback(this);
}
//创建
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
//TODO:1.画笔
Paint paint = new Paint();
//TODO:2.设置笔的颜色
paint.setColor(Color.BLUE);
//设置画笔样式,fill是实心,stoke是空心,fill_or_stoke:同时实心与空心
// paint.setStyle(Paint.Style.FILL);
// paint.getTextSize(float textsize)//设置绘制文字的字号大小
// paint.setAntiAlias(true);//抗锯齿
//TODO:3.设置线条宽度
paint.setStrokeWidth(20);
////TODO:3.画布
Canvas canvas = surfaceHolder.lockCanvas();//锁定画布
canvas.drawColor(Color.WHITE);//设置画布颜色
//画一条线
canvas.drawLine(0,0,500,500,paint);
//画一个点
canvas.drawPoint(300,300,paint);
//画一个圆形(oval是椭圆)
canvas.drawOval(200,200,400,400,paint);
//画文字
/**
* 参数1:要从第几个文字开始绘制
* 参数2:要绘制到第几个文字
* 参数3:文本的X轴的开始位置
* 参数4:文本的Y轴的结束位置
* 参数5 画笔对象
*/
canvas.drawText("开始写字了",50,50,paint);
/**
* 参数1:路径
* 参数2:距离路径开始位置的偏移量
* 参数3:距离路径上下的偏移量
* 参数4:画笔对象
*/
// canvas.drawTextOnPath("123456789",path,0,-50,paint);
//画矩形
/**
* 参数1:float left
* 参数2:float top
* 参数3:float right
* 参数4:float buttom
*/
canvas.drawRect(100,100,200,200,paint);
//画圆角矩形
RectF rectF = new RectF(80, 260, 200, 300);//设置个新的长方形
canvas.drawRoundRect(rectF,20,5,paint);//第二个参数是X半径,第三个参数是Y半径
//画扇形
canvas.drawArc(500,500,700,700,20,180,true,paint);
surfaceHolder.unlockCanvasAndPost(canvas);//解锁画布
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
}
三.播放音乐的时候,滚动歌词
1. xml布局
<LinearLayout 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=".MusicActivity"
android:orientation="vertical">
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/surfaceview3"></SurfaceView>
</LinearLayout>
2.MainActivity中代码
public class MusicActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private Timer timer = new Timer();
private SurfaceView surfaceview3;
ArrayList<Music>list = new ArrayList<>();
private MediaPlayer mediaPlayer = new MediaPlayer();
SurfaceHolder surfaceHolder;
int position;//正在显示的歌词的下标
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music);
surfaceview3 = (SurfaceView) findViewById(R.id.surfaceview3);
surfaceHolder = surfaceview3.getHolder();
surfaceHolder.addCallback(this);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE},100);
}
try {
initCi(); //解析歌词
initPlayer(); //播放音乐
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void initPlayer() throws IOException {
if (mediaPlayer!=null){
mediaPlayer.reset();
mediaPlayer.setDataSource("/sdcard/凤凰传奇 - 最炫民族风(Live).mp3");
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(final MediaPlayer mediaPlayer) {
mediaPlayer.start();
timer.schedule(new TimerTask() {
@Override
public void run() {
if (list.size()>0&& position+1<list.size()){
int currentPosition = mediaPlayer.getCurrentPosition();
if (currentPosition>=list.get(position+1).getStart_time()) {
position++;
}
}
}
},0,100);
}
});
}
}
private void initCi() throws IOException {
//TODO 1:读取SD卡的歌词 json串
FileInputStream fileInputStream = new FileInputStream("/sdcard/最炫民族风");
StringBuffer stringBuffer = new StringBuffer();
byte[] bytes = new byte[1024];
int len=0;
while((len=fileInputStream.read(bytes))!=-1){
stringBuffer.append(new String(bytes,0,len));
}
//TODO 2:解析json串获得整首歌的歌词
Gson gson = new Gson();
Bean bean = gson.fromJson(stringBuffer.toString(), Bean.class);
String lyric = bean.getLrc().getLyric();
Log.d("zjy", "initCi: "+lyric);
//TODO 3:按照\n进行切割得到每句歌词
String[] split = lyric.split("\n");
for (int i = 1; i < split.length; i++) {
String replace = split[i].replace("[", "")
.replaceFirst(":","@")//只替换第一个
.replace(".","@")
.replace("]","@");
Log.d("zjy", "initCi: "+replace);
String[] split1 = replace.split("@");
int start_time= Integer.parseInt(split1[0])*60*1000+Integer.parseInt(split1[1])*1000+Integer.parseInt(split1[2]);
if (split1.length>=4){
list.add(new Music(split1[3],start_time));
}
}
//TODO 4:打印集合数据
for (Music music:list){
Log.d("zjy", "initCi: "+music);
}
}
@Override
public void surfaceCreated(final SurfaceHolder surfaceHolder) {
new Thread(new Runnable() {
@Override
public void run() {
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setTextSize(40);
while (true){
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
canvas.drawText(list.get(position).getText(),200,300,paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}).start();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
}
3.Bean类(歌词类)
package com.example.app2.bean;
public 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;
}
}
}
4.实体类
package com.example.app2.entity;
public class Music {
private String text;
private long 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;
}
@Override
public String toString() {
return "Music{" +
"text='" + text + '\'' +
", start_time=" + start_time +
'}';
}
}
上一篇: 如何在markdown中打出上标、下标和一些特殊符号
下一篇: windows安装mysql5.7
推荐阅读
-
android使用surfaceview+MediaPlayer播放视频
-
Cocos2d游戏开发学习记录——1.Surface、SurfaceView、SurfaceHolder实现简单的游戏demo
-
Android SurfaceView拍照录像实现方法
-
Android利用SurfaceView实现简单计时器
-
利用SurfaceView实现下雨与下雪动画效果详解(Kotlin语法)
-
Android SurfaceView拍照录像实现方法
-
利用SurfaceView实现下雨与下雪动画效果详解(Kotlin语法)
-
android图像绘制(四)自定义一个SurfaceView控件
-
Android截屏SurfaceView黑屏问题的解决办法
-
Android利用SurfaceView实现下雨的天气动画效果