Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發之自定義View開發及實例詳解

Android開發之自定義View開發及實例詳解

編輯:關於Android編程

在開發Android應用的過程中,難免需要自定義View,其實自定義View不難,只要了解原理,實現起來就沒有那麼難。   其主要原理就是繼承View,重寫構造方法、onDraw,(onMeasure)等函數。我自定義了個虛擬按鍵的View,  首先得自己寫個自定義View類,這裡我寫了個VirtualKeyView類,繼承自View類,實現了構造方法以及onDraw方法,以及實現了鍵盤按鍵的接口事件,實現代碼如下:   復制代碼 package com.czm.customview;     import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View;   public class VirtualKeyView extends View{       private static final boolean bDebug = true;     private static final String TAG = VirtualKeyView.class.getSimpleName();          private Context mContext;          private Bitmap bmpRound;     private Bitmap bmpRound_press;     private Bitmap bmpOk;     private Bitmap bmpOk_press;       private int mWidth;//真實寬度          private int widthBg = 584;     //private int widthItemBg = 292;     private int widthMid = 220;//中心寬度          private int cir_Centre_X = 292;//圓心位置     private int cir_Centre_Y = 292;//圓心位置     private int bigRadius = 292;     private int smallRadius = 110;     private int smallCir_X = 182;     private int smallCir_Y = 182;     private float scale = 1.0f;          private boolean isInit = false;          private int inputPress = -1;//顯示點擊了哪個鍵            public VirtualKeyView(Context context) {         super(context);         // TODO Auto-generated constructor stub         mContext = context;     }          public VirtualKeyView(Context context, AttributeSet attrs) {         super(context, attrs);         // TODO Auto-generated constructor stub         mContext = context;     }   private void initData() {                  mWidth = getWidth();         scale = mWidth*1.0f/widthBg;                  cir_Centre_X = (int) (cir_Centre_X*scale);         cir_Centre_Y = (int) (cir_Centre_Y*scale);         bigRadius = (int) (bigRadius*scale);         smallRadius = (int) (smallRadius*scale);         smallCir_X = (int) (smallCir_X*scale);         smallCir_Y = (int) (smallCir_Y*scale);                  initView();         isInit = true;     }          private void initView() {         if(mWidth == widthBg){             bmpRound = Utils.decodeCustomRes(mContext, R.drawable.controller_round);             bmpRound_press= Utils.decodeCustomRes(mContext, R.drawable.controller_round_bg_pressed);             bmpOk= Utils.decodeCustomRes(mContext, R.drawable.controller_ok);             bmpOk_press= Utils.decodeCustomRes(mContext, R.drawable.controller_ok_pressed);         } else {             int mid = (int) (widthMid*scale);             Bitmap bitmapTmp = Utils.decodeCustomRes(mContext, R.drawable.controller_round);             bmpRound = Bitmap.createScaledBitmap(bitmapTmp, mWidth, mWidth, true);             bitmapTmp.recycle();             bitmapTmp = null;                          bitmapTmp = Utils.decodeCustomRes(mContext, R.drawable.controller_round_bg_pressed);             bmpRound_press = Bitmap.createScaledBitmap(bitmapTmp, mWidth, mWidth, true);             bitmapTmp.recycle();             bitmapTmp = null;               bitmapTmp = Utils.decodeCustomRes(mContext, R.drawable.controller_ok);             bmpOk = Bitmap.createScaledBitmap(bitmapTmp, mid, mid, true);             bitmapTmp.recycle();             bitmapTmp = null;                          bitmapTmp = Utils.decodeCustomRes(mContext, R.drawable.controller_ok_pressed);             bmpOk_press = Bitmap.createScaledBitmap(bitmapTmp, mid, mid, true);             bitmapTmp.recycle();             bitmapTmp = null;         }         System.gc();     }          public void  recycle() {         if (bmpRound != null && !bmpRound.isRecycled()) {             bmpRound.recycle();             bmpRound = null;         }         if (bmpRound_press != null && !bmpRound_press.isRecycled()) {             bmpRound_press.recycle();             bmpRound_press = null;         }         if (bmpOk != null && !bmpOk.isRecycled()) {             bmpOk.recycle();             bmpOk = null;         }         if (bmpOk_press != null && !bmpOk_press.isRecycled()) {             bmpOk_press.recycle();             bmpOk_press = null;         }         System.gc();     }          @Override     protected void onDraw(Canvas canvas) {         // TODO Auto-generated method stub         super.onDraw(canvas);         if(!isInit){             initData();         }         canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG                 | Paint.FILTER_BITMAP_FLAG));// 抗鋸齒         drawCir(canvas);     }          private void drawCir(Canvas canvas) {         switch (inputPress) {         case -1:             //無按鍵             canvas.drawBitmap(bmpRound, 0, 0, null);             canvas.drawBitmap(bmpOk, smallCir_X , smallCir_Y, null);             break;         case KeyEvent.KEYCODE_DPAD_CENTER:             //中心Ok鍵             canvas.drawBitmap(bmpRound, 0, 0, null);             canvas.drawBitmap(bmpOk_press, smallCir_X , smallCir_Y, null);             break;         case KeyEvent.KEYCODE_DPAD_UP:             //上             drawBg(canvas,180);             canvas.drawBitmap(bmpOk, smallCir_X , smallCir_Y, null);             break;         case KeyEvent.KEYCODE_DPAD_DOWN:             //下             drawBg(canvas,0);             canvas.drawBitmap(bmpOk, smallCir_X , smallCir_Y, null);             break;         case KeyEvent.KEYCODE_DPAD_LEFT:             //左             drawBg(canvas,90);             canvas.drawBitmap(bmpOk, smallCir_X , smallCir_Y, null);             break;         case KeyEvent.KEYCODE_DPAD_RIGHT:             //右             drawBg(canvas,270);             canvas.drawBitmap(bmpOk, smallCir_X , smallCir_Y, null);             break;                      default:             break;         }     }          private void drawBg(Canvas canvas,int rotate) {         canvas.save();    //保存canvas狀態         canvas.rotate(rotate,cir_Centre_X,cir_Centre_Y);         canvas.drawBitmap(bmpRound_press, 0, 0, null);//這裡畫的是旋轉後的         canvas.restore();// 恢復canvas狀態     }          public boolean onTouchEvent(MotionEvent event) {         if (bDebug)             Log.d(TAG, "event.getAction() = " + event.getAction());         if (event.getAction() == MotionEvent.ACTION_DOWN) {                 // 計算圓選擇的哪個字母                 int x1 = (int) (event.getX() - cir_Centre_X);                 int y1 = (int) (event.getY() - cir_Centre_Y);                 if (bDebug)                     Log.d(TAG, "x= " + x1 + ", y = " + y1);                 int x2 = x1 * x1;                 int y2 = y1 * y1;                 int bigRadius2 = bigRadius * bigRadius;                 int smallRadius2 = smallRadius * smallRadius;                 if (x2 + y2 < bigRadius2) {                     // 表示在畫圓形之內,才有繼續計算的必要                     if (x2 + y2 < smallRadius2) {                         // 如果再小圓內                         setOnKeyDown(KeyEvent.KEYCODE_DPAD_CENTER);                     } else if (y1 > x1) {                         if (y1 > -x1) {                             // 下                             setOnKeyDown(KeyEvent.KEYCODE_DPAD_DOWN);                         } else {                             // 左                             setOnKeyDown(KeyEvent.KEYCODE_DPAD_LEFT);                         }                     } else if (y1 < x1) {                         if (y1 > -x1) {                             // 右                             setOnKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT);                         } else {                             // 上                             setOnKeyDown(KeyEvent.KEYCODE_DPAD_UP);                         }                     }                 }                 // isShowCir = false;                 postInvalidate();             return true;         }           if (event.getAction() == MotionEvent.ACTION_UP) {                 // 計算圓選擇的哪個字母                   int x1 = (int) (event.getX() - cir_Centre_X);                 int y1 = (int) (event.getY() - cir_Centre_Y);                 if (bDebug)                     Log.d(TAG, "x= " + x1 + ", y = " + y1);                 int x2 = x1 * x1;                 int y2 = y1 * y1;                 int bigRadius2 = bigRadius * bigRadius;                 int smallRadius2 = smallRadius * smallRadius;                 if (x2 + y2 < bigRadius2) {                     // 表示在畫圓形之內,才有繼續計算的必要                     if (x2 + y2 < smallRadius2) {                         // 如果再小圓內                         setOnKeyUp(KeyEvent.KEYCODE_DPAD_CENTER);                     } else if (y1 > x1) {                         if (y1 > -x1) {                             // 下                             setOnKeyUp(KeyEvent.KEYCODE_DPAD_DOWN);                         } else {                             // 左                             setOnKeyUp(KeyEvent.KEYCODE_DPAD_LEFT);                         }                     } else if (y1 < x1) {                         if (y1 > -x1) {                             // 右                             setOnKeyUp(KeyEvent.KEYCODE_DPAD_RIGHT);                         } else {                             // 上                             setOnKeyUp(KeyEvent.KEYCODE_DPAD_UP);                         }                     }                   }                 postInvalidate();         }         return true;     }          private void setOnKeyDown(int keyCode) {         if(bDebug)             Log.d(TAG, "keyCode = "+keyCode);         inputPress = keyCode;         if(myIntputCallBack != null){             myIntputCallBack.intputDown(keyCode);         }     }          private void setOnKeyUp(int keyCode) {         inputPress = -1;         if(myIntputCallBack != null){             myIntputCallBack.intputUp(keyCode);         }     }          /******************* 輸入回調函數 ********************/     private IntputCallBack myIntputCallBack = null;       public interface IntputCallBack {         void intputDown(int keyCode);         void intputUp(int keyCode);     }       public void setOnInputCallBack(IntputCallBack myIntputCallBack) {         this.myIntputCallBack = myIntputCallBack;     } } 復制代碼 在xml布局文件裡面如何使用上面自定義的View視圖控件呢?很簡單就是 和 使用<TextView> 一樣,只需寫全路徑即可:本例中如下:   在main.xml的UI布局文件中加入:   復制代碼 <com.czm.customview.VirtualKeyView         android:id="@+id/virtualKeyView"         android:layout_marginTop="20dp"         android:layout_width="250dp"         android:layout_height="250dp"         android:layout_centerHorizontal="true"          /> 復制代碼 在看看 如何在java類文件中使用 該 VirtualKeyView視圖控件呢,這個時候就和 普通的TextView視圖一樣使用了,本例中   在MainActivity中使用如下:   復制代碼 package com.czm.customview;     import com.czm.customview.VirtualKeyView.IntputCallBack;   import android.os.Bundle; import android.app.Activity; import android.view.KeyEvent; import android.widget.Toast;   public class MainActivity extends Activity {       private VirtualKeyView virtualKeyView;       @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.main);           virtualKeyView = (VirtualKeyView) findViewById(R.id.virtualKeyView);           virtualKeyView.setOnInputCallBack(new IntputCallBack() {               @Override             public void intputUp(int keyCode) {               }               @Override             public void intputDown(int keyCode) {                 if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {                     showToast("您按了 上 鍵");                 } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {                     showToast("您按了 下 鍵");                 } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {                     showToast("您按了 左 鍵");                 } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {                     showToast("您按了 右 鍵");                 } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {                     showToast("您按了 OK 鍵");                 }               }         });       }     private void showToast(String msg){         Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();     }          @Override     public void onDestroy() {         super.onDestroy();         virtualKeyView.recycle();     }   } 復制代碼 Utils.java文件中的decodeCustomRes方法實現如下:   復制代碼 package com.czm.customview;   import java.io.InputStream;   import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory;   public class Utils {     public static Bitmap decodeCustomRes(Context c, int res) {         InputStream is = c.getResources().openRawResource(res);         BitmapFactory.Options options = new BitmapFactory.Options();         options.inJustDecodeBounds = false;         options.inSampleSize = 1;//表示原尺寸加載圖片,不縮放         Bitmap bmp = BitmapFactory.decodeStream(is, null, options);         return bmp;     } }
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved