├── images
├── Entry.png
├── Image.png
├── Label.png
├── BoxView.png
├── Button.png
├── Editor.png
├── OpenGL.png
├── Stepper.png
├── Switch.png
├── WebView.png
├── DatePicker.png
├── ListView.png
├── SearchBar.png
├── TimePicker.png
├── ProgressBar.png
├── TableViewNewest.png
└── ActivityIndicator.png
├── XtcGuide
├── iOS
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Resources
│ │ └── icon.png
│ ├── Entitlements.plist
│ ├── packages.config
│ ├── Main.cs
│ ├── AppDelegate.cs
│ ├── LaunchScreen.storyboard
│ ├── Info.plist
│ └── XtcGuide.iOS.csproj
├── Droid
│ ├── Resources
│ │ ├── drawable
│ │ │ └── icon.png
│ │ ├── drawable-hdpi
│ │ │ └── icon.png
│ │ ├── drawable-xhdpi
│ │ │ └── icon.png
│ │ ├── drawable-xxhdpi
│ │ │ └── icon.png
│ │ ├── layout
│ │ │ ├── Toolbar.axml
│ │ │ └── Tabbar.axml
│ │ ├── values
│ │ │ └── styles.xml
│ │ └── AboutResources.txt
│ ├── Properties
│ │ ├── AndroidManifest.xml
│ │ └── AssemblyInfo.cs
│ ├── Assets
│ │ └── AboutAssets.txt
│ ├── MainActivity.cs
│ ├── packages.config
│ └── XtcGuide.Droid.csproj
├── XtcGuide
│ ├── packages.config
│ ├── XtcGuide.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── XtcGuide.csproj
├── UITests
│ ├── packages.config
│ ├── AppInitializer.cs
│ ├── Tests.cs
│ └── XtcGuide.UITests.csproj
└── XtcGuide.sln
├── .gitignore
└── README.md
/images/Entry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/Entry.png
--------------------------------------------------------------------------------
/images/Image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/Image.png
--------------------------------------------------------------------------------
/images/Label.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/Label.png
--------------------------------------------------------------------------------
/images/BoxView.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/BoxView.png
--------------------------------------------------------------------------------
/images/Button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/Button.png
--------------------------------------------------------------------------------
/images/Editor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/Editor.png
--------------------------------------------------------------------------------
/images/OpenGL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/OpenGL.png
--------------------------------------------------------------------------------
/images/Stepper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/Stepper.png
--------------------------------------------------------------------------------
/images/Switch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/Switch.png
--------------------------------------------------------------------------------
/images/WebView.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/WebView.png
--------------------------------------------------------------------------------
/images/DatePicker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/DatePicker.png
--------------------------------------------------------------------------------
/images/ListView.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/ListView.png
--------------------------------------------------------------------------------
/images/SearchBar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/SearchBar.png
--------------------------------------------------------------------------------
/images/TimePicker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/TimePicker.png
--------------------------------------------------------------------------------
/images/ProgressBar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/ProgressBar.png
--------------------------------------------------------------------------------
/images/TableViewNewest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/TableViewNewest.png
--------------------------------------------------------------------------------
/images/ActivityIndicator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/images/ActivityIndicator.png
--------------------------------------------------------------------------------
/XtcGuide/iOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/XtcGuide/iOS/Resources/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/XtcGuide/iOS/Resources/icon.png
--------------------------------------------------------------------------------
/XtcGuide/Droid/Resources/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/XtcGuide/Droid/Resources/drawable/icon.png
--------------------------------------------------------------------------------
/XtcGuide/Droid/Resources/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/XtcGuide/Droid/Resources/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/XtcGuide/Droid/Resources/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/XtcGuide/Droid/Resources/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/XtcGuide/Droid/Resources/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/HEAD/XtcGuide/Droid/Resources/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/XtcGuide/XtcGuide/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/XtcGuide/UITests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/XtcGuide/iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/XtcGuide/iOS/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/XtcGuide/Droid/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/XtcGuide/Droid/Resources/layout/Toolbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/XtcGuide/UITests/AppInitializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using Xamarin.UITest;
5 | using Xamarin.UITest.Queries;
6 |
7 | namespace XtcGuide.UITests
8 | {
9 | public class AppInitializer
10 | {
11 | public static IApp StartApp(Platform platform)
12 | {
13 | if (platform == Platform.Android)
14 | {
15 | return ConfigureApp.Android.StartApp();
16 | }
17 |
18 | return ConfigureApp.iOS.StartApp();
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/XtcGuide/Droid/Resources/layout/Tabbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/XtcGuide/iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace XtcGuide.iOS
9 | {
10 | public class Application
11 | {
12 | // This is the main entry point of the application.
13 | static void Main(string[] args)
14 | {
15 | // if you want to use a different Application Delegate class from "AppDelegate"
16 | // you can specify it here.
17 | UIApplication.Main(args, null, "AppDelegate");
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/XtcGuide/Droid/Assets/AboutAssets.txt:
--------------------------------------------------------------------------------
1 | Any raw assets you want to be deployed with your application can be placed in
2 | this directory (and child directories) and given a Build Action of "AndroidAsset".
3 |
4 | These files will be deployed with your package and will be accessible using Android's
5 | AssetManager, like this:
6 |
7 | public class ReadAsset : Activity
8 | {
9 | protected override void OnCreate (Bundle bundle)
10 | {
11 | base.OnCreate (bundle);
12 |
13 | InputStream input = Assets.Open ("my_asset.txt");
14 | }
15 | }
16 |
17 | Additionally, some Android functions will automatically load asset files:
18 |
19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
20 |
--------------------------------------------------------------------------------
/XtcGuide/iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace XtcGuide.iOS
9 | {
10 | [Register("AppDelegate")]
11 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
12 | {
13 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
14 | {
15 | global::Xamarin.Forms.Forms.Init();
16 |
17 | // Code for starting up the Xamarin Test Cloud Agent
18 | #if ENABLE_TEST_CLOUD
19 | Xamarin.Calabash.Start();
20 | #endif
21 |
22 | LoadApplication(new App());
23 |
24 | return base.FinishedLaunching(app, options);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/XtcGuide/Droid/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Android.App;
4 | using Android.Content;
5 | using Android.Content.PM;
6 | using Android.Runtime;
7 | using Android.Views;
8 | using Android.Widget;
9 | using Android.OS;
10 |
11 | namespace XtcGuide.Droid
12 | {
13 | [Activity(Label = "XtcGuide.Droid", Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
14 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
15 | {
16 | protected override void OnCreate(Bundle bundle)
17 | {
18 | TabLayoutResource = Resource.Layout.Tabbar;
19 | ToolbarResource = Resource.Layout.Toolbar;
20 |
21 | base.OnCreate(bundle);
22 |
23 | global::Xamarin.Forms.Forms.Init(this, bundle);
24 |
25 | LoadApplication(new App());
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/XtcGuide/UITests/Tests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using NUnit.Framework;
5 | using Xamarin.UITest;
6 | using Xamarin.UITest.Queries;
7 |
8 | namespace XtcGuide.UITests
9 | {
10 | [TestFixture(Platform.Android)]
11 | [TestFixture(Platform.iOS)]
12 | public class Tests
13 | {
14 | IApp app;
15 | Platform platform;
16 |
17 | public Tests(Platform platform)
18 | {
19 | this.platform = platform;
20 | }
21 |
22 | [SetUp]
23 | public void BeforeEachTest()
24 | {
25 | app = AppInitializer.StartApp(platform);
26 | }
27 |
28 | [Test]
29 | public void Repl()
30 | {
31 | app.Repl();
32 | }
33 |
34 | [Test]
35 | public void WelcomeTextIsDisplayed()
36 | {
37 | AppResult[] results = app.WaitForElement(c => c.Marked("Welcome to Xamarin Forms!"));
38 | app.Screenshot("Welcome screen.");
39 |
40 | Assert.IsTrue(results.Any());
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/XtcGuide/XtcGuide/XtcGuide.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Xamarin.Forms;
4 |
5 | namespace XtcGuide
6 | {
7 | public class App : Application
8 | {
9 | public App()
10 | {
11 | // The root page of your application
12 | var content = new ContentPage
13 | {
14 | Title = "XtcGuide",
15 | Content = new StackLayout
16 | {
17 | Children = {
18 | new Label {
19 | HorizontalTextAlignment = TextAlignment.Center,
20 | Text = "Welcome to Xamarin Forms!"
21 | },
22 | new WebView { AutomationId = "MyWebView", Source = "https://www.google.com/",WidthRequest = 300, HeightRequest = 300 }
23 | }
24 | }
25 | };
26 |
27 | content.ToolbarItems.Add(new ToolbarItem { AutomationId = "OneButton", Text = "One", Icon = "icon.png" });
28 | content.ToolbarItems.Add(new ToolbarItem { AutomationId = "TwoButton", Text = "Two", Icon = "icon.png" });
29 |
30 | MainPage = new NavigationPage(content);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/XtcGuide/Droid/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/XtcGuide/XtcGuide/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 |
4 | // Information about this assembly is defined by the following attributes.
5 | // Change them to the values specific to your project.
6 |
7 | [assembly: AssemblyTitle("XtcGuide")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("")]
12 | [assembly: AssemblyCopyright("michaelw")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
19 |
20 | [assembly: AssemblyVersion("1.0.*")]
21 |
22 | // The following attributes are used to specify the signing key for the assembly,
23 | // if desired. See the Mono documentation for more information about signing.
24 |
25 | //[assembly: AssemblyDelaySign(false)]
26 | //[assembly: AssemblyKeyFile("")]
27 |
--------------------------------------------------------------------------------
/XtcGuide/Droid/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using Android.App;
4 |
5 | // Information about this assembly is defined by the following attributes.
6 | // Change them to the values specific to your project.
7 |
8 | [assembly: AssemblyTitle("XtcGuide.Droid")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("")]
13 | [assembly: AssemblyCopyright("michaelw")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
20 |
21 | [assembly: AssemblyVersion("1.0.0")]
22 |
23 | // The following attributes are used to specify the signing key for the assembly,
24 | // if desired. See the Mono documentation for more information about signing.
25 |
26 | //[assembly: AssemblyDelaySign(false)]
27 | //[assembly: AssemblyKeyFile("")]
28 |
--------------------------------------------------------------------------------
/XtcGuide/Droid/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/XtcGuide/iOS/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/XtcGuide/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDisplayName
6 | XtcGuide
7 | CFBundleName
8 | XtcGuide
9 | CFBundleIdentifier
10 | com.michaelwatson.xtcguide
11 | CFBundleShortVersionString
12 | 1.0
13 | CFBundleVersion
14 | 1.0
15 | LSRequiresIPhoneOS
16 |
17 | MinimumOSVersion
18 | 8.0
19 | UIDeviceFamily
20 |
21 | 1
22 | 2
23 |
24 | UILaunchStoryboardName
25 | LaunchScreen
26 | UIRequiredDeviceCapabilities
27 |
28 | armv7
29 |
30 | UISupportedInterfaceOrientations
31 |
32 | UIInterfaceOrientationPortrait
33 | UIInterfaceOrientationLandscapeLeft
34 | UIInterfaceOrientationLandscapeRight
35 |
36 | UISupportedInterfaceOrientations~ipad
37 |
38 | UIInterfaceOrientationPortrait
39 | UIInterfaceOrientationPortraitUpsideDown
40 | UIInterfaceOrientationLandscapeLeft
41 | UIInterfaceOrientationLandscapeRight
42 |
43 | XSAppIconAssets
44 | Assets.xcassets/AppIcon.appiconset
45 |
46 |
47 |
--------------------------------------------------------------------------------
/XtcGuide/Droid/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.axml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable/
12 | icon.png
13 |
14 | layout/
15 | main.axml
16 |
17 | values/
18 | strings.xml
19 |
20 | In order to get the build system to recognize Android resources, set the build action to
21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
22 | instead operate on resource IDs. When you compile an Android application that uses resources,
23 | the build system will package the resources for distribution and generate a class called "R"
24 | (this is an Android convention) that contains the tokens for each one of the resources
25 | included. For example, for the above Resources layout, this is what the R class would expose:
26 |
27 | public class R {
28 | public class drawable {
29 | public const int icon = 0x123;
30 | }
31 |
32 | public class layout {
33 | public const int main = 0x456;
34 | }
35 |
36 | public class strings {
37 | public const int first_string = 0xabc;
38 | public const int second_string = 0xbcd;
39 | }
40 | }
41 |
42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first
44 | string in the dictionary file values/strings.xml.
45 |
--------------------------------------------------------------------------------
/XtcGuide/UITests/XtcGuide.UITests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}
7 | Library
8 | XtcGuide.UITests
9 | XtcGuide.UITests
10 | v4.5
11 |
12 |
13 | true
14 | full
15 | false
16 | bin\Debug
17 | DEBUG;
18 | prompt
19 | 4
20 |
21 |
22 | true
23 | bin\Release
24 | prompt
25 | 4
26 |
27 |
28 |
29 |
30 | ..\packages\NUnit.2.6.3\lib\nunit.framework.dll
31 |
32 |
33 | ..\packages\Xamarin.UITest.2.0.5\lib\Xamarin.UITest.dll
34 |
35 |
36 |
37 |
38 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}
39 | XtcGuide.iOS
40 | False
41 | False
42 |
43 |
44 | {C2A66189-3E04-426E-8190-42B085B68BBF}
45 | XtcGuide.Droid
46 | False
47 | False
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/XtcGuide/XtcGuide/XtcGuide.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}
7 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | true
9 | Library
10 | XtcGuide
11 | XtcGuide
12 | v4.5
13 | Profile259
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug
20 | DEBUG;
21 | prompt
22 | 4
23 |
24 |
25 | true
26 | bin\Release
27 | prompt
28 | 4
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | ..\packages\Xamarin.Forms.2.3.3.175\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.Core.dll
37 |
38 |
39 | ..\packages\Xamarin.Forms.2.3.3.175\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.Platform.dll
40 |
41 |
42 | ..\packages\Xamarin.Forms.2.3.3.175\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.Xaml.dll
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/XtcGuide/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "idiom": "iphone",
5 | "size": "29x29",
6 | "scale": "1x"
7 | },
8 | {
9 | "idiom": "iphone",
10 | "size": "29x29",
11 | "scale": "2x"
12 | },
13 | {
14 | "idiom": "iphone",
15 | "size": "29x29",
16 | "scale": "3x"
17 | },
18 | {
19 | "idiom": "iphone",
20 | "size": "40x40",
21 | "scale": "2x"
22 | },
23 | {
24 | "idiom": "iphone",
25 | "size": "40x40",
26 | "scale": "3x"
27 | },
28 | {
29 | "idiom": "iphone",
30 | "size": "57x57",
31 | "scale": "1x"
32 | },
33 | {
34 | "idiom": "iphone",
35 | "size": "57x57",
36 | "scale": "2x"
37 | },
38 | {
39 | "idiom": "iphone",
40 | "size": "60x60",
41 | "scale": "2x"
42 | },
43 | {
44 | "idiom": "iphone",
45 | "size": "60x60",
46 | "scale": "3x"
47 | },
48 | {
49 | "idiom": "ipad",
50 | "size": "29x29",
51 | "scale": "1x"
52 | },
53 | {
54 | "idiom": "ipad",
55 | "size": "29x29",
56 | "scale": "2x"
57 | },
58 | {
59 | "idiom": "ipad",
60 | "size": "40x40",
61 | "scale": "1x"
62 | },
63 | {
64 | "idiom": "ipad",
65 | "size": "40x40",
66 | "scale": "2x"
67 | },
68 | {
69 | "idiom": "ipad",
70 | "size": "50x50",
71 | "scale": "1x"
72 | },
73 | {
74 | "idiom": "ipad",
75 | "size": "50x50",
76 | "scale": "2x"
77 | },
78 | {
79 | "idiom": "ipad",
80 | "size": "72x72",
81 | "scale": "1x"
82 | },
83 | {
84 | "idiom": "ipad",
85 | "size": "72x72",
86 | "scale": "2x"
87 | },
88 | {
89 | "idiom": "ipad",
90 | "size": "76x76",
91 | "scale": "1x"
92 | },
93 | {
94 | "idiom": "ipad",
95 | "size": "76x76",
96 | "scale": "2x"
97 | },
98 | {
99 | "size": "24x24",
100 | "idiom": "watch",
101 | "scale": "2x",
102 | "role": "notificationCenter",
103 | "subtype": "38mm"
104 | },
105 | {
106 | "size": "27.5x27.5",
107 | "idiom": "watch",
108 | "scale": "2x",
109 | "role": "notificationCenter",
110 | "subtype": "42mm"
111 | },
112 | {
113 | "size": "29x29",
114 | "idiom": "watch",
115 | "role": "companionSettings",
116 | "scale": "2x"
117 | },
118 | {
119 | "size": "29x29",
120 | "idiom": "watch",
121 | "role": "companionSettings",
122 | "scale": "3x"
123 | },
124 | {
125 | "size": "40x40",
126 | "idiom": "watch",
127 | "scale": "2x",
128 | "role": "appLauncher",
129 | "subtype": "38mm"
130 | },
131 | {
132 | "size": "44x44",
133 | "idiom": "watch",
134 | "scale": "2x",
135 | "role": "longLook",
136 | "subtype": "42mm"
137 | },
138 | {
139 | "size": "86x86",
140 | "idiom": "watch",
141 | "scale": "2x",
142 | "role": "quickLook",
143 | "subtype": "38mm"
144 | },
145 | {
146 | "size": "98x98",
147 | "idiom": "watch",
148 | "scale": "2x",
149 | "role": "quickLook",
150 | "subtype": "42mm"
151 | }
152 | ],
153 | "info": {
154 | "version": 1,
155 | "author": "xcode"
156 | }
157 | }
--------------------------------------------------------------------------------
/XtcGuide/XtcGuide.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XtcGuide", "XtcGuide\XtcGuide.csproj", "{A4C97C3E-B114-44EA-9995-DF4A95D24D35}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XtcGuide.iOS", "iOS\XtcGuide.iOS.csproj", "{4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XtcGuide.Droid", "Droid\XtcGuide.Droid.csproj", "{C2A66189-3E04-426E-8190-42B085B68BBF}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XtcGuide.UITests", "UITests\XtcGuide.UITests.csproj", "{0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
17 | Release|iPhone = Release|iPhone
18 | Release|iPhoneSimulator = Release|iPhoneSimulator
19 | Debug|iPhone = Debug|iPhone
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
27 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
28 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|iPhone.ActiveCfg = Release|Any CPU
29 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|iPhone.Build.0 = Release|Any CPU
30 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
31 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
32 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|iPhone.ActiveCfg = Debug|Any CPU
33 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|iPhone.Build.0 = Debug|Any CPU
34 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
35 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
36 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|Any CPU.ActiveCfg = Release|iPhone
37 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|Any CPU.Build.0 = Release|iPhone
38 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
39 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
40 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|iPhone.ActiveCfg = Release|iPhone
41 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|iPhone.Build.0 = Release|iPhone
42 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
43 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
44 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|iPhone.ActiveCfg = Debug|iPhone
45 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|iPhone.Build.0 = Debug|iPhone
46 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|Any CPU.Build.0 = Release|Any CPU
50 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
51 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
52 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|iPhone.ActiveCfg = Release|Any CPU
53 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|iPhone.Build.0 = Release|Any CPU
54 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
55 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
56 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
57 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|iPhone.Build.0 = Debug|Any CPU
58 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
59 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|Any CPU.Build.0 = Debug|Any CPU
60 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|Any CPU.ActiveCfg = Release|Any CPU
61 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|Any CPU.Build.0 = Release|Any CPU
62 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
63 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
64 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|iPhone.ActiveCfg = Release|Any CPU
65 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|iPhone.Build.0 = Release|Any CPU
66 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
67 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
68 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|iPhone.ActiveCfg = Debug|Any CPU
69 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|iPhone.Build.0 = Debug|Any CPU
70 | EndGlobalSection
71 | EndGlobal
72 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/xamarinstudio,visualstudio
3 |
4 | ### XamarinStudio ###
5 | bin/
6 | obj/
7 | *.userprefs
8 |
9 |
10 | ### VisualStudio ###
11 | ## Ignore Visual Studio temporary files, build results, and
12 | ## files generated by popular Visual Studio add-ons.
13 | ##
14 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
15 |
16 | # User-specific files
17 | *.suo
18 | *.user
19 | *.userosscache
20 | *.sln.docstates
21 | *.vcxproj.filters
22 |
23 | # User-specific files (MonoDevelop/Xamarin Studio)
24 |
25 | # Build results
26 | [Dd]ebug/
27 | [Dd]ebugPublic/
28 | [Rr]elease/
29 | [Rr]eleases/
30 | x64/
31 | x86/
32 | bld/
33 | [Bb]in/
34 | [Oo]bj/
35 | [Ll]og/
36 |
37 | # Visual Studio 2015 cache/options directory
38 | .vs/
39 | # Uncomment if you have tasks that create the project's static files in wwwroot
40 | #wwwroot/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUNIT
47 | *.VisualState.xml
48 | TestResult.xml
49 |
50 | # Build Results of an ATL Project
51 | [Dd]ebugPS/
52 | [Rr]eleasePS/
53 | dlldata.c
54 |
55 | # .NET Core
56 | project.lock.json
57 | project.fragment.lock.json
58 | artifacts/
59 | **/Properties/launchSettings.json
60 |
61 | *_i.c
62 | *_p.c
63 | *_i.h
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.pch
68 | *.pdb
69 | *.pgc
70 | *.pgd
71 | *.rsp
72 | *.sbr
73 | *.tlb
74 | *.tli
75 | *.tlh
76 | *.tmp
77 | *.tmp_proj
78 | *.log
79 | *.vspscc
80 | *.vssscc
81 | .builds
82 | *.pidb
83 | *.svclog
84 | *.scc
85 |
86 | # Chutzpah Test files
87 | _Chutzpah*
88 |
89 | # Visual C++ cache files
90 | ipch/
91 | *.aps
92 | *.ncb
93 | *.opendb
94 | *.opensdf
95 | *.sdf
96 | *.cachefile
97 | *.VC.db
98 | *.VC.VC.opendb
99 |
100 | # Visual Studio profiler
101 | *.psess
102 | *.vsp
103 | *.vspx
104 | *.sap
105 |
106 | # TFS 2012 Local Workspace
107 | $tf/
108 |
109 | # Guidance Automation Toolkit
110 | *.gpState
111 |
112 | # ReSharper is a .NET coding add-in
113 | _ReSharper*/
114 | *.[Rr]e[Ss]harper
115 | *.DotSettings.user
116 |
117 | # JustCode is a .NET coding add-in
118 | .JustCode
119 |
120 | # TeamCity is a build add-in
121 | _TeamCity*
122 |
123 | # DotCover is a Code Coverage Tool
124 | *.dotCover
125 |
126 | # Visual Studio code coverage results
127 | *.coverage
128 | *.coveragexml
129 |
130 | # NCrunch
131 | _NCrunch_*
132 | .*crunch*.local.xml
133 | nCrunchTemp_*
134 |
135 | # MightyMoose
136 | *.mm.*
137 | AutoTest.Net/
138 |
139 | # Web workbench (sass)
140 | .sass-cache/
141 |
142 | # Installshield output folder
143 | [Ee]xpress/
144 |
145 | # DocProject is a documentation generator add-in
146 | DocProject/buildhelp/
147 | DocProject/Help/*.HxT
148 | DocProject/Help/*.HxC
149 | DocProject/Help/*.hhc
150 | DocProject/Help/*.hhk
151 | DocProject/Help/*.hhp
152 | DocProject/Help/Html2
153 | DocProject/Help/html
154 |
155 | # Click-Once directory
156 | publish/
157 |
158 | # Publish Web Output
159 | *.[Pp]ublish.xml
160 | *.azurePubxml
161 | # TODO: Comment the next line if you want to checkin your web deploy settings
162 | # but database connection strings (with potential passwords) will be unencrypted
163 | *.pubxml
164 | *.publishproj
165 |
166 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
167 | # checkin your Azure Web App publish settings, but sensitive information contained
168 | # in these scripts will be unencrypted
169 | PublishScripts/
170 |
171 | # NuGet Packages
172 | *.nupkg
173 | # The packages folder can be ignored because of Package Restore
174 | **/packages/*
175 | # except build/, which is used as an MSBuild target.
176 | !**/packages/build/
177 | # Uncomment if necessary however generally it will be regenerated when needed
178 | #!**/packages/repositories.config
179 | # NuGet v3's project.json files produces more ignoreable files
180 | *.nuget.props
181 | *.nuget.targets
182 |
183 | # Microsoft Azure Build Output
184 | csx/
185 | *.build.csdef
186 |
187 | # Microsoft Azure Emulator
188 | ecf/
189 | rcf/
190 |
191 | # Windows Store app package directories and files
192 | AppPackages/
193 | BundleArtifacts/
194 | Package.StoreAssociation.xml
195 | _pkginfo.txt
196 |
197 | # Visual Studio cache files
198 | # files ending in .cache can be ignored
199 | *.[Cc]ache
200 | # but keep track of directories ending in .cache
201 | !*.[Cc]ache/
202 |
203 | # Others
204 | ClientBin/
205 | ~$*
206 | *~
207 | *.dbmdl
208 | *.dbproj.schemaview
209 | *.jfm
210 | *.pfx
211 | *.publishsettings
212 | node_modules/
213 | orleans.codegen.cs
214 |
215 | # Since there are multiple workflows, uncomment next line to ignore bower_components
216 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
217 | #bower_components/
218 |
219 | # RIA/Silverlight projects
220 | Generated_Code/
221 |
222 | # Backup & report files from converting an old project file
223 | # to a newer Visual Studio version. Backup files are not needed,
224 | # because we have git ;-)
225 | _UpgradeReport_Files/
226 | Backup*/
227 | UpgradeLog*.XML
228 | UpgradeLog*.htm
229 |
230 | # SQL Server files
231 | *.mdf
232 | *.ldf
233 |
234 | # Business Intelligence projects
235 | *.rdl.data
236 | *.bim.layout
237 | *.bim_*.settings
238 |
239 | # Microsoft Fakes
240 | FakesAssemblies/
241 |
242 | # GhostDoc plugin setting file
243 | *.GhostDoc.xml
244 |
245 | # Node.js Tools for Visual Studio
246 | .ntvs_analysis.dat
247 |
248 | # Visual Studio 6 build log
249 | *.plg
250 |
251 | # Visual Studio 6 workspace options file
252 | *.opt
253 |
254 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
255 | *.vbw
256 |
257 | # Visual Studio LightSwitch build output
258 | **/*.HTMLClient/GeneratedArtifacts
259 | **/*.DesktopClient/GeneratedArtifacts
260 | **/*.DesktopClient/ModelManifest.xml
261 | **/*.Server/GeneratedArtifacts
262 | **/*.Server/ModelManifest.xml
263 | _Pvt_Extensions
264 |
265 | # Paket dependency manager
266 | .paket/paket.exe
267 | paket-files/
268 |
269 | # FAKE - F# Make
270 | .fake/
271 |
272 | # JetBrains Rider
273 | .idea/
274 | *.sln.iml
275 |
276 | # CodeRush
277 | .cr/
278 |
279 | # Python Tools for Visual Studio (PTVS)
280 | __pycache__/
281 | *.pyc
282 |
283 | # Cake - Uncomment if you are using it
284 | # tools/
285 |
286 | ### VisualStudio Patch ###
287 | build/
--------------------------------------------------------------------------------
/XtcGuide/Droid/XtcGuide.Droid.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {C2A66189-3E04-426E-8190-42B085B68BBF}
7 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | Library
9 | XtcGuide.Droid
10 | XtcGuide.Droid
11 | v7.0
12 | True
13 | Resources\Resource.designer.cs
14 | Resource
15 | Properties\AndroidManifest.xml
16 | Resources
17 | Assets
18 | true
19 |
20 |
21 | true
22 | full
23 | false
24 | bin\Debug
25 | DEBUG;
26 | prompt
27 | 4
28 | None
29 |
30 |
31 | true
32 | pdbonly
33 | true
34 | bin\Release
35 | prompt
36 | 4
37 | true
38 | false
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | ..\packages\Xamarin.Android.Support.v4.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll
47 |
48 |
49 | ..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Vector.Drawable.dll
50 |
51 |
52 | ..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Animated.Vector.Drawable.dll
53 |
54 |
55 | ..\packages\Xamarin.Android.Support.v7.AppCompat.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll
56 |
57 |
58 | ..\packages\Xamarin.Android.Support.v7.RecyclerView.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll
59 |
60 |
61 | ..\packages\Xamarin.Android.Support.Design.23.3.0\lib\MonoAndroid43\Xamarin.Android.Support.Design.dll
62 |
63 |
64 | ..\packages\Xamarin.Android.Support.v7.CardView.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.CardView.dll
65 |
66 |
67 | ..\packages\Xamarin.Android.Support.v7.MediaRouter.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.MediaRouter.dll
68 |
69 |
70 | ..\packages\Xamarin.Forms.2.3.3.175\lib\MonoAndroid10\FormsViewGroup.dll
71 |
72 |
73 | ..\packages\Xamarin.Forms.2.3.3.175\lib\MonoAndroid10\Xamarin.Forms.Core.dll
74 |
75 |
76 | ..\packages\Xamarin.Forms.2.3.3.175\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll
77 |
78 |
79 | ..\packages\Xamarin.Forms.2.3.3.175\lib\MonoAndroid10\Xamarin.Forms.Platform.dll
80 |
81 |
82 | ..\packages\Xamarin.Forms.2.3.3.175\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll
83 |
84 |
85 |
86 |
87 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}
88 | XtcGuide
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/XtcGuide/iOS/XtcGuide.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | iPhoneSimulator
6 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}
7 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | Exe
9 | XtcGuide.iOS
10 | XtcGuide.iOS
11 | Resources
12 |
13 |
14 | true
15 | full
16 | false
17 | bin\iPhoneSimulator\Debug
18 | DEBUG;ENABLE_TEST_CLOUD;
19 | prompt
20 | 4
21 | iPhone Developer
22 | true
23 | true
24 | true
25 | true
26 | true
27 | 29091
28 | None
29 | x86_64
30 | HttpClientHandler
31 | Default
32 | x86
33 |
34 |
35 | pdbonly
36 | true
37 | bin\iPhone\Release
38 | prompt
39 | 4
40 | iPhone Developer
41 | true
42 | true
43 | true
44 | Entitlements.plist
45 | SdkOnly
46 | ARMv7, ARM64
47 | HttpClientHandler
48 | Default
49 | x86
50 |
51 |
52 | pdbonly
53 | true
54 | bin\iPhoneSimulator\Release
55 | prompt
56 | 4
57 | iPhone Developer
58 | true
59 | true
60 | None
61 | x86_64
62 | HttpClientHandler
63 | Default
64 | x86
65 |
66 |
67 | true
68 | full
69 | false
70 | bin\iPhone\Debug
71 | DEBUG;ENABLE_TEST_CLOUD;
72 | prompt
73 | 4
74 | iPhone Developer
75 | true
76 | true
77 | true
78 | true
79 | true
80 | true
81 | true
82 | Entitlements.plist
83 | SdkOnly
84 | ARMv7, ARM64
85 | HttpClientHandler
86 | Default
87 | x86
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | ..\packages\Xamarin.Forms.2.3.3.175\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll
96 |
97 |
98 | ..\packages\Xamarin.Forms.2.3.3.175\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll
99 |
100 |
101 | ..\packages\Xamarin.Forms.2.3.3.175\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll
102 |
103 |
104 | ..\packages\Xamarin.Forms.2.3.3.175\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll
105 |
106 |
107 | ..\packages\Xamarin.TestCloud.Agent.0.19.0\lib\Xamarin.iOS10\Calabash.dll
108 |
109 |
110 |
111 |
112 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}
113 | XtcGuide
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Xamarin Test Cloud Guide for Xamarin.Forms Applications
2 | When we begin writing C# UI test scripts for our Xamarin.Forms application, it is important that we know how to interact with each UI element on iOS and Android. This guide is meant to cover all control scenarios in Xamarin.Forms.
3 |
4 | ## Xamarin.Forms UI Controls
5 | We will begin with the [Views]() Xamarin has documented and explain the best way to interact with that control on iOS and Android in a C# UI test.
6 |
7 | ### `ActivityIndicator`
8 | 
9 |
10 | ### Uniquely Identifying a `ActivityIndicator` on iOS
11 | Native Control: [`UIActivityIndicatorView`](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/ActivityIndicatorRenderer.cs)
12 | Setting the `AutomationId` property on the `ActivityIndicator` will translate to the `Id` property to identify in `Xamarin.UITest`.
13 |
14 | ### Uniquely Identifying a `ActivityIndicator` on Android
15 | Native Control: [Android.Widget.ProgressBar](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ActivityIndicatorRenderer.cs)
16 | Setting the `AutomationId` property on the `ActivityIndicator` will translate to the `Label` property to identify in `Xamarin.UITest`.
17 |
18 | Setting `AutomationId` in Xamarin.Forms Project:
19 |
20 | ```C#
21 | ActivityIndicator indicator = new ActivityIndicator { AutomationId = "LoadingIndicator"};
22 |
23 | ```
24 |
25 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `ActivityIndicator` on both iOS and Android.
26 | ```C#
27 | app.WaitForElement(x=>x.Marked("LoadingIndicator"));
28 | app.WaitForNoElement(x=>x.Marked("LoadingIndicator))
29 | ```
30 | The code above would be an example of waiting for the `ActivityIndicator` to appear on the screen or disappear from the screen. It is common to use the `ActivityIndicator` appearing to wait for information to begin loading on the screen and then the `ActivityIndicator` disappearrance to assume all of the data has been loaded on the screen. The code above would acheive this desired effect.
31 |
32 | ### `BoxView`
33 | 
34 | ### Uniquely Identifying a `BoxView` on iOS
35 | Native Control: [BoxView](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/BoxRenderer.cs)
36 | Setting the `AutomationId` property on the `BoxView` will translate to the `Id` property to identify in `Xamarin.UITest`.
37 |
38 | ### Uniquely Identifying a `BoxView` on Android
39 | Native Control: [BoxView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/BoxRenderer.cs)
40 | Setting the `AutomationId` property on the `BoxView` will translate to the `Label` property to identify in `Xamarin.UITest`.
41 |
42 | Setting `AutomationId` in Xamarin.Forms Project:
43 |
44 | ```C#
45 | BoxView indicator = new BoxView { AutomationId = "MyBox"};
46 |
47 | ```
48 |
49 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `BoxView` on both iOS and Android.
50 | ```C#
51 | app.Tap(x=>x.Marked("MyBox"));
52 | ```
53 | I'm not sure why you would need to interact with a `BoxView`, but there it is.
54 |
55 | ### `Button`
56 | 
57 | ### Uniquely Identifying a `Button` on iOS
58 | Native Control: [UIButton](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/ButtonRenderer.cs)
59 | Setting the `AutomationId` property on the `Button` will translate to the `Id` property to identify in `Xamarin.UITest`. The `Label` property to identify in `Xamarin.UITest` will be whatever the `Button.Text` property is set to.
60 |
61 | ### Uniquely Identifying a `Button` on Android
62 | Native Control: [Android.Widget.Button](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ButtonRenderer.cs)
63 | Setting the `AutomationId` property on the `Button` will translate to the `Label` property to identify in `Xamarin.UITest`. The `Text` property to identify in `Xamarin.UITest` will be whatever the `Button.Text` property is set to.
64 |
65 | Setting `AutomationId` in Xamarin.Forms Project:
66 |
67 | ```C#
68 | Button loginButton = new Button { AutomationId = "LoginButton"};
69 |
70 | ```
71 |
72 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Button` on both iOS and Android.
73 | ```C#
74 | app.Tap(x=>x.Marked("LoginButton"));
75 | ```
76 |
77 | ### `DatePicker`
78 | 
79 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date.
80 |
81 | ### Uniquely Identifying a `DatePicker` on iOS
82 | Native Control: [UITextField](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/DatePickerRenderer.cs) with internal `UIDatePicker`
83 | Setting the `AutomationId` property on the `DatePicker` will translate to the `Id` property to identify in `Xamarin.UITest`.
84 |
85 | We will need to first tap on the `UITextField` to engage the `UIDatePicker`. From there we will need to invoke the native method `selectRow()` on the `UIDatePicker` and press the "ok" button.
86 |
87 | In Code:
88 | ```C#
89 | //Activate the DatePicker
90 | app.Tap(x=>x.Id("{AutomationId of Xamarin.Forms.DatePicker}"));
91 |
92 | //Wait for DatePicker animation to completed
93 | app.WaitForElement(x=>x.Class("UIPickerView"));
94 |
95 | //Invoke the native method selectRow()
96 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", date.Month - 1 , "inComponent", 0, "animated", true));
97 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", date.Day - 1, "inComponent", 1, "animated", true));
98 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", date.Year - 1, "inComponent", 2, "animated", true));
99 | ```
100 |
101 | The code above shows how we can invoke the `selectRow()` method on the DatePicker. The "Done" button will always have an `Class` property of "UIToolbarTextButton".
102 |
103 | ### Uniquely Identifying a `DatePicker` on Android
104 | Native Control: [Android.Widget.DatePicker](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/DatePickerRenderer.cs) with `Android.Widget.EditText`
105 | Setting the `AutomationId` property on the `DatePicker` will translate to the `Label` property to identify the `Android.Widget.EditText`.
106 |
107 | We will need to first tap on the `Android.Widget.EditText` to engage the `Android.Widget.DatePicker`. From there we will need to invoke the native method `updateDate()` on the `Android.Widget.DatePicker` and press the "ok" button.
108 |
109 | In code:
110 | ```C#
111 | //Activate the DatePicker
112 | app.Tap(x=>x.Id("{AutomationId of Xamarin.Forms.DatePicker}"));
113 |
114 | //Wait for DatePicker animation to completed
115 | app.WaitForElement(x=>x.Class("DatePicker"));
116 |
117 | //Invoke updateDate() method on displayed DatePicker
118 | app.Query(x=>x.Class("DatePicker").Invoke("updateDate",date.Year,date.Month,date.Day));
119 |
120 | //Tap the ok button to close the DatePicker dialogue
121 | app.Tap(x=>x.Id("button1"));//Ok Button in DatePicker Dialogue
122 | ```
123 |
124 | The code above shows how we can invoke the `updateDate()` method on the DatePicker. The "ok" button will always have an `Id` property of "button1". The "cancel" button will always have an `Id` property of "button2"
125 |
126 | ### `Editor`
127 | 
128 |
129 | ### Uniquely Identifying a `Editor` on iOS
130 | Native Control: [UITextField](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/EditorRenderer.cs)
131 | Setting the `AutomationId` property on the `Editor` will translate to the `Id` property to identify in `Xamarin.UITest`.
132 |
133 | ### Uniquely Identifying a `Editor` on Android
134 | Native Control: [Android.Widget.EditText](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/EditorRenderer.cs)
135 | Setting the `AutomationId` property on the `EditText` will translate to the `Label` property to identify the `Android.Widget.EditText`.
136 |
137 | Setting `AutomationId` in Xamarin.Forms Project:
138 |
139 | ```C#
140 | Editor editor = new Editor { AutomationId = "NewsEditor"};
141 | ```
142 |
143 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Editor` on both iOS and Android.
144 | ```C#
145 | //EnterText into Editor
146 | app.EnterText(x=>x.Marked("NewsEditor"), "This is some text");
147 | app.DismissKeyboard();
148 |
149 | //ClearText from Editor
150 | app.ClearText(x=>x.Marked("NewsEditor"));
151 | app.DismissKeyboard();
152 | ```
153 | The code above is an example of entering text into the Editor and clearing text from the Editor. Make sure you don't forget to dismiss the keyboard afterwards to ensure the keyboard isn't covering up any UI elements.
154 |
155 | ### `Entry`
156 | 
157 |
158 | ### Uniquely Identifying a `Entry` on iOS
159 | Native Control: [UITextField](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs)
160 | Setting the `AutomationId` property on the `Entry` will translate to the `Id` property to identify in `Xamarin.UITest`.
161 |
162 | ### Uniquely Identifying a `Entry` on Android
163 | Native Control: [Android.Widget.EditText](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/EntryEditText.cs)
164 | Setting the `AutomationId` property on the `EditText` will translate to the `Label` property to identify the `Android.Widget.EditText`.
165 |
166 | Setting `AutomationId` in Xamarin.Forms Project:
167 |
168 | ```C#
169 | Entry usernameEntry = new Entry { AutomationId = "UsernameEntry"};
170 | ```
171 |
172 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Entry` on both iOS and Android.
173 | ```C#
174 | //EnterText into Entry
175 | app.EnterText(x=>x.Marked("UsernameEntry"), "This is some text");
176 | app.DismissKeyboard();
177 |
178 | //ClearText from Entry
179 | app.ClearText(x=>x.Marked("UsernameEntry"));
180 | app.DismissKeyboard();
181 | ```
182 | The code above is an example of entering text into the Entry and clearing text from the Entry. Make sure you don't forget to dismiss the keyboard afterwards to ensure the keyboard isn't covering up any UI elements.
183 |
184 | ### `Image`
185 | 
186 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date.
187 |
188 | ### Uniquely Identifying a `Image` on iOS
189 | Native Control: [UIImage](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/ImageRenderer.cs)
190 | Setting the `AutomationId` property on the `Entry` will translate to the `Id` property to identify in `Xamarin.UITest`.
191 |
192 | ### Uniquely Identifying a `Image` on Android
193 | Native Control: [Android.Widget.ImageView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs)
194 | Setting the `AutomationId` property on the `Image` will translate to the `Label` property to identify the `Android.Widget.ImageView`.
195 |
196 | ```C#
197 | Image profilePic = new Image { AutomationId = "ProfilePicture"};
198 | ```
199 |
200 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Image` on both iOS and Android.
201 | ```C#
202 | app.Query((x=>x.Marked("ProfilePicture"));
203 | ```
204 |
205 | ### `Label`
206 | 
207 |
208 | ### Uniquely Identifying a `Label` on iOS
209 | Native Control: [UILabel](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs)
210 | Setting the `AutomationId` property on the `Xamarin.Forms.Label` will translate to the `Id` property to identify in `Xamarin.UITest`.
211 |
212 | ### Uniquely Identifying a `Label` on Android
213 | Native Control: [Android.Widget.TextView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs)
214 | Setting the `AutomationId` property on the `Xamarin.Forms.Label` will translate to the `Label` property to identify the `Android.Widget.TextView`.
215 |
216 | ```C#
217 | Label usernameLabel = new Label { AutomationId = "ProfilePicture"};
218 | ```
219 |
220 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Xamarin.Forms.Label` on both iOS and Android.
221 | ```C#
222 | app.Query((x=>x.Marked("ProfilePicture"));
223 | ```
224 |
225 | ### `ListView`
226 | 
227 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date.
228 |
229 | ### Uniquely Identifying a `ListView` on iOS
230 | Native Control: [UITableView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs)
231 | Setting the `AutomationId` property on the `Xamarin.Forms.Label` will translate to the `Id` property to identify in `Xamarin.UITest`.
232 |
233 | ### Uniquely Identifying a `ListView` on Android
234 | Native Control: [Android.Widget.ListView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs)
235 | Setting the `AutomationId` property on the `Xamarin.Forms.ListView` will translate to the `Label` property to identify the `Android.Widget.ListView`.
236 |
237 | ```C#
238 | ListView myList = new ListView { AutomationId = "MyListView"};
239 | ```
240 |
241 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Xamarin.Forms.ListView` on both iOS and Android.
242 | ```C#
243 | app.Query((x=>x.Marked("MyListView"));
244 | ```
245 |
246 | ### Interacting with Pull-to-refresh on Xamarin.Forms.ListView
247 | We must handle the Pull-to-refresh differently between iOS and Android. This is because the refreshing indicator is handled differently on each platform. On iOS, there is a `UIRefreshControl` that is displayed when the pull-to-refresh command is executing. On Android, we have to invoke the native `android.support.v4.widget.SwipeRefreshLayout.isRefreshing()` method. This will tell us if the refresh loading indicator is displayed or not.
248 |
249 | ```C#
250 | public bool RefreshIndicatorIsDisplayed
251 | {
252 | get
253 | {
254 | if (OnAndroid)
255 | return (bool)app.Query(x => x.Class("SwipeRefreshLayout").Invoke("isRefreshing")).First();
256 |
257 | if (OniOS)
258 | return (bool)app.Query(x => x.Class("UIRefreshControl")).Any();
259 |
260 | throw new Exception("Platform Not Recognized");
261 | }
262 | }
263 | ```
264 | The above code example returns a boolean whether the `Xamarin.Forms.ListView` refresh indicator is displayed or not. We may want to wait for the refresh indicator to appear or disappear, so we will need to create a method to handle this for us.
265 |
266 | ```C#
267 | public void WaitForIndicatorToDisappear(int timeoutInSeconds = 10)
268 | {
269 | int counter = 0;
270 | while (RefreshIndicatorIsDisplayed)
271 | {
272 | Thread.Sleep(200);//Value determined by user
273 | counter++;
274 |
275 | if (counter >= timeoutInSeconds)
276 | throw new Exception($"Loading the list took longer than {timeoutInSeconds}");
277 | }
278 | }
279 | ```
280 |
281 | In this example we are periodically checking to see if the refresh indicator is displayed and performing this in a loop. If we exceed the timeout given, we throw an exception with an error message that is specific to our application.
282 |
283 | ### Interacting with Cells in the ListView
284 | I get questions about this a lot and we are going to discuss a little theory here. This guide is meant to explain how to test your application, not how to test the native operating system. For example, if your application has a list of cells that are all the same type (DataTemplate is the same for each cell), we should only test interacting with the first cell in the list. This is because every cell in the list should be handled the exact same way. If we test tapping every single cell, we are really testing that the native operating system acts as we expect. In my opinion, this is a waste of time because you have no control over bugs introduced by Apple or Android. We should expect the native SDKs to work as expected and we can consider this an assumption of our tests.
285 |
286 | To interact with the first cell in the ListView, we would do something like the following:
287 |
288 | ```C#
289 | public void SelectFirstCellInList(int timeoutInSeconds = 20)
290 | {
291 | Func firstCellInList;
292 |
293 | if (OnAndroid)
294 | firstCellInList = x => x.Class("ViewCellRenderer_ViewCellContainer").Index(0);
295 | else if (OniOS)
296 | firstCellInList = x => x.Marked("{AutomationId of ViewCell}").Index(0);
297 |
298 | app.WaitForElement(firstCellInList, "Timed our waiting for the first user to appear", TimeSpan.FromSeconds(timeoutInSeconds));
299 | app.Tap(firstCellInList);
300 | }
301 | ```
302 |
303 | In the code above, we have to identify our cells differently. On Android, we can simply use the `ViewCellRenderer_ViewCellContainer` class to identify the cells. On iOS, we can set the `AutomationId` property of the `Xamarin.Forms.ViewCell`.
304 |
305 | ### `OpenGL`
306 | 
307 | TBD
308 |
309 | ### `ProgressBar`
310 | 
311 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date.
312 |
313 | ### Uniquely Identifying a `ProgressBar` on iOS
314 | Native Control: [UIProgressView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/ProgressBarRenderer.cs)
315 | Setting the `AutomationId` property on the `ProgressBar` will translate to the `Id` property to identify in `Xamarin.UITest`.
316 |
317 | ### Uniquely Identifying a `ProgressBar` on Android
318 | Native Control: [Android.Widget.ProgressBar](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ProgressBarRenderer.cs)
319 | Setting the `AutomationId` property on the `ProgressBar` will translate to the `Label` property to identify the `Android.Widget.ProgressBar`.
320 |
321 | Setting `AutomationId` in Xamarin.Forms Project:
322 |
323 | ```C#
324 | ProgressBar progressBar = new ProgressBar { AutomationId = "LoadingProgress"};
325 | ```
326 |
327 | ### Getting ProgressBar current level
328 | ```C#
329 | if(OnAndroid)
330 | app.Query(x => x.Class("ProgressBar").Invoke("getProgress"))
331 | else if(OniOS)
332 | app.Query(x => x.Class("UIProgressView").Invoke("progress"))
333 | ```
334 |
335 | In the code above, we have to invoke native methods to check the progress level. On Android, we invoke the `Android.Widget.ProgressBar.getProgress()` method that returns a value between 0 and 10,000 (0 is 0% and 10,000 is 100%). On iOS, we invoke the `progress` property on the `UIProgressView` to return a value between 0 and 1.
336 |
337 | ### Setting ProgressBar current level
338 | ```C#
339 | if(OnAndroid)
340 | app.Query(x => x.Class("ProgressBar").Invoke("setProgress",5000)) //Sets ProgressBar to 50%, 100% = 10,000
341 | else if(OniOS)
342 | app.Query(x => x.Class("UIProgressView").Invoke("setProgress:animated",0.5f)) //Sets ProgressBar to 50%, 100% = 1.0f
343 | ```
344 |
345 | In the code above, we have to invoke native methods to set the progress level. On Android, we invoke the `Android.Widget.ProgressBar.setProgress()` method with value between 0 and 10,000 (0 is 0% and 10,000 is 100%). On iOS, we invoke the `setProgress(Float,animated: Bool)` method on the `UIProgressView` to return a value between 0 and 1.
346 |
347 | ### `SearchBar`
348 | 
349 |
350 | ### Uniquely Identifying a `SearchBar` on iOS
351 | Native Control: [UISearchBar](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/SearchBarRenderer.cs)
352 | Setting the `AutomationId` property on the `SearchBar` will translate to the `Id` property to identify the `UISearchBar` in `Xamarin.UITest`. The "Cancel" button will have a `Label` property of "Cancel".
353 |
354 | ### Uniquely Identifying a `SearchBar` on Android
355 | Native Control: [Android.Widget.SearchView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/SearchBarRenderer.cs)
356 | Setting the `AutomationId` property on the `SearchBar` will translate to the `Label` property to identify the `Android.Widget.SearchView`.
357 |
358 | Setting `AutomationId` in Xamarin.Forms Project:
359 |
360 | ```C#
361 | SearchBar searchBar = new SearchBar { AutomationId = "UserSearchBar"};
362 | ```
363 |
364 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `SearchBar` on both iOS and Android.
365 | ```C#
366 | //EnterText into SearchBar
367 | app.EnterText(x=>x.Marked("UserSearchBar"), "This is some text");
368 | app.DismissKeyboard();
369 |
370 | //ClearText from SearchBar
371 | app.ClearText(x=>x.Marked("UserSearchBar"));
372 | app.DismissKeyboard();
373 | ```
374 | The code above is an example of entering text into the Editor and clearing text from the Editor. Make sure you don't forget to dismiss the keyboard afterwards to ensure the keyboard isn't covering up any UI elements.
375 |
376 | ### Cancelling the SearchBar search
377 |
378 | ```C#
379 | if(OnAndroid)
380 | app.Tap(x=>x.Marked("Cancel"));
381 | else if(OniOS)
382 | app.Tap(x => x.Id("search_close_btn"));
383 | ```
384 |
385 | In the code above, we can interact with the "Cancel" button found on the search controls. It is important to note that on Android, you might need to call `DismissKeyboard()` depending on how you are using the search and what version of Android you are on.
386 |
387 | ### `Stepper`
388 | 
389 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date.
390 |
391 | ### Uniquely Identifying a `Stepper` on iOS
392 | Native Control: [UIStepper](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/StepperRenderer.cs)
393 | Setting the `AutomationId` property on the `Stepper` will translate to the `Id` property to identify the `UIStepper` in `Xamarin.UITest`. The '+' and '-' buttons of the UIStepper will have `Label` properties of "Increment" and "Decrement".
394 |
395 | ### Uniquely Identifying a `Stepper` on Android
396 | Native Control: [Android.Widget.LinearLayout](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/StepperRenderer.cs) with two internal `Android.Widget.Button`
397 | Setting the `AutomationId` property on the `Stepper` will translate to the `Label` property to identify the `Android.Widget.SearchView`.
398 |
399 | Setting `AutomationId` in Xamarin.Forms Project:
400 |
401 | ```C#
402 | Stepper stepper = new Stepper { AutomationId = "MyStepper"};
403 | ```
404 |
405 | ### Increasing the value of `Stepper`
406 |
407 | ```C#
408 | if(OnAndroid)
409 | app.Tap(x => x.Class("android.widget.Button").Text("+"))
410 | else if(OniOS)
411 | app.Tap(x=>x.Marked("Increment"));
412 | ```
413 |
414 | ### Decreasing the value of `Stepper`
415 |
416 | ```C#
417 | if(OnAndroid)
418 | app.Tap(x => x.Class("android.widget.Button").Text("-"))
419 | else if(OniOS)
420 | app.Tap(x=>x.Marked("Decrement"));
421 | ```
422 |
423 | ### Getting value of `Stepper`
424 |
425 | ```C#
426 | if(OnAndroid)
427 | //Would need to expose through Backdoor
428 | // TODO
429 | else if(OniOS)
430 | app.Query(x => x.Id("MyStepper").Invoke("value"));
431 | ```
432 |
433 | ### `Switch`
434 | 
435 |
436 | ### Uniquely Identifying a `Switch` on iOS
437 | Native Control: [UISwitch](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/SwitchRenderer.cs)
438 | Setting the `AutomationId` property on the `Switch` will translate to the `Id` property to identify the `UISwitch` in `Xamarin.UITest`. The '+' and '-' buttons of the UIStepper will have `Label` properties of "Increment" and "Decrement".
439 |
440 | ### Uniquely Identifying a `Switch` on Android
441 | Native Control: [Android.Widget.Switch](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/SwitchRenderer.cs) with two internal `Android.Widget.Button`
442 | Setting the `AutomationId` property on the `Switch` will translate to the `Label` property to identify the `Android.Widget.Switch`.
443 |
444 | Setting `AutomationId` in Xamarin.Forms Project:
445 |
446 | ```C#
447 | Switch stepper = new Switch { AutomationId = "MySwitch"};
448 | ```
449 |
450 | ### `TableView`
451 | 
452 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date.
453 |
454 | ### Uniquely Identifying a `TableView` on iOS
455 | Native Control: [UITableView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/TableViewRenderer.cs)
456 | Setting the `AutomationId` property on the `TableView` will translate to the `Id` property to identify the `UITableView` in `Xamarin.UITest`.
457 |
458 | ### Uniquely Identifying a `TableView` on Android
459 | Native Control: [Android.Widget.LinearLayout](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/TableViewRenderer.cs) with two internal `Android.Widget.Button`
460 | Setting the `AutomationId` property on the `TableView` will translate to the `Label` property to identify the `Android.Widget.SearchView`.
461 |
462 | ```C#
463 | TableView tableView = new TableView { AutomationId = "MyTableView"};
464 | ```
465 |
466 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Xamarin.Forms.ListView` on both iOS and Android.
467 | ```C#
468 | app.Query((x=>x.Marked("MyTableView"));
469 | ```
470 |
471 | ### Built in Xamarin.Forms.Cells
472 | These cells are typically constructed together with a combination of other elements. Due to this, we typically have to identify the cell in some way and access the objects through the `Child()` method in `Xamarin.UITest`.
473 |
474 | ### Interacting with an `TextCell`
475 |
476 | ```C#
477 | app.Query(x=>x.Marked("TextCell Text"));
478 | ```
479 |
480 | ### Interacting with an `EntryCell`
481 |
482 | ```C#
483 | //Enter some text
484 | if(OniOS)
485 | {
486 | app.EnterText(x => x.Class("Xamarin_Forms_Platform_iOS_EntryCellRenderer_EntryCellTableViewCell").Child(0).Child(0), "Text to enter");
487 | app.DismissKeyboard();
488 | } else if (OnAndroid)
489 | {
490 | app.EnterText(x => x.Class("EntryCellView").Child(1), "Text to enter");
491 | app.DismissKeyboard();
492 | }
493 |
494 | //Clear text
495 | if(OniOS)
496 | app.ClearText(x => x.Class("Xamarin_Forms_Platform_iOS_EntryCellRenderer_EntryCellTableViewCell").Child(0).Child(0));
497 | else if (OnAndroid)
498 | app.ClearText(x => x.Class("EntryCellView").Child(1));
499 | ```
500 |
501 | In the code above on iOS, we have to interact with the cell children to enter text or clear text. Each `EntryCell` will have three children on iOS, the first index (0) is the physical view of the cell while the next two indexes (1 and 2) are the `UITableViewCellSeparatorView`. After we access the Cell view, there are two more children of this view: the `UILabel` and `UITextField` of the `EntryCell`. We will want to access the first child which is the `UITextField`.
502 |
503 | In the code above on Android, we have to interact with the cell children to enter text or clear text. Each `EntryCell` will have two children on Android, the first index (0) is the `TextView` containing the text displayed in the cell. The second index (1) is the physical `Entry` for the user to input.
504 |
505 | ### Interacting with an `SwitchCell`
506 |
507 | ```C#
508 | if(OnAndroid)
509 | app.Query(x => x.Class("SwitchCellView").Class("Switch").Invoke("setChecked", {true or false});
510 | else if(OniOS)
511 | app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_CellTableViewCell").Class("UISwitch").Invoke("setOn:animated", {true or false}));
512 | ```
513 | In the code above, we have to interact with the cell children to toggle the `Switch`. We can directly invoke the native class of the `Switch` element to toggle it.
514 |
515 | ### `TimePicker`
516 | 
517 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the time.
518 |
519 | ### Uniquely Identifying a `TimePicker` on iOS
520 | Native Control: [UITextField](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/DatePickerRenderer.cs) with internal `UIDatePicker`
521 | Setting the `AutomationId` property on the `TimePicker` will translate to the `Id` property to identify in `Xamarin.UITest`.
522 |
523 | We will need to first tap on the `UITextField` to engage the `UIDatePicker`. From there we will need to invoke the native method `selectRow()` on the `UIDatePicker` and press the "ok" button.
524 |
525 | In Code:
526 | ```C#
527 | //Activate the DatePicker
528 | app.Tap(x=>x.Id("{AutomationId of Xamarin.Forms.DatePicker}"));
529 |
530 | //Wait for DatePicker animation to completed
531 | app.WaitForElement(x=>x.Class("UIPickerView"));
532 |
533 | //Invoke the native method selectRow()
534 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", time.Hour , "inComponent", 0, "animated", true)); //if time.Hour == 0, than hour is '1'. if time.Hour == 11, than hour is '12'
535 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", time.Minutes, "inComponent", 1, "animated", true)); //if time.Minute == 0, than minutes is '1'. if time.Minute == 59, than minutes is '59'
536 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", 0, "inComponent", 2, "animated", true)); //0 == AM and 1 == PM
537 | ```
538 |
539 | The code above shows how we can invoke the `selectRow()` method on the DatePicker. The "Done" button will always have an `Class` property of "UIToolbarTextButton".
540 |
541 | ### Uniquely Identifying a `TimePicker` on Android
542 | Native Control: [Android.Widget.TimePicker](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/TimePickerRenderer.cs) with `Android.Widget.EditText`
543 | Setting the `AutomationId` property on the `TimePicker` will translate to the `Label` property to identify the `Android.Widget.EditText`.
544 |
545 | We will need to first tap on the `Android.Widget.EditText` to engage the `Android.Widget.TimePicker`. From there we will need to invoke the native method `updateDate()` on the `Android.Widget.TimePicker` and press the "ok" button.
546 |
547 | Setting `AutomationId` in Xamarin.Forms Project:
548 |
549 | ```C#
550 | TimePicker myTime = new TimePicker { AutomationId = "MyTimePicker"};
551 | ```
552 |
553 | In code:
554 | ```C#
555 | //Activate the TimePicker
556 | app.Tap(x=>x.Id("MyTimePicker"));
557 |
558 | //Wait for TimePicker animation to completed
559 | app.WaitForElement(x=>x.Id("timePicker"));
560 |
561 | //Invoke methods to select time
562 | app.Query(x=>x.Id("timePicker").Invoke("setHour",3));
563 | app.Query(x=>x.Id("timePicker").Invoke("setMinute",30));
564 |
565 | //Tap the ok button to close the TimePicker dialogue
566 | app.Tap(x=>x.Id("button1"));//Ok Button in TimePicker Dialogue
567 | ```
568 |
569 | The code above shows how we can invoke the `Android.Widget.TimePicker` methods to set the time. The "ok" button will always have an `Id` property of "button1". The "cancel" button will always have an `Id` property of "button2".
570 |
571 |
572 | ### `WebView`
573 | 
574 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the time.
575 |
576 | ### Uniquely Identifying a `WebView` on iOS
577 | Native Control: [UIWebView](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs)
578 | Setting the `AutomationId` property does not work for the `WebView` control and we must identify the `WebView` through its class: `Xamarin_Forms_Platform_iOS_WebViewRenderer`.
579 |
580 | ### Uniquely Identifying a `WebView` on Android
581 | Native Control: [Android.Widget.WebView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs).
582 | Setting the `AutomationId` property on the `TimePicker` will translate to the `Label` property to identify the `Android.Widget.WebView`.
583 |
584 | ##### Is the WebView Loading?
585 | ```C#
586 | if(OnAndroid)
587 | int loadingProgress = app.Query(x => x.Marked("{WebView AutomationId}").Invoke("getProgress")); //Returns a value between 0-100
588 | else if(OniOS)
589 | int isLoading = app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").Invoke("isLoading")); //0 = false, 1 = true
590 | ```
591 |
592 | #### What is the current WebView request URL?
593 | ```C#
594 | if(OnAndroid)
595 | string url = app.Query(x => x.Marked("{WebView AutomationId}").Invoke("getUrl");
596 | else if(OniOS)
597 | string url = app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").Invoke("request"));
598 | ```
599 |
600 | #### Reload the current WebView
601 | ```C#
602 | if(OnAndroid)
603 | app.Query(x => x.Marked("{WebView AutomationId}").Invoke("reload"));
604 | else if(OniOS)
605 | app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").Invoke("reload"));
606 | ```
607 |
608 | #### Navigate back in current WebView
609 | ```C#
610 | if(OnAndroid)
611 | app.Query(x => x.Marked("{WebView AutomationId}").Invoke("goBack"));
612 | else if(OniOS)
613 | app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").Invoke("goBack"));
614 | ```
615 |
616 | #### Navigate forward in current WebView
617 | ```C#
618 | if(OnAndroid)
619 | app.Query(x => x.Marked("{WebView AutomationId}").Invoke("goForward"));
620 | else if(OniOS)
621 | app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").Invoke("goForward"));
622 | ```
623 |
624 | #### Evaluate Javascript in current WebView
625 | ```C#
626 | string javascript = "document.getElementById(\"lst-ib\").value=\"Hello\"; //Javascript to change google.com search bar text to "Hello"
627 |
628 | if(OnAndroid)
629 | app.Query(x => x.Marked("{WebView AutomationId}").InvokeJS(javascript));
630 | else if(OniOS)
631 | app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").InvokeJS(javascript));
632 | ```
633 |
634 | ### ToolbarItems
635 |
636 | ### Uniquely Identifying a `ToolbarItem` on iOS
637 | Native Control: [UIBarButtonItem](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Extensions/ToolbarItemExtensions.cs)
638 | Setting the `AutomationId` property on the `ToolbarItem` will translate to the `Id` property to identify the `UINavigationBarButton` in `Xamarin.UITest`.
639 |
640 | Setting `AutomationId` in Xamarin.Forms Project:
641 |
642 | ```C#
643 | //Setting the AutomationId property of ToolBarItem
644 | ToolbarItem firstButton = new ToolbarItem { AutomationId = "ToolbarButtonOne"};
645 |
646 | //Tapping the NavBar button
647 | app.Tap(x=>x.Id("ToolbarButtonOne"));
648 | ```
649 |
650 | ### Uniquely Identifying a `ToolbarItem` on Android
651 | Native Control: [Android.Widget.Button](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ToolbarButton.cs) with two internal `Android.Widget.Button`
652 | Setting the `AutomationId` property on the `ToolbarItem` does not work. Whatever the `ToolbarItem.Text` property is set to will be translated to the `Label` property in `Xamarin.UITest`.
653 |
654 | Setting `ToolbarItem.Text` property in Xamarin.Forms Project:
655 |
656 | ```C#
657 | //Setting the AutomationId property of ToolBarItem
658 | ToolbarItem firstButton = new ToolbarItem { AutomationId = "ToolbarButtonOne", Text = "ToolBarButtonText" };
659 |
660 | //Tapping the NavBar button
661 | app.Tap(x=>x.Marked("ToolBarButtonText"));
662 | ```
--------------------------------------------------------------------------------