Android 總結 - Canvas & Drawables

Canvas and Drawable

當想要畫2D圖形時,典型的有兩種方式:
a. 通過Layout把圖形或者動畫 draw 到一個View對象中。這種方式比較適合畫一個簡單的圖形不需要動態變化並且不是高性能的遊戲。通過Drawables瞭解更詳細的信息。
b. 直接把圖形畫到Canvas上。這種方式,你需要親自調用相關類的onDraw()方法 或者 Canvas類中的任一個draw開頭的方法(像drawPicture())。

  • 如果在UI thread中,你在Layout中創建了一個自定義View,調用invalidate() 方法然後處理onDraw() callback。
  • 或者, 不在UI thread, wherein you manage a SurfaceView and perform draws to the Canvas as fast as your thread is capable (you do not need to request invalidate()).

Draw with a Canvas

Canvas類擁有很多”draw” 方法. 想要繪製,需要4個基礎組件: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing).

On a View

  繼承View並且覆寫onDraw()回調方法,這個方法將被Android Framework調用去請求view繪製自己。View中的繪製工作都通過onDraw回調方法中的Canvas用來執行。
Android framework會在必要的時候調用onDraw方法。每次你的應用準備去被繪製的時候,你必須通過調用invalidate(如果不是主線程、則需要調用postInvalidate)方法來請求你的View被無效。這個表示你想要你的View被繪製並且Android將會調用View的onDraw方法。

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (mBitmap != null) {
        canvas.drawBitmap(mBitmap, 0, 0, null);
    }
}
@Override
public boolean onTouchEvent(MotionEvent event) {
    ... ...
    invalidate();
    return true;
}

On a SurfaceView

  通過SurfaceView,首先要創建一個新類繼承SurfaceView同時也應該實現SurfaceHolder.Callback。 這個回調函數是一個用來通知你關於Surface相關的信息,比如它什麼時候被創建、改變或者銷燬。
  我們應該通過使用SurfaceHolder來替換直接操作Surface對象。所以,當SurfaceView被初始化後通過調用getHolder來獲取SurfaceHolder 。你應該通知SurfaceHolder 你想要接收SurfaceHolder callbaks通過調用addCallback()。
  爲了能夠在別的線程中繪製到這個Surface Canvas中,必須傳遞SurfaceHolder然後通過lockCanvas來獲取Canvas。當完成繪製工作後通過調用unlockCanvasAndPost把繪製內容傳遞到Canvas中。這個Surface將會繪製剛纔那個Canvas。每次你想重繪製的時候都需要這麼執行這個locking and unlocking的順序

Drawables

Drawable類定義了好多特定類型的drawable圖形,包括了:BitmapDrawable, ShapeDrawable, PictureDrawable, LayerDrawable等等。下面是兩種定義和使用的方式:

Creating from resource images

通過image資源來創建,只需把需要用的image,放置到res/drawable/ 目錄下, 然後通過R.drawable.my_image來訪問。(在res/drawable/ 目錄下的圖片資源會被aapt壓縮優化,如果需要使用原圖片的字節流,請把圖片放到res/raw目錄下)

Creating from resource XML

通過XML資源來創建,一旦把Drawable定義在XML中,把文件保存在“res/drawable/”目錄下,然後通過“Resources.getDrawable()”獲取Drawable對象。

<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/image_expand">
    <item android:drawable="@drawable/image_collapse">
</transition>
Resources res = mContext.getResources();
TransitionDrawable transition = (TransitionDrawable)
    res.getDrawable(R.drawable.expand_collapse);
ImageView image = (ImageView) findViewById(R.id.toggle_image);
image.setImageDrawable(transition);

Shape Drawable

  當你想要動態的繪製一些二維圖形時,ShapeDrawable可以滿足這個需求。ShapeDrawable可以編程的方式繪製原始的圖形並且進行樣式化。
  ShapeDrawable主要包含三個主要的組件:Shape、Paint和Bounds。一定要調用setBounds方法,要不然shape不會被繪製。

public class CustomDrawableView extends View {
  private ShapeDrawable mDrawable;

  public CustomDrawableView(Context context) {
    super(context);

    int x = 10;
    int y = 10;
    int width = 300;
    int height = 50;

    mDrawable = new ShapeDrawable(new OvalShape());
    mDrawable.getPaint().setColor(0xff74AC23);
    mDrawable.setBounds(x, y, x + width, y + height);
  }

  protected void onDraw(Canvas canvas) {
    mDrawable.draw(canvas);
  }
}

Nine-patch

發佈了100 篇原創文章 · 獲贊 21 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章