XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書
顯示具有 Android 標籤的文章。 顯示所有文章
顯示具有 Android 標籤的文章。 顯示所有文章

2015/10/01

使用Material Theme來變更App主題與風格 Theme / Style

在Android 5.0之後,提出了 Material Theme的設計指引,提供了每個開發者有個統一規範可以遵循來設計每個App,透過這個指引,我們可以透過 Theme / Style 的XML定義檔案,不需要修正任何C#程式碼,就可以直接將您的App風格樣貌做個更換。

了解更多關於 [Xamarin.Android] 的使用方式
了解更多關於 [Xamarin.iOS] 的使用方式
了解更多關於 [Xamarin.Forms] 的使用方式
了解更多關於 [Hello, Android:快速入門] 的使用方式
了解更多關於 [Hello, iOS – 快速入門] 的使用方式
了解更多關於 [Xamarin.Forms 快速入門] 的使用方式

不過,Material Theme這樣的設計方式,只存在於 Android 5.0 (API 21)或者更新版本的作業系統環境上才能夠運行,若您想要使用這樣的方式來設計您的App,並且希望讓您的App可以在比Android 5.0更舊的版本上來運行,並且享受到同樣的好處,您需要透過 v7 Support Libraries的支援,它提供了 material 設計樣式的主題 theme,可以用來配置不同的UI控制項,並且可以讓您客製化不同的顏色配置。
在看到如何使用之前,我們先看看有哪些項目是我們可以透過 Theme / Style的方式來進行替換不同的風格,在下圖中,我們可以看到不同的屬性,例如:colorPrimary, colorPrimaryDark等等,透過定義這些屬性到不同的顏色色碼,我們就可以立即將您的App更換到不同的風格樣貌。

首先,我們需要在 Resources/values目錄內styles.xml,加入一些定義,如下所示。
在 styles.xml檔案內定義我們App要用的基礎主題 MyTheme.Base,這個主題內容是從 Theme.AppCompat.Light.DarkActionBar繼承而來;  Theme.AppCompat.Light.DarkActionBar 這個主題,是在 Meterial Theme內預設定義的。  我們在自行定義的基礎主題 MyTheme.Base 中,修改了許多顏色配置,這些顏色配置將會存在於 Resources/values/colors.xml內,  也就是說,我們要變更App的顏色風格配置,只需要修改Resources/values/colors.xml內的顏色色碼即可。
想要參考更詳盡的 系統提供的 Theme / Style ,可以參考 Android API開發指南的Styles / Themes部分內容
R.Style的參考文件中,其實並不是一個很好與方便查詢各 Style和屬性的地方,因為在其官方文件上,這部分並沒有寫得相當清楚;如果您想要更進一步、完整的了解與參考這些Android內的 Style 和 Theme,可以參考底下兩個連結,在這兩個連結中,完整的列出了系統內提供的各個 Style & Theme 與其屬性定義名稱,透過這樣的查詢,您可以廓中您的App成為更多采多姿的程式。
Android Styles (styles.xml)
Android Themes (themes.xml)
在上圖中所所標示出來的 colorPrimary, colorPrimaryDark, textColorPrimary, windowbackground, navigationbarcolor 這些屬性,就可以透過地下的方式來進行擴充,若想要自訂其他的項目,可以參考與查詢上述兩個 Android Style / Android Themes 這兩份文件來做到。
  <style name="MyTheme" parent="MyTheme.Base">
  </style>

  <!--
  定義我們App要用的基礎主題 MyTheme.Base,這個主題內容是從 Theme.AppCompat.Light.DarkActionBar繼承而來
  Theme.AppCompat.Light.DarkActionBar 這個主題,是在 Meterial Theme內預設定義的
  我們在自行定義的基礎主題 MyTheme.Base 中,修改了許多顏色配置,這些顏色配置將會存在於 Resources/values/colors.xml內
  也就是說,我們要變更App的顏色風格配置,只需要修改Resources/values/colors.xml內的顏色色碼即可
  -->
  <!-- Base theme applied no matter what API -->
  <style name="MyTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette-->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">@color/primary</item>
    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">@color/primaryDark</item>
    <!-- colorAccent is used as the default value for colorControlActivated which is used to tint widgets -->
    <item name="colorAccent">@color/accent</item>    
    <!-- You can also set colorControlNormal, colorControlActivated colorControlHighlight and colorSwitchThumbNormal. -->
    <!-- Option to hide the drop shadow here    
      <item name="actionBarStyle">@style/MyTheme.ActionBar</item>
      <item name="android:windowContentOverlay">@null</item>
    -->
  </style>

  <style name="MyTheme.ActionBar" parent="style/Widget.AppCompat.Light.ActionBar.Solid">
    <!-- remove shadow below action bar -->
    <!-- <item name="android:elevation">0dp</item> -->
    <!-- Support library compatibility -->
    <item name="elevation">0dp</item>
  </style>
