本節講解使用SurfaceView組件繪制動畫的方法。SurfaceView類作為View類的子類,進行繪圖時能夠比一般的View組件更快,所以我們在Android游戲、視頻等對流暢度和幀速要求較高的應用中經常會見到SurfaceView的身影。
本文通過實例講解的方式來介紹SurfaceView的使用方法,此實例實現的是一個能發送莫爾斯碼的燈塔。下面是詳細步驟,代碼中的注釋可以幫助大家理解。
1、創建項目Lesson25_Morse,啟動Activity名字叫MainActivity.java。
2、創建一個莫爾斯碼的工具類Morse.java。
Java代碼
- package basic.android.lesson37;
-
- import java.util.HashMap;
- import java.util.Map;
-
- public class Morse {
-
- public static Map<STRING string ,> standardMorseCharactersMap = new HashMap</STRING><STRING string ,>();
-
- static {
- standardMorseCharactersMap.put("a", ".-");
- standardMorseCharactersMap.put("b", "-...");
- standardMorseCharactersMap.put("c", "-.-.");
- standardMorseCharactersMap.put("d", "-..");
- standardMorseCharactersMap.put("e", ".");
- standardMorseCharactersMap.put("f", "..-.");
- standardMorseCharactersMap.put("g", "--.");
- standardMorseCharactersMap.put("h", "....");
- standardMorseCharactersMap.put("i", "..");
- standardMorseCharactersMap.put("j", ".---");
- standardMorseCharactersMap.put("k", "-.-");
- standardMorseCharactersMap.put("l", ".-..");
- standardMorseCharactersMap.put("m", "--");
- standardMorseCharactersMap.put("n", "-.");
- standardMorseCharactersMap.put("o", "---");
- standardMorseCharactersMap.put("p", ".--.");
- standardMorseCharactersMap.put("q", "--.-");
- standardMorseCharactersMap.put("r", ".-.");
- standardMorseCharactersMap.put("s", "...");
- standardMorseCharactersMap.put("t", "-");
- standardMorseCharactersMap.put("u", "..-");
- standardMorseCharactersMap.put("v", "...-");
- standardMorseCharactersMap.put("w", ".--");
- standardMorseCharactersMap.put("x", "-..-");
- standardMorseCharactersMap.put("y", "-.--");
- standardMorseCharactersMap.put("z", "--..");
-
- standardMorseCharactersMap.put("0", "-----");
- standardMorseCharactersMap.put("1", ".----");
- standardMorseCharactersMap.put("2", "..---");
- standardMorseCharactersMap.put("3", "...--");
- standardMorseCharactersMap.put("4", "....-");
- standardMorseCharactersMap.put("5", ".....");
- standardMorseCharactersMap.put("6", "-....");
- standardMorseCharactersMap.put("7", "--...");
- standardMorseCharactersMap.put("8", "---..");
- standardMorseCharactersMap.put("9", "----.");
-
- standardMorseCharactersMap.put(".", ".-.-.-");
- standardMorseCharactersMap.put("-", "-....-");
- standardMorseCharactersMap.put(",", "--..--");
- standardMorseCharactersMap.put("?", "..--..");
- standardMorseCharactersMap.put("/", "-..-.");
- standardMorseCharactersMap.put(";", "-.-.-.");
- standardMorseCharactersMap.put("(", "-.--.");
- standardMorseCharactersMap.put(")", "-.--.-");
- standardMorseCharactersMap.put("@", ".--.-.");
- standardMorseCharactersMap.put("*", "...-.-");
- standardMorseCharactersMap.put("+", ".-.-.");
- standardMorseCharactersMap.put("%", ".-...");
- standardMorseCharactersMap.put("\\", "---...");
- standardMorseCharactersMap.put("\"", ".-..-.");
- standardMorseCharactersMap.put("'", ".----.");
- standardMorseCharactersMap.put("!", "=---.");
- standardMorseCharactersMap.put("$", "...-..-");
- standardMorseCharactersMap.put(" ", "/");
- }
-
- public static String morseEncoder(String input) {
- String output = "";
- for (char c : input.toCharArray()) {
- output += standardMorseCharactersMap.get(String.valueOf(c)) + " ";
- }
- return output;
- }
-
- public static void main(String[] args) {
- String input = "yao mu yang";
- String output = Morse.morseEncoder(input);
- System.out.println(output);
- }
-
- }</STRING>
3、布局文件main.xml 的內容如下:
XML/HTML代碼
- <?xml version="1.0" encoding="utf-8"?>
- <LINEARLAYOUT xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/LinearLayout01" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
-
- <TEXTVIEW android:id="@+id/TextView01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="輸入:">
- </TEXTVIEW>
-
- <EDITTEXT android:id="@+id/EditText01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="">
- </EDITTEXT>
-
- <BUTTON type=submit android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="轉換">
- </BUTTON>
-
- <TEXTVIEW android:id="@+id/TextView02" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="輸出:">
- </TEXTVIEW>
-
- <EDITTEXT android:id="@+id/EditText02" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="" android:editable="false">
- </EDITTEXT>
-
- <BUTTON type=submit android:id="@+id/Button02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="發送信號">
- </BUTTON>
- </LINEARLAYOUT>
4、MainActivity.java的內容如下:
Java代碼
- package basic.android.lesson37;
-
- import android.app.Activity;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.LinearLayout;
-
- public class MainActivity extends Activity {
- private LinearLayout layout;
-
- //莫爾斯碼數組變量
- char[] chars;
- //莫爾斯碼數組計數變量
- int count = 0;
- //開關標志
- boolean flag = false;
- //循環標志
- boolean loop = false;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- // 定義UI組件
- final Button b1 = (Button) findViewById(R.id.Button01);
- final Button b2 = (Button) findViewById(R.id.Button02);
-
- final EditText et1 = (EditText) findViewById(R.id.EditText01);
- final EditText et2 = (EditText) findViewById(R.id.EditText02);
-
- layout = (LinearLayout) findViewById(R.id.LinearLayout01);
-
- // 單擊轉換按鈕,轉換莫爾斯碼
- b1.setOnClickListener(new View.OnClickListener(){
-
- @Override
- public void onClick(View v) {
- String text = Morse.morseEncoder(et1.getText().toString());
- et2.setText(text);
- }
- });
-
- // 單擊發送信號按鈕,把莫爾斯碼用燈信號的方式發送出去
- b2.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- //當morse碼文本框中有內容的時候就發送燈信號
- if (et2.getText() != null && et2.getText().toString().length() > 0) {
- //把莫爾斯碼拆解成一個一個字符
- chars = et2.getText().toString().toCharArray();
- //計數
- count = chars.length;
- //創建SurfaceView
- LightView light = new LightView(MainActivity.this);
- //把SurfaceView動態加入Activity
- layout.addView(light);
- }
- }
- });
- }
-
- // 信號燈
- class LightView extends SurfaceView {
-
- //聲明 surfaceHolder 對象
- SurfaceHolder holder;
-
- // 構造方法
- public LightView(Context context) {
- super(context);
-
- // 從 SurfaceView 中獲取 SurfaceHolder對象
- holder = this.getHolder();
- // addCallback 對象
- holder.addCallback(new SurfaceHolder.Callback() { //創建SurfaceHolder.Callback匿名內部類
-
- //在SurfaceHolder.Callback內部類的內部創建它所需要的線程內部類
- class LightThread implements Runnable {
-
- @Override
- public void run() {
-
- while (loop) {
-
- if (count > 0) {
- Log.i("yao", "" + count);
- String s = String.valueOf(chars[chars.length - count]);
- // 鎖定canvas,開始繪圖
- Canvas canvas = holder.lockCanvas(null);
-
- Paint paint = new Paint();
- paint.setAntiAlias(true);
-
- //清屏幕
- paint.setColor(Color.BLACK);
- canvas.drawRect(0, 0, 480, 480, paint);
-
- //標志位是真的時候關一下燈
- if(flag){
- sleep(2);
- paint.setColor(Color.BLACK);
- }else{ //為假的時候就亮燈
- // di 亮2個時間點
- if (s.equalsIgnoreCase(".")) {
- sleep(2);
- paint.setColor(Color.YELLOW);
- } else if(s.equalsIgnoreCase("-")) {
- // dah 亮4個時間點
- sleep(4);
- paint.setColor(Color.YELLOW);
- }else if(s.equalsIgnoreCase(" ")){
- // 空格 亮2個時間點
- sleep(2);
- paint.setColor(Color.BLACK);
- }else if(s.equalsIgnoreCase("/")){
- // 單詞之間的空白亮2個時間點
- sleep(2);
- paint.setColor(Color.BLACK);
- }else{
- // 出問題的時候亮紅燈
- sleep(2);
- paint.setColor(Color.RED);
- }
- count--;
- }
- //繪制燈光
- canvas.drawCircle(250.0f, 200.0f, 100, paint);
-
- //標准位開關
- flag = !flag;
-
- // 釋放canvas,繪圖完畢
- holder.unlockCanvasAndPost(canvas);
- }
-
- }
-
- }
-
- //休眠
- public void sleep(int time){
- try {
- Thread.sleep(time*80);
- } catch (Exception e) {
- //no nothing
- }
- }
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- // do nothing
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- //在SurfaceView被創建的時候執行
- new Thread(new LightThread()).start();
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- loop = false;
- }
- });
-
- loop = true;
-
- }
- }
- }
5、編譯並運行程序,查看結果:
好了,本講就到這裡,下次再見。