XAML in Xamarin.Forms 基礎篇 電子書

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

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書

2015/10/01

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>

沒有留言:

張貼留言