</resources>

底下為自行定義擴充的顏色定義,上面的Xml定義中,標示著黃底紫色的文字的屬性,其顏色代碼,就是參考底下這個XML定義。
<?xml version="1.0" encoding="utf-8"?>
<!--專案範本預設的樣式-->
<!--Get colors from: http://www.materialpalette.com/-->
<!--<resources>
  <color name="primary">#03A9F4</color>
  <color name="primaryDark">#0288D1</color>
  <color name="accent">#FFC107</color>
  <color name="lightPrimary">#B3E5FC</color>
  <color name="textIcon">#FFFFFF</color>
  <color name="primaryText">#212121</color>
  <color name="secondaryText">#727272</color>
  <color name="divider">#B6B6B6</color>
  <color name="activated_color">#E8E8E8</color>
</resources>-->

<!--自訂顏色-->
<resources>
  <!--Get colors from: http://www.materialpalette.com/-->
  <color name="primary">#4CAF50</color>
  <color name="primaryDark">#388E3C</color>
  <color name="accent">#FFEB3B</color>
  <color name="lightPrimary">#C8E6C9</color>
  <color name="textIcon">#FFFFFF</color>
  <color name="primaryText">#212121</color>
  <color name="secondaryText">#727272</color>
  <color name="divider">#B6B6B6</color>
  <color name="activated_color">#E8E8E8</color>
</resources>

上面的 Colors.xml 檔案,我們定義了兩種情境顏色配置,下面螢幕截圖則是執行結果;下圖左邊是 [專案範本預設的樣式]定義,下圖右邊則是[自訂顏色]的執行結果

image image

image image

當然,我們也有方便的視覺快速設定方式,您可以透過 material palette 網頁,得到底下的設定

image





image

Xamarin.Android Templates Pack 範本解密3

在上一篇 [Xamarin.Android Templates Pack 範本解密2]文章中,我們剖析了專案內的 Activity & 相關的 Layout 配置,不過,在 Resources\layout 目錄下,還有兩個檔案沒有說明到
fragment1.axml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:text="@string/fragment1"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/textView1"
        android:gravity="center" />
</LinearLayout>

Fragment1.cs 這個檔案定義這個 Fragment 的控制相關的行為,程式碼內容如下,我們可以看到,這個類別內並沒有複雜的定義,而是在 OnCreateView 方法內,使用 LayoutInflater.Inflate方法,指定這個 Fragment要顯示的視覺配置內容。

    public class Fragment1 : Fragment
    {
        public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Create your fragment here        }

        public static Fragment1 NewInstance()
        {
            var frag1 = new Fragment1 { Arguments = new Bundle() };
            return frag1;
        }


        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            var ignored = base.OnCreateView(inflater, container, savedInstanceState);
            return inflater.Inflate(Resource.Layout.fragment1, null);
        }
    }


fragment2.axml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:text="@string/fragment2"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/textView1"
        android:gravity="center" />
</LinearLayout>

Fragment2.cs 這個檔案定義這個 Fragment 的控制相關的行為,程式碼內容如下,我們可以看到,這個類別內並沒有複雜的定義,而是在 OnCreateView 方法內,使用 LayoutInflater.Inflate方法,指定這個 Fragment要顯示的視覺配置內容。

    public class Fragment2 : Fragment
    {
        public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Create your fragment here        }

        public static Fragment2 NewInstance()
        {
            var frag2 = new Fragment2 { Arguments = new Bundle() };
            return frag2;
        }


        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            var ignored = base.OnCreateView(inflater, container, savedInstanceState);
            return inflater.Inflate(Resource.Layout.fragment2, null);
        }
    }


這兩個 .axml檔案,定義了兩個 Fragment,而當我們在 MainActivity內,有定義了當點選了導覽列中的功能表選項的話,會進行切換到不同的 Fragment

            //定義事件,當 navigation view 內的功能表選單有被選取的時候,要做何相對應的處置            navigationView.NavigationItemSelected += (sender, e) =>
            {
                e.MenuItem.SetChecked(true);

                switch (e.MenuItem.ItemId)
                {
                    case Resource.Id.nav_home_1:
                        ListItemClicked(0);
                        break;
                    case Resource.Id.nav_home_2:
                        ListItemClicked(1);
                        break;
                }

                // 這是 Google 新推出的 Metrial Design
                // 詳細說明,請參考 https://www.google.com/design/spec/material-design/introduction.html
                // 底下為產生類似 Toast 的簡短提示訊息通知效果
                Snackbar.Make(drawerLayout, "You selected: " + e.MenuItem.TitleFormatted, Snackbar.LengthLong)
                    .Show();

                // 使用動畫撥放方式,關閉所有正在開啟的 Drawer views
                drawerLayout.CloseDrawers();
            };


