共用方式為


Android 圖形和動畫

Android 提供非常豐富且多樣化的架構,可支援 2D 圖形和動畫。 本主題介紹這些架構,並討論如何建立自定義圖形和動畫,以在 Xamarin.Android 應用程式中使用。

概觀

儘管在傳統上處於有限功率的裝置上執行,但最高分級的行動應用程式通常具有複雜的用戶體驗(UX),其完整的高品質圖形和動畫,可提供直覺、回應性、動態的感覺。 隨著行動應用程式越來越複雜,使用者已經開始期待越來越多的應用程式。

幸運的是,新式行動平臺有非常強大的架構,可用來建立複雜的動畫和自定義圖形,同時保留易於使用。 這可讓開發人員以很少的努力來新增豐富的互動功能。

Android 中的 UI API 架構大致可以分成兩個類別:圖形和動畫。

圖形會進一步分割成不同的方法來執行 2D 和 3D 圖形。 3D 圖形可透過數個內建架構取得,例如 OpenGL ES(行動裝置特定版本的 OpenGL),以及 MonoGame 等第三方架構(與 XNA 工具組相容的跨平臺工具組)。 雖然 3D 圖形不在本文的範圍內,但我們將會檢查內建的 2D 繪圖技術。

Android 提供兩個不同的 API 來建立 2D 圖形。 一個是高階宣告式方法,另一個則是程序設計低階 API:

  • 可繪製的資源 – 這些是用來透過程序設計方式或(更通常)在 XML 檔案中內嵌繪圖指示來建立自定義圖形。 可繪製的資源通常定義為 XML 檔案,其中包含 Android 轉譯 2D 圖形的指示或動作。

  • Canvas – 這是低階 API,牽涉到直接在基礎位圖上繪製。 它提供非常精細的控制所顯示的內容。

除了這些 2D 圖形技術之外,Android 也提供數種不同的方法來建立動畫:

  • 可繪製動畫 – Android 也支援稱為 「可繪製動畫」的逐畫面動畫。 這是最簡單的動畫 API。 Android 會循序載入並顯示可繪製的資源(很像卡通)。

  • 檢視動畫 – 檢視動畫是 Android 中的原始動畫 API,且適用於所有版本的 Android。 此 API 有限,因為它只會使用 View 物件,而且只能在這些檢視上執行簡單的轉換。 檢視動畫通常會定義於資料夾中找到的 /Resources/anim XML 檔案中。

  • 屬性動畫 – Android 3.0 引進了一組新的動畫 API,稱為 「屬性動畫」。 這些新的 API 引進了可延伸且彈性的系統,可用來建立任何對象的屬性動畫效果,而不只是 View 物件。 這種彈性可讓動畫封裝在不同的類別中,讓程式代碼共用更容易。

檢視動畫更適用於必須支援舊版 Android 3.0 API (API 層級 11) 的應用程式。 否則,應用程式應該基於上述原因使用較新的屬性動畫 API。

不過,所有這些架構都是可行的選項,不過,應該將喜好設定提供給屬性動畫,因為它是更靈活的 API 來搭配使用。 屬性動畫可讓動畫邏輯封裝在不同的類別中,讓程式代碼共用更容易並簡化程式代碼維護。

協助工具選項

圖形和動畫有助於讓Android應用程式更具吸引力且有趣地使用;不過,請務必記住,某些互動會透過螢幕助讀程式、替代輸入設備或輔助縮放進行。 此外,某些互動可能會在沒有音訊功能的情況下發生。

如果應用程式已設計為輔助功能,則這些應用程式更容易使用:在使用者介面中提供提示和瀏覽協助,並確保UI的圖片元素有文字內容或描述。

如需如何使用Android輔助功能 API 的詳細資訊,請參閱Google的輔助功能指南

2D 圖形

可繪製的資源是Android應用程式中的熱門技術。 與其他資源一樣,可繪製的資源是宣告式資源, 它們定義於 XML 檔案中。 此方法可讓您清楚區分程式代碼與資源。 這可以簡化開發和維護,因為不需要變更程式碼來更新或變更 Android 應用程式中的圖形。 不過,雖然可繪製的資源適用於許多簡單且常見的圖形需求,但它們缺少 Canvas API 的功能和控制。

使用 Canvas 物件的另一種技術與其他傳統 API 架構非常類似,例如 System.Drawing 或 iOS 的核心繪圖。 使用 Canvas 物件可讓您最控制如何建立 2D 圖形。 適用於可繪製資源無法運作或難以使用的情況。 例如,您可能需要繪製自定義滑桿控件,其外觀會根據滑桿值的相關計算而變更。

