SurfaceView
- Surface——表面,這個概念在圖形編程中常常被提到。基本上我們可以把它當作顯存的一個映射,寫入到Surface 的內容 可以被直接複製到顯存從而顯示出來,這使得顯示速度非常快。
- 可以直接從內存或者DMA【直接存儲器訪問(Direct Memory Access)】等硬件接口取得圖像數據,是個非常重要的繪圖容器。
- 它的特性是:可以在主線程之外的線程中向屏幕繪圖。這樣可以避免畫圖任務繁重的時候造成主線程阻塞,從而提高了程序的反應速度。當界面的動畫元素較多,而且很多都需要通過定時器來控制這些動畫元素的移動,就考慮使用SurfaceView。遊戲開發中多用到SurfaceView,遊戲中的背景、人物、動畫等等儘量在畫布canvas中畫出。
- View缺乏雙緩衝機制;
- 當程序需要更新View上的圖像時,程序必須重繪View上顯示的整張圖片;
- 新線程無法直接更新View組件。
A. 具有獨立的繪圖表面;B. 需要在宿主窗口上挖一個洞來顯示自己;C. 它的UI繪製可以在獨立的線程中進行,這樣就可以進行復雜的UI繪製,並且不會影響應用程序的主線程響應用戶輸入。
- SurfaceView.getHolder()獲得SurfaceHolder對象 ---->
- SurfaceHolder.addCallback(callback)添加回調方法---->
- 實現SurfaceHolder.Callback接口 ,重寫其中的方法---->
- SurfaceHolder.lockCanvas()獲得Canvas對象並鎖定畫布---->
- Canvas繪畫 ---->
- SurfaceHolder.unlockCanvasAndPost(Canvas canvas)結束鎖定畫圖,並提交改變,將圖形顯示。
(1)、abstract void addCallback(SurfaceHolder.Callback callback);
給SurfaceView當前的持有者一個回調對象。
(2)、abstract Canvas lockCanvas();
鎖定畫布,一般在鎖定後就可以通過其返回的畫布對象Canvas,在其上面畫圖等操作了。
(3)、abstract Canvas lockCanvas(Rect dirty);
鎖定畫布的某個區域進行畫圖等..因爲畫完圖後,會調用下面的unlockCanvasAndPost來改變顯示內容。
相對部分內存要求比較高的遊戲來說,可以不用重畫dirty外的其它區域的像素,只對Rect所圈出來的區域進行更新,通過這種方式可以提高畫面的更新速度。
(4)、abstract void unlockCanvasAndPost(Canvas canvas);
結束鎖定畫圖,並提交改變。
B、將定義好的路徑繪製在畫布上:1、addArc() 添加弧形路徑2、addCircle() 添加圓形路徑3、addOval() 添加橢圓形路徑4、addRect() 添加矩形路徑5、addRoundRect() 添加圓角矩形路徑6、moveTo() 設置繪製直線的起始點7、lineTo() 繪製直線8、quadTo() 繪製線段軌跡9、close() 閉合路徑
三、實例代碼:1、drawPath() : 繪製路徑2、drawTextOnPath() : 沿着指定路徑繪製字符串
publicclass MainActivity extends Activity {
private SurfaceView surfaceView_main;
private SurfaceHolder surfaceHolder;
private MediaPlayer mediaPlayer = null;
private String filePath = "";
privateintposition = 0;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
filePath = "/mnt/sdcard/Download/2050.3gp";
mediaPlayer = new MediaPlayer();
surfaceView_main = (SurfaceView) findViewById(R.id.surfaceView_main);
surfaceHolder = surfaceView_main.getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
publicvoid surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
publicvoid surfaceCreated(SurfaceHolder holder) {
if (position > 0) {
play();
mediaPlayer.seekTo(position);
position = 0;
}
}
@Override
publicvoid surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
}
});
}
publicvoid clickButton(View view) {
switch (view.getId()) {
case R.id.imageView_main_play:
if (!mediaPlayer.isPlaying()) {
play();
}
break;
case R.id.imageView_main_pause:
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
} else {
mediaPlayer.start();
}
break;
case R.id.imageView_main_stop:
mediaPlayer.stop();
break;
}
}
privatevoid play() {
try {
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(filePath);
mediaPlayer.setDisplay(surfaceHolder);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protectedvoid onPause() {
super.onPause();
if (mediaPlayer.isPlaying()) {
position = mediaPlayer.getCurrentPosition();
mediaPlayer.pause();
}
}
@Override
protectedvoid onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
}
}
@Override
publicboolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
returntrue;
}
}
publicclass MainActivity extends Activity {
private SurfaceView surfaceView_main;
private SurfaceHolder surfaceHolder;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView_main = (SurfaceView) findViewById(R.id.surfaceView_main);
surfaceHolder = surfaceView_main.getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
publicvoid surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
publicvoid surfaceCreated(SurfaceHolder holder) {
new MyThread().start();
}
@Override
publicvoid surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
}
});
}
class MyThread extends Thread {
@Override
publicvoid run() {
super.run();
Bitmap bitmapBg = null;
Bitmap bitmapBear = null;
int count = 1;
int bgX = 0;
intbearX = 0;
AssetManager assetManager = getResources().getAssets();
try {
bitmapBg = BitmapFactory.decodeStream(assetManager
.open("bg.png"));
while (true) {
bitmapBear = BitmapFactory.decodeStream(assetManager
.open("bear" + count + ".png"));
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.GRAY);
Paint paint = new Paint();
canvas.drawBitmap(bitmapBg, bgX, 0, paint);
canvas.drawBitmap(bitmapBg, bgX - 1024, 0, paint);
canvas.drawBitmap(bitmapBear, 200, 100, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
bgX += 2;
if (bgX > 1024) {
bgX = 0;
}
Thread.sleep(30);
count++;
if (count > 8) {
count = 1;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
publicboolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
returntrue;
}
}
publicclass MainActivity extends Activity {
private Camera mCamera = null;
private SurfaceView surfaceView_main;
private SurfaceHolder surfaceHolder;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
privatevoid initSurfaceView() {
surfaceView_main = (SurfaceView) findViewById(R.id.surfaceView_main);
surfaceHolder = surfaceView_main.getHolder();
// surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
publicvoid surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
}
}
@Override
publicvoid surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
publicvoid surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
}
});
}
@Override
protectedvoid onResume() {
super.onResume();
if (mCamera == null) {
mCamera = Camera.open();
}
}
@Override
protectedvoid onPause() {
super.onPause();
if (mCamera != null) {
mCamera.release();
}
}
publicvoid clickButton(View view) {
switch (view.getId()) {
case R.id.button_main_preview:
initSurfaceView();
break;
case R.id.button_main_takepicture:
mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
break;
}
}
ShutterCallback shutterCallback = new ShutterCallback() {
@Override
publicvoid onShutter() {
// TODO Auto-generated method stub
}
};
PictureCallback rawCallback = new PictureCallback() {
@Override
publicvoid onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
}
};
PictureCallback jpegCallback = new PictureCallback() {
@Override
publicvoid onPictureTaken(byte[] data, Camera camera) {
setTitle(data.length + "");
}
};
@Override
publicboolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
returntrue;
}
}
良心的公衆號,更多精品文章,不要忘記關注哈
《Android和Java技術棧》