介绍
使用场景:
播放视频
绘制滚动图形
画板功能
歌词滚动
飞机大战
特点:
频繁的更新UI,内有双缓冲机制
代码
布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<SurfaceView
android:id="@+id/surfaceview"
android:layout_above="@id/buttonGroup"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/buttonGroup"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/last"
android:layout_weight="1"
android:onClick="click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="倒退"/>
<Button
android:id="@+id/play"
android:layout_weight="1"
android:onClick="click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="播放"/>
<Button
android:id="@+id/stop"
android:layout_weight="1"
android:onClick="click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止"/>
<Button
android:id="@+id/nest"
android:layout_weight="1"
android:onClick="click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="快进"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
MainActivity::
surfaceview:一个SurfaceView对应一个SurfaceHolder
surfaceholder:持有者,不能直接操作SurfaceView,通过SurfaceHolder控制
画画:paint+canves
new Paint():
setColor();
setStrokeWidth() 画笔宽度(画图)
setTextSize() 文字大小
setAntiAlias(); 抗锯齿 默认false
.
holder.lockCanves() 锁定画布
unlockCanvasAndPost();解除锁定
canves.drawPiont(X,Y,paint)
package com.example.day11;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.SeekBar;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
SurfaceView surfaceView;
MediaPlayer mediaPlayer=new MediaPlayer();
SurfaceHolder surfaceHolder;
SeekBar seekBar;
int isPlay=0;
Handler handler=new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if (msg.what==101) {
Log.i("yu", "设置进度条: "+isPlay);
seekBar.setProgress(isPlay);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seekBar=findViewById(R.id.seekbar);
initvideo();
initplay();
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int aa=0;
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
aa=i;
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
isPlay=aa;
mediaPlayer.seekTo(isPlay);
}
});
}
private void setProgress() {
//视频长度
int max = mediaPlayer.getDuration();
seekBar.setMax(max);
}
private void initplay() {
try {
mediaPlayer.setDataSource("http://uvideo.spriteapp.cn/video/2019/0512/56488d0a-7465-11e9-b91b-1866daeb0df1_wpd.mp4");
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
setProgress();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
private void initvideo() {
surfaceView=findViewById(R.id.surfaceview);
surfaceHolder=surfaceView.getHolder();
surfaceHolder.addCallback(this);
}
//创建
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
mediaPlayer.setDisplay(surfaceHolder);
}
//改变
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
//销毁
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
if (mediaPlayer!=null) {
mediaPlayer.stop();
mediaPlayer.release();//释放资源
mediaPlayer=null;
}
}
public void click(View view) {
switch (view.getId()){
//倒退
case R.id.last:
break;
//播放
case R.id.play:
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
new MyThread().start();
}else if(mediaPlayer.isPlaying()){
mediaPlayer.pause();
}
break;
//停止
case R.id.stop:
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
break;
//快进
case R.id.nest:
break;
}
}
private class MyThread extends Thread{
@Override
public void run() {
while (mediaPlayer.isPlaying()) {
isPlay = mediaPlayer.getCurrentPosition();
Log.i("yu", "不断读取; "+isPlay);
handler.sendEmptyMessage(101);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
滚动图形,文字
package com.example.day11_1;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
SurfaceView surfaceView;
SurfaceHolder holder;
int x=0;
int y=100;
int x1=200;
int y1=300;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
surfaceView=findViewById(R.id.surfaceview);
holder=surfaceView.getHolder();
holder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
new MyThread().start();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
private class MyThread extends Thread{
@Override
public void run() {
Paint paint = new Paint();
paint.setTextSize(50);//字体大小
paint.setStrokeWidth(30); //画笔宽度
paint.setColor(Color.BLUE);//颜色
paint.setAntiAlias(true);//抗锯齿
while (true) {
Canvas canvas = holder.lockCanvas();
if (canvas==null) {
break;
}
if (x==getWindowManager().getDefaultDisplay().getWidth()) {
x=0;
}
if (y1==getWindowManager().getDefaultDisplay().getHeight()) {
y1=0;
}
//擦除之前的
canvas.drawColor(Color.WHITE, PorterDuff.Mode.CLEAR);
canvas.drawText("aaa",x+=5,y,paint);
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher),x1,y1+=5,paint);
holder.unlockCanvasAndPost(canvas);
}
}
}
}
滚动歌词
package com.example.day11_playmusic;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
List<Music> lists=new ArrayList<>();
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
MediaPlayer mediaPlayer=new MediaPlayer();
int position=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView=findViewById(R.id.surfaceview);
surfaceHolder=surfaceView.getHolder();
surfaceHolder.addCallback(this);
readJsonString();
initplay();
initTimer();
}
private void initTimer() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
int currentPosition = mediaPlayer.getCurrentPosition();
if (lists.size()>0) {
if (currentPosition>lists.get(position+1).getStart()) {
position++;
}
}
}
},0,500);
}
private void initplay() {
try {
mediaPlayer.setDataSource("/sdcard/Music/凤凰传奇 - 最炫民族风(Live).mp3");
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
Log.i("yu", "准备好播放: ");
mediaPlayer.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
private void readJsonString() {
try {
BufferedReader br = new BufferedReader(new FileReader("/sdcard/Download/最炫民族风1.txt"));
StringBuffer sb = new StringBuffer();
String str="";
while ((str=br.readLine())!=null) {
sb.append(str);
Log.i("yu", "readJsonString: "+sb.toString());
}
Bean bean = new Gson().fromJson(sb.toString(), Bean.class);
String lyric1 = bean.getLrc().getLyric();
Log.i("yu", "lyric1: "+lyric1);
String[] strings = lyric1.split("\n");
for (int i = 0; i < strings.length; i++) {
String[] split = strings[i].split("]");
if (split.length>=2) {
int minute = Integer.parseInt(split[0].substring(1, 3));
int second =Integer.parseInt(split[0].substring(4,6));
int miao = Integer.parseInt(split[0].substring(7,10));
int start = (minute * 60000) + (second * 1000) + miao;
String text = split[1];
lists.add(new Music(start,text));
Log.i("yu", "时长 : "+(minute*60000)+(second*1000)+miao);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
new MusicThread().start();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
private class MusicThread extends Thread{
@Override
public void run() {
Log.i("yu", "开始画: ");
Paint paint = new Paint();
paint.setStrokeWidth(20);
paint.setAntiAlias(true);
paint.setTextSize(50);
while(true){
Canvas canvas = surfaceHolder.lockCanvas();
if (canvas==null) {
break;
}
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
for (int i = 0; i <= position - 1; i++) {
paint.setColor(Color.BLUE);
canvas.drawText(lists.get(i).getText(),200,400-(position-i)*50,paint);
}
if (lists.size()>0) {
paint.setColor(Color.GREEN);
canvas.drawText(lists.get(position).getText(),200,400,paint);
}
for (int i = position+1; i <= lists.size() - 1; i++) {
paint.setColor(Color.BLUE);
canvas.drawText(lists.get(i).getText(),200,400+(i-position)*50,paint);
}
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}