而 ListItemClicked方法定義如下,我們可以看到,這個方法會根據所選擇的項目,產生相對應的Fragment物件,並且透過 SuppotFragmentManager的 BeginTranscation 來進行切換到所指定的 Fragment。

Fragement是我當初學習 Android UI時候,一開始不太了解的東東,不過,把 Fragment當作是在 WPF中的 User Control,這樣的使用者控制項,是可以反覆使用的,也就是說,一旦我們定義好了之後,這些 Fragment是可以用於不同的 Activity內。
        private void ListItemClicked(int position)
        {
            //this way we don't load twice, but you might want to modify this a bit.
            if (position == oldPosition)
                return;

            oldPosition = position;

            Android.Support.V4.App.Fragment fragment = null;
            switch (position)
            {
                case 0:
                    fragment = Fragment1.NewInstance();
                    break;
                case 1:
                    fragment = Fragment2.NewInstance();
                    break;
            }

            SupportFragmentManager.BeginTransaction()
                .Replace(Resource.Id.content_frame, fragment)
                .Commit();
        }


最後,我們要來看 Resources\values 內的一些常數定義內容,首先看到的是 colors.xml 檔案,這個檔案定義了 Activity 的要顯示的顏色配色定義。

這些配色定義,將會在樣式定義檔案 styles.xml 內使用到
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <!--Get colors from: http://www.materialpalette.com/-->
  <color name="primary">#03A9F4</color>
  <color name="primaryDark">#0288D1</color>
  <color name="accent">#FFC107</color>
  <color name="lightPrimary">#B3E5FC</color>
  <color name="textIcon">#FFFFFF</color>
  <color name="primaryText">#212121</color>
  <color name="secondaryText">#727272</color>
  <color name="divider">#B6B6B6</color>
  <color name="activated_color">#E8E8E8</color>
</resources>

接下來看看格式定義檔案的內容 styles.xml,在這個檔案內,我們定義一個 MyTheme樣式,他繼承了 MyTheme.Base;而 MyTheme.Base則是繼承從 Theme.AppCompat.Light.DarkActionBar,並且做了些修正來取代系統中的定義,另外還有兩種 Theme可以來選擇,分別是 Theme.AppCompat / Theme.AppCompat.Light

例如:我們定義了Theme.AppCompat.Light.DarkActionBar內用到的 colorPrimary 顏色,將會使用 Resources\values\color.xml 內的 primary 來取代,也就是這個色碼 #03A9F4

而有些資源資料,可以從這裡取得 http://developer.android.com/intl/zh-tw/design/downloads/index.html#action-bar-icon-pack
<?xml version="1.0" encoding="utf-8" ?>
<resources>
  <style name="MyTheme" parent="MyTheme.Base">
  </style>
  <!-- Base theme applied no matter what API -->
  <style name="MyTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette-->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">@color/primary</item>
    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">@color/primaryDark</item>
    <!-- colorAccent is used as the default value for colorControlActivated
         which is used to tint widgets -->
    <item name="colorAccent">@color/accent</item>
    <!-- You can also set colorControlNormal, colorControlActivated
         colorControlHighlight and colorSwitchThumbNormal. -->    
    <!-- Option to hide the drop shadow here
    
      <item name="actionBarStyle">@style/MyTheme.ActionBar</item>
      <item name="android:windowContentOverlay">@null</item>
    -->
  </style>

  <style name="MyTheme.ActionBar" parent="style/Widget.AppCompat.Light.ActionBar.Solid">
    <!-- remove shadow below action bar -->
    <!-- <item name="android:elevation">0dp</item> -->
    <!-- Support library compatibility -->
    <item name="elevation">0dp</item>
  </style>
</resources>

而在 Resources/values-v21 目錄下也有個 styles.xml 檔案,內容如下;這裡定義了 API 21以上用到的Theme會用到的內容。
<?xml version="1.0" encoding="utf-8" ?>
<resources>
  <!--
        Base application theme for API 21+. This theme completely replaces
        MyTheme from BOTH res/values/styles.xml on API 21+ devices.
    -->
  <style name="MyTheme" parent="MyTheme.Base">
   <item name="android:windowContentTransitions">true</item>
    <item name="android:windowAllowEnterTransitionOverlap">true</item>
    <item name="android:windowAllowReturnTransitionOverlap">true</item>
    <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>
    <item name="android:windowSharedElementExitTransition">@android:transition/move</item>
  </style>
</resources>

2015/09/30

Android Design Support Library


Android Design Support Library 這是這連三天才開始進行研究的內容,原本以為看過一些 Android SDK 文件中後,就可以開始進行 Xamarin.Android App開發了,沒想到,有接觸到Android 5.0 SDK,有看到了 Toolbar 這樣的視覺API,接著研究後,才知道這些都是涵蓋在 Android Design Support Library 內的咚咚,這也解除了在專案檔案中看到的一些套件,明瞭到這些套件存在的目的。