讓我們先檢查可繪製的資源。 它們更簡單,涵蓋最常見的自定義繪圖案例。

可繪製的資源

可繪製的資源定義於目錄中 /Resources/drawable的 XML 檔案中。 與內嵌 PNG 或 JPEG 不同,不需要提供可繪製資源的密度特定版本。 在運行時間,Android 應用程式會載入這些資源,並使用這些 XML 檔案中包含的指示來建立 2D 圖形。 Android 定義數種不同類型的可繪製資源:

  • ShapeDrawable – 這是繪製基本幾何圖形的 Drawable 物件,並套用一組有限的圖形效果給該圖形。 它們對於自定義按鈕或設定 TextViews 背景等專案非常有用。 我們將會在此文章稍後看到如何使用 ShapeDrawable 的範例。

  • StateListDrawable – 這是可繪製的資源,會根據小工具/控件的狀態變更外觀。 例如,按鈕可能會根據是否按下按鈕來變更其外觀。

  • LayerDrawable – 此可繪製的資源會堆棧數個其他可繪製資源。另一個可繪製資源。 下列螢幕快照顯示 LayerDrawable範例:

    LayerDrawable 範例

  • TransitionDrawable – 這是 LayerDrawable,但有一個差異。 TransitionDrawable 能夠讓一個圖層以動畫顯示在另一層上方。

  • LevelListDrawable – 這與 StateListDrawable 非常類似,因為它會根據特定條件顯示影像。 不過,與 StateListDrawable 不同LevelListDrawable 會根據整數值顯示影像。 LevelListDrawable範例是顯示WiFi訊號的強度。 隨著WiFi訊號的強度變更,所顯示的可繪製將會隨之變更。

  • ScaleDrawable ClipDrawable/– 正如其名稱所指,這些 Drawable 提供縮放和裁剪功能。 ScaleDrawable 會調整另一個 Drawable,而 ClipDrawable 則會裁剪另一個 Drawable

  • InsetDrawable – 此 Drawable 會在另一個 Drawable 資源的兩側套用內嵌。 當 View 需要小於檢視實際界限的背景時,就會使用它。

  • XML BitmapDrawable – 此檔案是 XML 中要對實際點陣圖執行的一組指令。 Android 可以執行的一些動作是並排、打擷取和消除鋸齒。 其中一個很常見的用法是跨版面配置背景並排點陣圖。

可繪製範例

讓我們看看如何使用 建立 2D 圖形 ShapeDrawable的快速範例。 ShapeDrawable可以定義四個基本圖形之一:矩形、橢圓形、線條和環形。 您也可以套用基本效果,例如漸層、色彩和大小。 下列 XML 位於 ShapeDrawableAnimationsDemo 隨附專案中(檔案中 Resources/drawable/shape_rounded_blue_rect.xml)。 它會定義具有紫色漸層背景和圓角的矩形:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<!-- Specify a gradient for the background -->
<gradient android:angle="45"
          android:startColor="#55000066"
          android:centerColor="#00000000"
          android:endColor="#00000000"
          android:centerX="0.75" />

<padding android:left="5dp"
          android:right="5dp"
          android:top="5dp"
          android:bottom="5dp" />

<corners android:topLeftRadius="10dp"
          android:topRightRadius="10dp"
          android:bottomLeftRadius="10dp"
          android:bottomRightRadius="10dp" />
</shape>

我們可以以宣告方式在版面配置或其他 Drawable 中參考此 Drawable 資源,如下列 XML 所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#33000000">
    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_centerInParent="true"
              android:background="@drawable/shape_rounded_blue_rect"
              android:text="@string/message_shapedrawable" />
</RelativeLayout>

您也可以以程式設計方式套用可繪製的資源。 下列代碼段示範如何以程式設計方式設定 TextView 的背景:

TextView tv = FindViewById<TextView>(Resource.Id.shapeDrawableTextView);
tv.SetBackgroundResource(Resource.Drawable.shape_rounded_blue_rect);

若要查看其外觀,請執行 AnimationsDemo 專案,然後從主選單中選取 Shape Drawable 專案。 我們應該會看到類似下列螢幕快照的內容:

具有自定義背景的 Textview,可使用漸層和圓角繪製

如需有關可繪製資源之 XML 元素和語法的詳細資訊,請參閱 Google 的檔

使用畫布繪圖 API

可抽籤功能強大,但有其限制。 某些專案可能或非常複雜(例如:將篩選套用至裝置上相機拍攝的圖片)。 使用可繪製的資源來套用紅眼縮小會非常困難。 相反地,Canvas API 可讓應用程式擁有非常精細的控制,以選擇性地變更圖片中特定部分的色彩。

一個通常與 Canvas 搭配使用的類別是 小畫家 類別。 這個類別保存如何繪製的色彩和樣式資訊。 它用來提供這類色彩和透明度的東西。

Canvas API 會使用 畫家的模型 來繪製 2D 圖形。 作業會以彼此頂端的連續層套用。 每個作業都會涵蓋基礎位圖的某些區域。 當區域重疊先前繪製的區域時,新的油漆會部分或完全遮蔽舊畫。 這與 System.Drawing 和 iOS 核心圖形等許多其他繪圖 API 的運作方式相同。

有兩種方式可以取得 Canvas 物件。 第一 種方式涉及定義 Bitmap 物件,然後使用它 具現 Canvas 化物件。 例如,下列代碼段會建立具有基礎位圖的新畫布:

Bitmap bitmap = Bitmap.CreateBitmap(100, 100, Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(b);

取得物件的另一Canvas種方式是提供 View 基類的 OnDraw 回呼方法。 Android 會在決定 View 需要自行繪製並傳入 Canvas 物件,讓 View 能夠使用時呼叫這個方法。

Canvas 類別會公開方法,以程式設計方式提供繪製指示。 例如:

使用 Canvas API 繪製

以下是畫布 API 運作情形的範例。 下列代碼段示範如何繪製檢視:

public class MyView : View
{
    protected override void OnDraw(Canvas canvas)
    {
        base.OnDraw(canvas);
        Paint green = new Paint {
            AntiAlias = true,
            Color = Color.Rgb(0x99, 0xcc, 0),
        };
        green.SetStyle(Paint.Style.FillAndStroke);

        Paint red = new Paint {
            AntiAlias = true,
            Color = Color.Rgb(0xff, 0x44, 0x44)
        };
        red.SetStyle(Paint.Style.FillAndStroke);

        float middle = canvas.Width * 0.25f;
        canvas.DrawPaint(red);
        canvas.DrawRect(0, 0, middle, canvas.Height, green);
    }
}

上述程式代碼會先建立紅色油漆和綠色油漆物件。 它會以紅色填滿畫布的內容,然後指示畫布繪製 25% 的畫布寬度的綠色矩形。 在本文的原始程式碼隨附的專案中, AnimationsDemo 可以看到此專案的範例。 藉由啟動應用程式,並從主功能表中選取 [繪圖] 專案,我們應該有類似下列畫面:

使用紅色油漆和綠色油漆對象的螢幕

動畫

用戶喜歡在其應用程式中移動的專案。 動畫是改善應用程式用戶體驗並協助其脫穎而出的絕佳方式。最好的動畫是使用者不會注意到的動畫,因為它們感覺自然。 Android 提供下列三個適用於動畫的 API:

  • 檢視動畫 – 這是原始 API。 這些動畫會系結至特定的 View,而且可以在檢視的內容上執行簡單的轉換。 由於簡單起見,此 API 仍然適用於 Alpha 動畫、旋轉等專案。

  • 屬性動畫 – 已在 Android 3.0 中引進屬性動畫。 它們可讓應用程式產生幾乎任何動畫效果。 屬性動畫可以用來變更任何物件的任何屬性,即使螢幕上看不到該物件也一樣。

  • 可繪製動畫 – 這是特殊的可繪製資源,可用來將非常簡單的動畫效果套用至版面配置。

一般而言,屬性動畫是慣用的系統,因為它更具彈性,並提供更多功能。

檢視動畫

檢視動畫僅限於檢視,而且只能在起點和終點、大小、旋轉和透明度等值上執行動畫。 這些類型的動畫通常稱為 tween 動畫。 檢視動畫可以透過程式代碼或使用 XML 檔案,以程式設計方式定義兩種方式。 XML 檔案是宣告檢視動畫的慣用方式,因為它們更容易閱讀且更容易維護。

動畫 XML 檔案會儲存在 /Resources/anim Xamarin.Android 專案的目錄中。 此檔案必須具有下列其中一個專案做為根元素:

  • alpha – 淡入或淡出動畫。

  • rotate – 旋轉動畫。

  • scale – 重設大小動畫。

  • translate – 水準和/或垂直動作。

  • set – 可保存一或多個其他動畫元素的容器。

根據預設,XML 檔案中的所有動畫都會同時套用。 若要讓動畫循序進行,請在上面定義的其中一個項目上設定 android:startOffset 屬性。

您可以使用插補器來影響動畫中的變更速率。 插補器可讓動畫效果加速、重複或減速。 Android 架構提供數個現成的插補程式,例如 (但不限於):

  • AccelerateInterpolator / DecelerateInterpolator – 這些插補器會增加或減少動畫中的變更速率。

  • BounceInterpolator – 變更會在結尾反彈。

  • LinearInterpolator – 變更的速率是常數。

下列 XML 顯示結合其中一些元素的動畫檔案範例:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android=http://schemas.android.com/apk/res/android
     android:shareInterpolator="false">

    <scale android:interpolator="@android:anim/accelerate_decelerate_interpolator"
           android:fromXScale="1.0"
           android:toXScale="1.4"
           android:fromYScale="1.0"
           android:toYScale="0.6"
           android:pivotX="50%"
           android:pivotY="50%"
           android:fillEnabled="true"
           android:fillAfter="false"
           android:duration="700" />

    <set android:interpolator="@android:anim/accelerate_interpolator">
        <scale android:fromXScale="1.4"
               android:toXScale="0.0"
               android:fromYScale="0.6"
               android:toYScale="0.0"
               android:pivotX="50%"
               android:pivotY="50%"
               android:fillEnabled="true"
               android:fillBefore="false"
               android:fillAfter="true"
               android:startOffset="700"
               android:duration="400" />

        <rotate android:fromDegrees="0"
                android:toDegrees="-45"
                android:toYScale="0.0"
                android:pivotX="50%"
                android:pivotY="50%"
                android:fillEnabled="true"
                android:fillBefore="false"
                android:fillAfter="true"
                android:startOffset="700"
                android:duration="400" />
    </set>
</set>

此動畫會同時執行所有動畫。 第一個縮放動畫會水平縮放影像,並垂直縮小影像,然後同時旋轉 45 度逆時針和縮小,從螢幕消失。

動畫可以透過擴充動畫,然後將動畫套用至 View,以程式設計方式套用至檢視。 Android 提供協助程式類別,這個類別 Android.Views.Animations.AnimationUtils 會擴充動畫資源,並傳回的 Android.Views.Animations.Animation實例。 這個物件會藉由呼叫 StartAnimation 並傳遞 Animation 物件,套用至 View。 下列代碼段顯示下列範例:

Animation myAnimation = AnimationUtils.LoadAnimation(Resource.Animation.MyAnimation);
ImageView myImage = FindViewById<ImageView>(Resource.Id.imageView1);
myImage.StartAnimation(myAnimation);

既然我們已經對檢視動畫的運作方式有了基本瞭解,讓我們移至屬性動畫。

屬性動畫

屬性動畫器是 Android 3.0 中引進的新 API。 它們提供更具擴充性的 API,可用來建立任何物件上任何屬性的動畫效果。

所有屬性動畫都是由 Animator 子類別的實例所建立。 應用程式不會直接使用此類別,而是使用其中一個子類別:

  • ValueAnimator – 這個類別是整個屬性動畫 API 中最重要的類別。 它會計算需要變更的屬性值。 ViewAnimator不會直接更新這些值,而是會引發可用來更新動畫物件的事件。

  • ObjectAnimator – 這個類別是 的 ValueAnimator 子類別。 它旨在藉由接受要更新的目標對象和屬性來簡化動畫物件的程式。

  • AnimationSet – 此類別負責協調動畫如何彼此相關執行。 動畫可以同時執行、循序執行,或兩者之間有指定的延遲。

評估工具 是動畫器用來計算動畫期間新值的特殊類別。 現為 Android 提供下列評估工具:

如果正在產生動畫效果的屬性不是 floatint 色彩,應用程式可能會藉由實 ITypeEvaluator 作 介面來建立自己的評估工具。 (實作自定義評估工具超出本主題的範圍。

使用 ValueAnimator

任何動畫都有兩個部分:計算動畫值,然後在某些物件上的屬性上設定這些值。 ValueAnimator 只會計算值,但不會直接在對象上運作。 相反地,物件將會在動畫生命週期內叫用的事件處理程式內更新。 此設計允許從一個動畫值更新數個屬性。

您可以呼叫下列其中一個 Factory 方法,以取得 的實例 ValueAnimator

  • ValueAnimator.OfInt
  • ValueAnimator.OfFloat
  • ValueAnimator.OfObject

完成後, ValueAnimator 實例必須設定其持續時間,然後才能啟動。 下列範例示範如何在1000毫秒的跨度上,以動畫顯示從0到1的值:

ValueAnimator animator = ValueAnimator.OfInt(0, 100);
animator.SetDuration(1000);
animator.Start();

但本身,上述代碼段並不十分有用 – 動畫工具會執行,但更新的值沒有目標。 類別 Animator 會在決定必須通知接聽程式新值時引發Update事件。 應用程式可能會提供事件處理程式來回應此事件,如下列代碼段所示:

MyCustomObject myObj = new MyCustomObject();
myObj.SomeIntegerValue = -1;

animator.Update += (object sender, ValueAnimator.AnimatorUpdateEventArgs e) =>
{
    int newValue = (int) e.Animation.AnimatedValue;
    // Apply this new value to the object being animated.
    myObj.SomeIntegerValue = newValue;
};

既然我們已經瞭解 ValueAnimator,讓我們深入瞭解 ObjectAnimator

使用 ObjectAnimator

ObjectAnimator 是 的 ViewAnimator 子類別,結合了 計時引擎和的值計算 ValueAnimator ,以及連接事件處理程式所需的邏輯。 需要 ValueAnimator 應用程式明確地連接事件處理程式, ObjectAnimator 將會為我們處理此步驟。

的 API 非常類似於 的 API ObjectAnimatorViewAnimator但要求您提供 要更新的物件和屬性名稱。 下列範例顯示使用 ObjectAnimator的範例:

MyCustomObject myObj = new MyCustomObject();
myObj.SomeIntegerValue = -1;

ObjectAnimator animator = ObjectAnimator.OfFloat(myObj, "SomeIntegerValue", 0, 100);
animator.SetDuration(1000);
animator.Start();

如您先前代碼段所見, ObjectAnimator 可以減少並簡化建立對象動畫所需的程序代碼。

可繪製的動畫

最後一個動畫 API 是可繪製的動畫 API。 可繪製的動畫會一個接一個地載入一系列的 Drawable 資源,並循序顯示它們,類似於翻轉動畫片。

可繪製的資源定義於 XML 檔案中,該檔案具有 <animation-list> 元素做為根元素,以及一系列 <item> 定義動畫中每個畫面的專案。 這個 XML 檔案會儲存在 /Resource/drawable 應用程式的資料夾中。 下列 XML 是可繪製動畫的範例:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/asteroid01" android:duration="100" />
  <item android:drawable="@drawable/asteroid02" android:duration="100" />
  <item android:drawable="@drawable/asteroid03" android:duration="100" />
  <item android:drawable="@drawable/asteroid04" android:duration="100" />
  <item android:drawable="@drawable/asteroid05" android:duration="100" />
  <item android:drawable="@drawable/asteroid06" android:duration="100" />
</animation-list>

此動畫會透過六個畫面執行。 屬性 android:duration 會宣告每個畫面的顯示時間長度。 下一個代碼段顯示建立 Drawable 動畫的範例,並在使用者按兩下畫面上的按鈕時啟動它:

AnimationDrawable _asteroidDrawable;

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.Main);

    _asteroidDrawable = (Android.Graphics.Drawables.AnimationDrawable)
    Resources.GetDrawable(Resource.Drawable.spinning_asteroid);

    ImageView asteroidImage = FindViewById<ImageView>(Resource.Id.imageView2);
    asteroidImage.SetImageDrawable((Android.Graphics.Drawables.Drawable) _asteroidDrawable);

    Button asteroidButton = FindViewById<Button>(Resource.Id.spinAsteroid);
    asteroidButton.Click += (sender, e) =>
    {
        _asteroidDrawable.Start();
    };
}

此時,我們已涵蓋 Android 應用程式中可用的動畫 API 基礎。

摘要

本文介紹許多新的概念和 API,以協助將一些圖形新增至 Android 應用程式。 首先,它討論了各種 2D 圖形 API,並示範 Android 如何讓應用程式使用 Canvas 物件直接繪製到畫面。 我們也看到一些替代技術,允許使用 XML 檔案以宣告方式建立圖形。 然後,我們接著討論在Android中建立動畫的舊版和新 API。