├── .gitattributes ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── LICENSE.md ├── Xfx.Controls.sln ├── Xfx.Controls.sln.DotSettings ├── build.cake ├── build.ps1 ├── build.sh ├── example ├── Xfx.Controls.Example.Droid │ ├── Assets │ │ └── AboutAssets.txt │ ├── MainActivity.cs │ ├── Properties │ │ ├── AndroidManifest.xml │ │ └── AssemblyInfo.cs │ ├── Resources │ │ ├── AboutResources.txt │ │ ├── Resource.Designer.cs │ │ ├── drawable-hdpi │ │ │ └── icon.png │ │ ├── drawable-xhdpi │ │ │ └── icon.png │ │ ├── drawable-xxhdpi │ │ │ └── icon.png │ │ └── drawable │ │ │ └── icon.png │ ├── Xfx.Controls.Example.Droid.csproj │ └── packages.config ├── Xfx.Controls.Example.iOS │ ├── AppDelegate.cs │ ├── Entitlements.plist │ ├── Info.plist │ ├── Main.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Resources │ │ ├── Default-568h@2x.png │ │ ├── Default-Portrait.png │ │ ├── Default-Portrait@2x.png │ │ ├── Default.png │ │ ├── Default@2x.png │ │ ├── Icon-60@2x.png │ │ ├── Icon-60@3x.png │ │ ├── Icon-76.png │ │ ├── Icon-76@2x.png │ │ ├── Icon-Small-40.png │ │ ├── Icon-Small-40@2x.png │ │ ├── Icon-Small-40@3x.png │ │ ├── Icon-Small.png │ │ ├── Icon-Small@2x.png │ │ ├── Icon-Small@3x.png │ │ ├── LaunchScreen.storyboard │ │ └── Media.xcassets │ │ │ ├── AppIcons.appiconset │ │ │ └── Contents.json │ │ │ └── LaunchImages.launchimage │ │ │ └── Contents.json │ ├── Xfx.Controls.Example.iOS.csproj │ ├── iTunesArtwork │ ├── iTunesArtwork@2x │ └── packages.config └── Xfx.Controls.Example │ ├── Annotations.cs │ ├── App.cs │ ├── BaseViewModel.cs │ ├── Features │ └── Controls │ │ ├── ControlsPage.xaml │ │ ├── ControlsPage.xaml.cs │ │ └── ControlsPageModel.cs │ ├── MainPage.xaml │ ├── MainPage.xaml.cs │ └── Xfx.Controls.Example.csproj ├── readme.md ├── resources ├── xfx.controls.droid.gif ├── xfx.controls.ios.gif └── xfx.png ├── src ├── SolutionInfo.cs ├── Xfx.Controls.Droid │ ├── Extensions │ │ ├── CollectionExtensions.cs │ │ ├── ColorExtensions.cs │ │ ├── FontExtensions.cs │ │ └── KeyboardExtensions.cs │ ├── Forms.Internals │ │ ├── GestureManager.cs │ │ ├── InnerGestureListener.cs │ │ ├── InnerScaleListener.cs │ │ ├── InstantAutoCompleteTextView.cs │ │ ├── PanGestureHandler.cs │ │ ├── PinchGestureHandler.cs │ │ └── TapGestureHandler.cs │ ├── Properties │ │ ├── AndroidManifest.xml │ │ └── AssemblyInfo.cs │ ├── Renderers │ │ ├── XfxCardViewRendererDroid.cs │ │ ├── XfxComboBoxRendererDroid.cs │ │ └── XfxEntryRendererDroid.cs │ ├── Resources │ │ └── Resource.Designer.cs │ ├── Xfx.Controls.Droid.csproj │ ├── XfxComboBox │ │ ├── XfxComboBoxArrayAdapter.cs │ │ └── XfxComboBoxFilter.cs │ ├── XfxControls.cs │ ├── XfxVisualElementManager.cs │ └── packages.config ├── Xfx.Controls.Shared │ ├── Extensions │ │ └── XamarinFormsExtensions.cs │ ├── Xfx.Controls.Shared.projitems │ └── Xfx.Controls.Shared.shproj ├── Xfx.Controls.iOS │ ├── Controls │ │ ├── FloatLabeledTextField.cs │ │ ├── MbAutoComplete │ │ │ ├── MbAutoCompleteDefaultDataSource.cs │ │ │ ├── MbAutoCompleteTableView.cs │ │ │ ├── MbAutoCompleteTextField.cs │ │ │ └── MbAutoCompleteViewSource.cs │ │ └── UICardView.cs │ ├── Extensions │ │ ├── ColorExtensions.cs │ │ ├── FontExtensions.cs │ │ ├── KeyboardExtensions.cs │ │ ├── StringExtensions.cs │ │ └── UIViewExtensions.cs │ ├── InvalidRendererException.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Renderers │ │ ├── XfxCardViewRendererTouch.cs │ │ ├── XfxComboBoxRendererTouch.cs │ │ └── XfxEntryRendererTouch.cs │ ├── Xfx.Controls.iOS.csproj │ ├── XfxControls.cs │ ├── XfxVisualElementManager.cs │ └── packages.config └── Xfx.Controls │ ├── Behaviors │ ├── BindableBehavior.cs │ └── ValidatesOnNotifyDataErrors.cs │ ├── IXfxValidatableElement.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Xfx.Controls.csproj │ ├── XfxBinding.cs │ ├── XfxBindingExtensions.cs │ ├── XfxCardView.cs │ ├── XfxComboBox.cs │ ├── XfxEntry.cs │ └── XfxSelectedItemChangedEventArgs.cs └── tools ├── Cake ├── .signature.p7s ├── Autofac.dll ├── Cake.Common.dll ├── Cake.Common.xml ├── Cake.Core.dll ├── Cake.Core.xml ├── Cake.NuGet.dll ├── Cake.NuGet.xml ├── Cake.exe ├── Cake.exe.config ├── Cake.xml ├── LICENSE ├── Microsoft.CodeAnalysis.CSharp.Scripting.dll ├── Microsoft.CodeAnalysis.CSharp.dll ├── Microsoft.CodeAnalysis.Scripting.dll ├── Microsoft.CodeAnalysis.dll ├── Microsoft.Web.XmlTransform.dll ├── Microsoft.Win32.Primitives.dll ├── Newtonsoft.Json.dll ├── NuGet.Commands.dll ├── NuGet.Common.dll ├── NuGet.Configuration.dll ├── NuGet.Credentials.dll ├── NuGet.DependencyResolver.Core.dll ├── NuGet.Frameworks.dll ├── NuGet.LibraryModel.dll ├── NuGet.PackageManagement.dll ├── NuGet.Packaging.Core.dll ├── NuGet.Packaging.dll ├── NuGet.ProjectModel.dll ├── NuGet.Protocol.dll ├── NuGet.Resolver.dll ├── NuGet.Versioning.dll ├── System.AppContext.dll ├── System.Collections.Concurrent.dll ├── System.Collections.Immutable.dll ├── System.Collections.NonGeneric.dll ├── System.Collections.Specialized.dll ├── System.Collections.dll ├── System.ComponentModel.EventBasedAsync.dll ├── System.ComponentModel.Primitives.dll ├── System.ComponentModel.TypeConverter.dll ├── System.ComponentModel.dll ├── System.Console.dll ├── System.Data.Common.dll ├── System.Diagnostics.Contracts.dll ├── System.Diagnostics.Debug.dll ├── System.Diagnostics.FileVersionInfo.dll ├── System.Diagnostics.Process.dll ├── System.Diagnostics.StackTrace.dll ├── System.Diagnostics.TextWriterTraceListener.dll ├── System.Diagnostics.Tools.dll ├── System.Diagnostics.TraceSource.dll ├── System.Diagnostics.Tracing.dll ├── System.Drawing.Primitives.dll ├── System.Dynamic.Runtime.dll ├── System.Globalization.Calendars.dll ├── System.Globalization.Extensions.dll ├── System.Globalization.dll ├── System.IO.Compression.ZipFile.dll ├── System.IO.Compression.dll ├── System.IO.FileSystem.DriveInfo.dll ├── System.IO.FileSystem.Primitives.dll ├── System.IO.FileSystem.Watcher.dll ├── System.IO.FileSystem.dll ├── System.IO.IsolatedStorage.dll ├── System.IO.MemoryMappedFiles.dll ├── System.IO.Pipes.dll ├── System.IO.UnmanagedMemoryStream.dll ├── System.IO.dll ├── System.Linq.Expressions.dll ├── System.Linq.Parallel.dll ├── System.Linq.Queryable.dll ├── System.Linq.dll ├── System.Net.Http.dll ├── System.Net.NameResolution.dll ├── System.Net.NetworkInformation.dll ├── System.Net.Ping.dll ├── System.Net.Primitives.dll ├── System.Net.Requests.dll ├── System.Net.Security.dll ├── System.Net.Sockets.dll ├── System.Net.WebHeaderCollection.dll ├── System.Net.WebSockets.Client.dll ├── System.Net.WebSockets.dll ├── System.ObjectModel.dll ├── System.Reflection.Extensions.dll ├── System.Reflection.Metadata.dll ├── System.Reflection.Primitives.dll ├── System.Reflection.dll ├── System.Resources.Reader.dll ├── System.Resources.ResourceManager.dll ├── System.Resources.Writer.dll ├── System.Runtime.CompilerServices.VisualC.dll ├── System.Runtime.Extensions.dll ├── System.Runtime.Handles.dll ├── System.Runtime.InteropServices.RuntimeInformation.dll ├── System.Runtime.InteropServices.dll ├── System.Runtime.Numerics.dll ├── System.Runtime.Serialization.Formatters.dll ├── System.Runtime.Serialization.Json.dll ├── System.Runtime.Serialization.Primitives.dll ├── System.Runtime.Serialization.Xml.dll ├── System.Runtime.dll ├── System.Security.Claims.dll ├── System.Security.Cryptography.Algorithms.dll ├── System.Security.Cryptography.Csp.dll ├── System.Security.Cryptography.Encoding.dll ├── System.Security.Cryptography.Primitives.dll ├── System.Security.Cryptography.X509Certificates.dll ├── System.Security.Principal.dll ├── System.Security.SecureString.dll ├── System.Text.Encoding.CodePages.dll ├── System.Text.Encoding.Extensions.dll ├── System.Text.Encoding.dll ├── System.Text.RegularExpressions.dll ├── System.Threading.Overlapped.dll ├── System.Threading.Tasks.Extensions.dll ├── System.Threading.Tasks.Parallel.dll ├── System.Threading.Tasks.dll ├── System.Threading.Thread.dll ├── System.Threading.ThreadPool.dll ├── System.Threading.Timer.dll ├── System.Threading.dll ├── System.ValueTuple.dll ├── System.Xml.ReaderWriter.dll ├── System.Xml.XDocument.dll ├── System.Xml.XPath.XDocument.dll ├── System.Xml.XPath.dll ├── System.Xml.XmlDocument.dll ├── System.Xml.XmlSerializer.dll └── netstandard.dll ├── nuget.exe ├── packages.config └── packages.config.md5sum /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at chase.florell@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contribution Guidelines 2 | 3 | ----- 4 | 5 | First of all, thank you for your willingness to contribute to Xfx.Controls. This is a fun little project that simply adds a little flare to some of the existing Xamarn Forms controls. 6 | 7 | ### Coding Style 8 | 9 | The coding style is quite simple. Please use the Visual Studio defauls for everything (SPACES NOT TABS), and also if you're running Resharper, try your best to get a green checkmark on every file you touch. R#'s default formatting can be acheived on a per-file basis by running ctrl + alt + shift + f. 10 | 11 | ### Renderer Approach 12 | 13 | It's really easy to make a mess of custom renderers. The best way to keep your renderers clean and supported is to follow the style used in the [Xamarin.Forms](https://github.com/Xamarin/Xamarin.Forms) repository. 14 | 15 | **Focused / Unfocused** 16 | When building a custom renderer from scratch (`ViewRenderer`), you'll have to ensure you use the reflection approach to raising the focused/unfocused event.* 17 | 18 | ```csharp 19 | var isFocusedPropertyKey = Element.GetInternalField("IsFocusedPropertyKey"); 20 | ElementController.SetValueFromRenderer(isFocusedPropertyKey, true/false); 21 | ``` 22 | 23 | **Events** 24 | A personal preference of mine is to not use the `MessagingCenter`. Instead I subscribe to `internal` events within the core library (these events are exposed to the other platforms via `InternalsVisibleTo`). 25 | Please avoid using the MessagingCenter in favor of event subscriptions. 26 | 27 | DON'T FORGET TO UNSUBSCRIBE FROM EVENTS 28 | 29 | ### Spelling, Documentation, Comments 30 | 31 | I'm absolutely open to taking Pull Requests just to fix spelling, documentation, or comments, providing they add value. 32 | 33 | - Please avoid unnecessary whitespace commits 34 | - Please don't fix spelling at the expense of breaking the API. Use the `[ObsoleteAttribute]` if you find a method, property, or enum value that is spelled incorrectly, and add the correct spelling beside it. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please fill out either the bug or feature request section and remove whatever section you are not using. 2 | 3 | # Bug 4 | 5 | * Version Number of Control: 6 | * Device Tested On: 7 | * Simulator Tested On: 8 | 9 | ### Affects 10 | 11 | - [ ] iOS 12 | - [ ] Android 13 | 14 | ### Expected Behavior 15 | 16 | 17 | ### Actual Behavior 18 | 19 | 20 | ### Steps to reproduce the Behavior 21 | 22 | 23 | ### Link to Github Reproduction (optional but recommended) 24 | 25 | [Repro]() 26 | 27 | # Feature Request: 28 | Please fill in what you would like 29 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please take a moment to fill out the following (change to preview to check or place x in [ ]): 2 | 3 | ## Description 4 | 5 | Changes Proposed in this pull request: 6 | - 7 | - 8 | - 9 | 10 | ## This is a: 11 | - [ ] Bug Fix 12 | - [ ] Feature Request 13 | - [ ] New Feature 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | *.userprefs 9 | 10 | # Xamarin Components 11 | Components/ 12 | 13 | # Nuget Releases 14 | *.nupkg 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | x64/ 21 | build/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Pp]ackages/ 26 | [Cc]omponents/ 27 | data/ 28 | .nuget/ 29 | .vs/ 30 | .idea/ 31 | .droidres/ 32 | *.csproj.bak 33 | build-artifacts/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | #NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | 84 | # Visual Studio profiler 85 | *.psess 86 | *.vsp 87 | *.vspx 88 | 89 | # TFS 2012 Local Workspace 90 | $tf/ 91 | 92 | # Guidance Automation Toolkit 93 | *.gpState 94 | 95 | # ReSharper is a .NET coding add-in 96 | _ReSharper*/ 97 | *.[Rr]e[Ss]harper 98 | *.DotSettings.user 99 | 100 | # JustCode is a .NET coding addin-in 101 | .JustCode 102 | 103 | # TeamCity is a build add-in 104 | _TeamCity* 105 | 106 | # DotCover is a Code Coverage Tool 107 | *.dotCover 108 | 109 | # NCrunch 110 | *.ncrunch* 111 | _NCrunch_* 112 | .*crunch*.local.xml 113 | 114 | # MightyMoose 115 | *.mm.* 116 | AutoTest.Net/ 117 | 118 | # Web workbench (sass) 119 | .sass-cache/ 120 | 121 | # Installshield output folder 122 | [Ee]xpress/ 123 | 124 | # DocProject is a documentation generator add-in 125 | DocProject/buildhelp/ 126 | DocProject/Help/*.HxT 127 | DocProject/Help/*.HxC 128 | DocProject/Help/*.hhc 129 | DocProject/Help/*.hhk 130 | DocProject/Help/*.hhp 131 | DocProject/Help/Html2 132 | DocProject/Help/html 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.[Pp]ublish.xml 139 | *.azurePubxml 140 | 141 | # Windows Azure Build Output 142 | csx/ 143 | *.build.csdef 144 | 145 | # Windows Store app package directory 146 | AppPackages/ 147 | 148 | # Others 149 | sql/ 150 | *.Cache 151 | ClientBin/ 152 | [Ss]tyle[Cc]op.* 153 | ~$* 154 | *~ 155 | *.dbmdl 156 | *.dbproj.schemaview 157 | *.pfx 158 | *.publishsettings 159 | node_modules/ 160 | .DS_Store 161 | 162 | # RIA/Silverlight projects 163 | Generated_Code/ 164 | 165 | # Backup & report files from converting an old project file to a newer 166 | # Visual Studio version. Backup files are not needed, because we have git ;-) 167 | _UpgradeReport_Files/ 168 | Backup*/ 169 | UpgradeLog*.XML 170 | UpgradeLog*.htm 171 | 172 | # SQL Server files 173 | *.mdf 174 | *.ldf 175 | 176 | # Business Intelligence projects 177 | *.rdl.data 178 | *.bim.layout 179 | *.bim_*.settings 180 | 181 | # Microsoft Fakes 182 | FakesAssemblies/ 183 | 184 | ._.DS_Store 185 | 186 | # project.json 187 | *.lock.json 188 | *.nuget.props 189 | *.nuget.targets 190 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright (c) 2017 Chase Florell 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /Xfx.Controls.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True -------------------------------------------------------------------------------- /build.cake: -------------------------------------------------------------------------------- 1 | var target = Argument("target", "Default"); 2 | var local = BuildSystem.IsLocalBuild; 3 | var appName = "Xfx.Controls"; 4 | var versionParam = Argument("BuildVersion"); 5 | var versionParts = versionParam.Split('.'); 6 | 7 | var version = string.Format("{0}.{1}.{2}", versionParts[0],versionParts[1],versionParts[2]); 8 | var semVersion = local ? version : (version + string.Concat("-build-", versionParts[3])); 9 | var configuration = Argument("configuration", "Release"); 10 | var primaryAuthor = "Chase Florell"; 11 | 12 | var touchDir = MakeAbsolute(Directory("./build-artifacts/output/touch")); 13 | var droidDir = MakeAbsolute(Directory("./build-artifacts/output/droid")); 14 | var coreDir = MakeAbsolute(Directory("./build-artifacts/output/core")); 15 | var nugetOutDir = MakeAbsolute(Directory("./nuget")); 16 | Setup(context => 17 | { 18 | var binsToClean = GetDirectories("./src/**/bin/"); 19 | var artifactsToClean = new []{ 20 | touchDir.ToString(), 21 | droidDir.ToString(), 22 | coreDir.ToString(), 23 | nugetOutDir.ToString() 24 | }; 25 | CleanDirectories(binsToClean); 26 | CleanDirectories(artifactsToClean); 27 | 28 | //Executed BEFORE the first task. 29 | Information("Building version {0} of {1}.", semVersion, appName); 30 | }); 31 | 32 | Task("Default") 33 | .IsDependentOn("Package Library"); 34 | 35 | Task("Build Droid") 36 | .IsDependentOn("Patch Assembly Info") 37 | .Does(() => 38 | { 39 | MSBuild("./src/Xfx.Controls.Droid/Xfx.Controls.Droid.csproj", new MSBuildSettings 40 | { 41 | ToolVersion = MSBuildToolVersion.VS2017 42 | } 43 | .WithProperty("OutDir", droidDir.ToString()) 44 | .SetConfiguration(configuration)); 45 | }); 46 | 47 | Task("Build Touch") 48 | .IsDependentOn("Patch Assembly Info") 49 | .Does(() => 50 | { 51 | MSBuild("./src/Xfx.Controls.iOS/Xfx.Controls.iOS.csproj", new MSBuildSettings 52 | { 53 | ToolVersion = MSBuildToolVersion.VS2017, 54 | MSBuildPlatform = (Cake.Common.Tools.MSBuild.MSBuildPlatform)1 55 | } 56 | .WithProperty("OutDir", touchDir.ToString()) 57 | .SetConfiguration(configuration)); 58 | }); 59 | 60 | Task("Build Core") 61 | .IsDependentOn("Patch Assembly Info") 62 | .Does(() => 63 | { 64 | MSBuild("./src/Xfx.Controls/Xfx.Controls.csproj", new MSBuildSettings 65 | { 66 | ToolVersion = MSBuildToolVersion.VS2017 67 | } 68 | .WithProperty("OutDir", coreDir.ToString()) 69 | .SetConfiguration(configuration)); 70 | }); 71 | 72 | Task("Patch Assembly Info") 73 | .IsDependentOn("Nuget Restore") 74 | .Does(() => 75 | { 76 | var file = "./src/SolutionInfo.cs"; 77 | 78 | CreateAssemblyInfo(file, new AssemblyInfoSettings 79 | { 80 | Product = appName, 81 | Version = version, 82 | FileVersion = version, 83 | InformationalVersion = semVersion, 84 | Copyright = "Copyright (c) 2015 - " + DateTime.Now.Year.ToString() + " " + primaryAuthor 85 | }); 86 | }); 87 | 88 | Task("Nuget Restore") 89 | .Does(() => { 90 | NuGetRestore("./Xfx.Controls.sln", new NuGetRestoreSettings { NoCache = true }); 91 | }); 92 | 93 | 94 | 95 | Task("Package Library") 96 | .IsDependentOn("Build Droid") 97 | .IsDependentOn("Build Touch") 98 | .IsDependentOn("Build Core") 99 | .Does(() => { 100 | var nuGetPackSettings = new NuGetPackSettings { 101 | Id = appName, 102 | Version = version, 103 | Title = "Xamarin Forms Extended Controls", 104 | Authors = new[] {primaryAuthor}, 105 | LicenseUrl = new Uri("https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/master/LICENSE.md"), 106 | Description = "Xamarin Forms Extended Controls. Provides extended controls with a 'Material Design' flare.", 107 | ProjectUrl = new Uri("https://github.com/XamFormsExtended/Xfx.Controls"), 108 | Files = new [] { 109 | new NuSpecContent {Source = coreDir.ToString() + "/Xfx.Controls.dll", Target = "lib/netcore45"}, 110 | new NuSpecContent {Source = coreDir.ToString() + "/Xfx.Controls.dll", Target = "lib/netstandard1.3"}, 111 | new NuSpecContent {Source = coreDir.ToString() + "/Xfx.Controls.dll", Target = "lib/portable-net45+win8+wpa81+wp8"}, 112 | 113 | new NuSpecContent {Source = droidDir.ToString() + "/Xfx.Controls.Droid.dll", Target = "lib/MonoAndroid"}, 114 | new NuSpecContent {Source = droidDir.ToString() + "/Xfx.Controls.dll", Target = "lib/MonoAndroid"}, 115 | 116 | new NuSpecContent {Source = touchDir.ToString() + "/Xfx.Controls.iOS.dll", Target = "lib/Xamarin.iOS10"}, 117 | new NuSpecContent {Source = touchDir.ToString() + "/Xfx.Controls.dll", Target = "lib/Xamarin.iOS10"}, 118 | }, 119 | Dependencies = new [] { 120 | new NuSpecDependency { Id = "Xamarin.Forms", Version = "2.0" } 121 | }, 122 | BasePath = "./src", 123 | NoPackageAnalysis = true, 124 | OutputDirectory = nugetOutDir 125 | }; 126 | 127 | NuGetPack(nuGetPackSettings); 128 | }); 129 | 130 | RunTarget(target); -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################## 4 | # This is the Cake bootstrapper script for Linux and OS X. 5 | # This file was downloaded from https://github.com/cake-build/resources 6 | # Feel free to change this file to fit your needs. 7 | ########################################################################## 8 | 9 | # Define directories. 10 | SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 11 | TOOLS_DIR=$SCRIPT_DIR/tools 12 | ADDINS_DIR=$TOOLS_DIR/Addins 13 | MODULES_DIR=$TOOLS_DIR/Modules 14 | NUGET_EXE=$TOOLS_DIR/nuget.exe 15 | CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe 16 | PACKAGES_CONFIG=$TOOLS_DIR/packages.config 17 | PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum 18 | ADDINS_PACKAGES_CONFIG=$ADDINS_DIR/packages.config 19 | MODULES_PACKAGES_CONFIG=$MODULES_DIR/packages.config 20 | 21 | # Define md5sum or md5 depending on Linux/OSX 22 | MD5_EXE= 23 | if [[ "$(uname -s)" == "Darwin" ]]; then 24 | MD5_EXE="md5 -r" 25 | else 26 | MD5_EXE="md5sum" 27 | fi 28 | 29 | # Define default arguments. 30 | SCRIPT="build.cake" 31 | CAKE_ARGUMENTS=() 32 | 33 | # Parse arguments. 34 | for i in "$@"; do 35 | case $1 in 36 | -s|--script) SCRIPT="$2"; shift ;; 37 | --) shift; CAKE_ARGUMENTS+=("$@"); break ;; 38 | *) CAKE_ARGUMENTS+=("$1") ;; 39 | esac 40 | shift 41 | done 42 | 43 | # Make sure the tools folder exist. 44 | if [ ! -d "$TOOLS_DIR" ]; then 45 | mkdir "$TOOLS_DIR" 46 | fi 47 | 48 | # Make sure that packages.config exist. 49 | if [ ! -f "$TOOLS_DIR/packages.config" ]; then 50 | echo "Downloading packages.config..." 51 | curl -Lsfo "$TOOLS_DIR/packages.config" https://cakebuild.net/download/bootstrapper/packages 52 | if [ $? -ne 0 ]; then 53 | echo "An error occurred while downloading packages.config." 54 | exit 1 55 | fi 56 | fi 57 | 58 | # Download NuGet if it does not exist. 59 | if [ ! -f "$NUGET_EXE" ]; then 60 | echo "Downloading NuGet..." 61 | curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe 62 | if [ $? -ne 0 ]; then 63 | echo "An error occurred while downloading nuget.exe." 64 | exit 1 65 | fi 66 | fi 67 | 68 | # Restore tools from NuGet. 69 | pushd "$TOOLS_DIR" >/dev/null 70 | if [ ! -f "$PACKAGES_CONFIG_MD5" ] || [ "$( cat "$PACKAGES_CONFIG_MD5" | sed 's/\r$//' )" != "$( $MD5_EXE "$PACKAGES_CONFIG" | awk '{ print $1 }' )" ]; then 71 | find . -type d ! -name . ! -name 'Cake.Bakery' | xargs rm -rf 72 | fi 73 | 74 | mono "$NUGET_EXE" install -ExcludeVersion 75 | if [ $? -ne 0 ]; then 76 | echo "Could not restore NuGet tools." 77 | exit 1 78 | fi 79 | 80 | $MD5_EXE "$PACKAGES_CONFIG" | awk '{ print $1 }' >| "$PACKAGES_CONFIG_MD5" 81 | 82 | popd >/dev/null 83 | 84 | # Restore addins from NuGet. 85 | if [ -f "$ADDINS_PACKAGES_CONFIG" ]; then 86 | pushd "$ADDINS_DIR" >/dev/null 87 | 88 | mono "$NUGET_EXE" install -ExcludeVersion 89 | if [ $? -ne 0 ]; then 90 | echo "Could not restore NuGet addins." 91 | exit 1 92 | fi 93 | 94 | popd >/dev/null 95 | fi 96 | 97 | # Restore modules from NuGet. 98 | if [ -f "$MODULES_PACKAGES_CONFIG" ]; then 99 | pushd "$MODULES_DIR" >/dev/null 100 | 101 | mono "$NUGET_EXE" install -ExcludeVersion 102 | if [ $? -ne 0 ]; then 103 | echo "Could not restore NuGet modules." 104 | exit 1 105 | fi 106 | 107 | popd >/dev/null 108 | fi 109 | 110 | # Make sure that Cake has been installed. 111 | if [ ! -f "$CAKE_EXE" ]; then 112 | echo "Could not find Cake.exe at '$CAKE_EXE'." 113 | exit 1 114 | fi 115 | 116 | # Start Cake 117 | exec mono "$CAKE_EXE" $SCRIPT "${CAKE_ARGUMENTS[@]}" 118 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.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 you 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 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.Droid/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Content.PM; 3 | using Android.OS; 4 | 5 | namespace Xfx.Controls.Example.Droid 6 | { 7 | [Activity(Label = "Xfx.Controls.Example.Droid", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] 8 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity 9 | { 10 | protected override void OnCreate(Bundle bundle) 11 | { 12 | base.OnCreate(bundle); 13 | 14 | XfxControls.Init(); 15 | global::Xamarin.Forms.Forms.Init(this, bundle); 16 | LoadApplication(new App()); 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.Droid/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.Droid/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using Android.App; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("Xfx.Controls.Example.Droid")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Xfx.Controls.Example.Droid")] 14 | [assembly: AssemblyCopyright("Copyright © 2014")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: ComVisible(false)] 18 | 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | // 26 | // You can specify all the values or you can default the Build and Revision Numbers 27 | // by using the '*' as shown below: 28 | // [assembly: AssemblyVersion("1.0.*")] 29 | [assembly: AssemblyVersion("1.0.0.0")] 30 | [assembly: AssemblyFileVersion("1.0.0.0")] 31 | 32 | // Add some common permissions, these can be removed if not needed 33 | [assembly: UsesPermission(Android.Manifest.Permission.Internet)] 34 | [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)] 35 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.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.xml), 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-hdpi/ 12 | icon.png 13 | 14 | drawable-ldpi/ 15 | icon.png 16 | 17 | drawable-mdpi/ 18 | icon.png 19 | 20 | layout/ 21 | main.xml 22 | 23 | values/ 24 | strings.xml 25 | 26 | In order to get the build system to recognize Android resources, set the build action to 27 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 28 | instead operate on resource IDs. When you compile an Android application that uses resources, 29 | the build system will package the resources for distribution and generate a class called 30 | "Resource" that contains the tokens for each one of the resources included. For example, 31 | for the above Resources layout, this is what the Resource class would expose: 32 | 33 | public class Resource { 34 | public class drawable { 35 | public const int icon = 0x123; 36 | } 37 | 38 | public class layout { 39 | public const int main = 0x456; 40 | } 41 | 42 | public class strings { 43 | public const int first_string = 0xabc; 44 | public const int second_string = 0xbcd; 45 | } 46 | } 47 | 48 | You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main 49 | to reference the layout/main.xml file, or Resource.strings.first_string to reference the first 50 | string in the dictionary file values/strings.xml. 51 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.Droid/Resources/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.Droid/Resources/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.Droid/Resources/drawable-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.Droid/Resources/drawable-xhdpi/icon.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.Droid/Resources/drawable-xxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.Droid/Resources/drawable-xxhdpi/icon.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.Droid/Resources/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.Droid/Resources/drawable/icon.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.Droid/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using Foundation; 2 | using UIKit; 3 | 4 | namespace Xfx.Controls.Example.iOS 5 | { 6 | // The UIApplicationDelegate for the application. This class is responsible for launching the 7 | // User Interface of the application, as well as listening (and optionally responding) to 8 | // application events from iOS. 9 | [Register("AppDelegate")] 10 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate 11 | { 12 | // 13 | // This method is invoked when the application has loaded and is ready to run. In this 14 | // method you should instantiate the window, load the UI into it and then make the window 15 | // visible. 16 | // 17 | // You have 17 seconds to return from this method, or iOS will terminate your application. 18 | // 19 | public override bool FinishedLaunching(UIApplication app, NSDictionary options) 20 | { 21 | XfxControls.Init(); 22 | global::Xamarin.Forms.Forms.Init(); 23 | LoadApplication(new App()); 24 | 25 | return base.FinishedLaunching(app, options); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIDeviceFamily 6 | 7 | 1 8 | 2 9 | 10 | UISupportedInterfaceOrientations 11 | 12 | UIInterfaceOrientationPortrait 13 | UIInterfaceOrientationLandscapeLeft 14 | UIInterfaceOrientationLandscapeRight 15 | 16 | UISupportedInterfaceOrientations~ipad 17 | 18 | UIInterfaceOrientationPortrait 19 | UIInterfaceOrientationPortraitUpsideDown 20 | UIInterfaceOrientationLandscapeLeft 21 | UIInterfaceOrientationLandscapeRight 22 | 23 | MinimumOSVersion 24 | 10.3 25 | CFBundleDisplayName 26 | Xfx.Controls.Example 27 | CFBundleIdentifier 28 | com.yourcompany.Xfx.Controls.Example 29 | CFBundleVersion 30 | 1.0 31 | CFBundleIconFiles 32 | 33 | Icon-60@2x.png 34 | Icon-76.png 35 | Icon-76@2x.png 36 | Default.png 37 | Default@2x.png 38 | Default-568h@2x.png 39 | Default-Portrait.png 40 | Default-Portrait@2x.png 41 | Icon-Small-40.png 42 | Icon-Small-40@2x.png 43 | Icon-Small.png 44 | Icon-Small@2x.png 45 | 46 | UILaunchStoryboardName 47 | LaunchScreen 48 | CFBundleShortVersionString 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.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 Xfx.Controls.Example.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 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Xfx.Controls.Example.iOS")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Xfx.Controls.Example.iOS")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Default-568h@2x.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Default-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Default-Portrait.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Default-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Default-Portrait@2x.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Default.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Default@2x.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Icon-60@2x.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Icon-60@3x.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Icon-76.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Icon-76@2x.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Icon-Small-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Icon-Small-40.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Icon-Small-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Icon-Small-40@2x.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Icon-Small-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Icon-Small-40@3x.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Icon-Small.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Icon-Small@2x.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/Resources/Icon-Small@3x.png -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Media.xcassets/AppIcons.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "scale": "2x", 5 | "size": "20x20", 6 | "idiom": "iphone" 7 | }, 8 | { 9 | "scale": "3x", 10 | "size": "20x20", 11 | "idiom": "iphone" 12 | }, 13 | { 14 | "scale": "2x", 15 | "size": "29x29", 16 | "idiom": "iphone" 17 | }, 18 | { 19 | "scale": "3x", 20 | "size": "29x29", 21 | "idiom": "iphone" 22 | }, 23 | { 24 | "scale": "2x", 25 | "size": "40x40", 26 | "idiom": "iphone" 27 | }, 28 | { 29 | "scale": "3x", 30 | "size": "40x40", 31 | "idiom": "iphone" 32 | }, 33 | { 34 | "scale": "2x", 35 | "size": "60x60", 36 | "idiom": "iphone" 37 | }, 38 | { 39 | "scale": "3x", 40 | "size": "60x60", 41 | "idiom": "iphone" 42 | }, 43 | { 44 | "scale": "1x", 45 | "size": "20x20", 46 | "idiom": "ipad" 47 | }, 48 | { 49 | "scale": "2x", 50 | "size": "20x20", 51 | "idiom": "ipad" 52 | }, 53 | { 54 | "scale": "1x", 55 | "size": "29x29", 56 | "idiom": "ipad" 57 | }, 58 | { 59 | "scale": "2x", 60 | "size": "29x29", 61 | "idiom": "ipad" 62 | }, 63 | { 64 | "scale": "1x", 65 | "size": "40x40", 66 | "idiom": "ipad" 67 | }, 68 | { 69 | "scale": "2x", 70 | "size": "40x40", 71 | "idiom": "ipad" 72 | }, 73 | { 74 | "scale": "1x", 75 | "size": "76x76", 76 | "idiom": "ipad" 77 | }, 78 | { 79 | "scale": "2x", 80 | "size": "76x76", 81 | "idiom": "ipad" 82 | }, 83 | { 84 | "scale": "2x", 85 | "size": "83.5x83.5", 86 | "idiom": "ipad" 87 | }, 88 | { 89 | "scale": "1x", 90 | "size": "1024x1024", 91 | "idiom": "ios-marketing" 92 | } 93 | ], 94 | "properties": {}, 95 | "info": { 96 | "version": 1, 97 | "author": "xcode" 98 | } 99 | } -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/Resources/Media.xcassets/LaunchImages.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "orientation": "portrait", 5 | "extent": "full-screen", 6 | "minimum-system-version": "7.0", 7 | "scale": "2x", 8 | "size": "0x0", 9 | "idiom": "iphone" 10 | }, 11 | { 12 | "orientation": "portrait", 13 | "extent": "full-screen", 14 | "minimum-system-version": "7.0", 15 | "subtype": "retina4", 16 | "scale": "2x", 17 | "size": "0x0", 18 | "idiom": "iphone" 19 | }, 20 | { 21 | "orientation": "portrait", 22 | "extent": "full-screen", 23 | "minimum-system-version": "7.0", 24 | "scale": "1x", 25 | "size": "0x0", 26 | "idiom": "ipad" 27 | }, 28 | { 29 | "orientation": "landscape", 30 | "extent": "full-screen", 31 | "minimum-system-version": "7.0", 32 | "scale": "1x", 33 | "size": "0x0", 34 | "idiom": "ipad" 35 | }, 36 | { 37 | "orientation": "portrait", 38 | "extent": "full-screen", 39 | "minimum-system-version": "7.0", 40 | "scale": "2x", 41 | "size": "0x0", 42 | "idiom": "ipad" 43 | }, 44 | { 45 | "orientation": "landscape", 46 | "extent": "full-screen", 47 | "minimum-system-version": "7.0", 48 | "scale": "2x", 49 | "size": "0x0", 50 | "idiom": "ipad" 51 | } 52 | ], 53 | "properties": {}, 54 | "info": { 55 | "version": 1, 56 | "author": "" 57 | } 58 | } -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/iTunesArtwork: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/iTunesArtwork -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/iTunesArtwork@2x: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XamFormsExtended/Xfx.Controls/d62678df2962e816ce1c73cfdfc4d0578e6b0b32/example/Xfx.Controls.Example.iOS/iTunesArtwork@2x -------------------------------------------------------------------------------- /example/Xfx.Controls.Example.iOS/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example/App.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms; 2 | using Xamarin.Forms.Xaml; 3 | 4 | [assembly: XamlCompilation(XamlCompilationOptions.Compile)] 5 | namespace Xfx.Controls.Example 6 | { 7 | public class App : Application 8 | { 9 | public App() 10 | { 11 | // The root page of your application 12 | MainPage = new NavigationPage(new MainPage()); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /example/Xfx.Controls.Example/BaseViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Runtime.CompilerServices; 7 | using Xamarin.Forms; 8 | 9 | namespace Xfx.Controls.Example 10 | { 11 | public abstract class BaseViewModel : BindableObject, INotifyDataErrorInfo 12 | { 13 | public static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly(nameof(IsValid), 14 | typeof(bool), 15 | typeof(BaseViewModel), 16 | default(bool)); 17 | 18 | protected readonly Dictionary> Errors = new Dictionary>(); 19 | 20 | /// 21 | /// ReadOnly IsValid summary. This is a bindable property. 22 | /// 23 | public bool IsValid 24 | { 25 | get => (bool) GetValue(IsValidPropertyKey.BindableProperty); 26 | set => SetValue(IsValidPropertyKey, value); 27 | } 28 | 29 | public event EventHandler ErrorsChanged; 30 | 31 | public IEnumerable GetErrors(string propertyName) 32 | { 33 | IList errorsForName; 34 | Errors.TryGetValue(propertyName, out errorsForName); 35 | return errorsForName; 36 | } 37 | 38 | public bool HasErrors => Errors.Any(kv => kv.Value != null && kv.Value.Count > 0); 39 | 40 | 41 | public abstract void ValidateProperty([CallerMemberName] string propertyName = null); 42 | 43 | protected void RaiseErrorsChanged(string propertyName) => ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName)); 44 | } 45 | } -------------------------------------------------------------------------------- /example/Xfx.Controls.Example/Features/Controls/ControlsPage.xaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 90 | 91 | -------------------------------------------------------------------------------- /example/Xfx.Controls.Example/Features/Controls/ControlsPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Xamarin.Forms; 3 | 4 | namespace Xfx.Controls.Example.Features.Controls 5 | { 6 | public partial class ControlsPage 7 | { 8 | public ControlsPage() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | private void Email_OnFocused(object sender, FocusEventArgs e) 14 | { 15 | Debug.WriteLine("Email Focused"); 16 | } 17 | 18 | private void Email_OnUnfocused(object sender, FocusEventArgs e) 19 | { 20 | Debug.WriteLine("Email Unfocused"); 21 | } 22 | 23 | private void Email_ItemSelected(object sender, XfxSelectedItemChangedEventArgs args) 24 | { 25 | Debug.WriteLine($"Selected Item from Event: {args.SelectedItem}"); 26 | Debug.WriteLine($"Selected Item index from Event: {args.SelectedItemIndex}"); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /example/Xfx.Controls.Example/Features/Controls/ControlsPageModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Runtime.CompilerServices; 7 | using Xamarin.Forms; 8 | 9 | namespace Xfx.Controls.Example.Features.Controls 10 | { 11 | public class MainPageModel : BaseViewModel 12 | { 13 | // here's a list of email address suffixes that we're going to use 14 | private static readonly string[] _emails = 15 | { 16 | "@gmail.com", 17 | "@hotmail.com", 18 | "@me.com", 19 | "@outlook.com", 20 | "@mail.com", 21 | "@live.com", // does anyone care about this one? haha 22 | "@yahoo.com" // seriously, does anyone use this anymore? 23 | }; 24 | 25 | public static readonly BindableProperty EmailAddressProperty = BindableProperty.Create(nameof(EmailAddress), 26 | typeof(string), 27 | typeof(MainPage), 28 | default(string), 29 | propertyChanged: EmailAddressPropertyChanged); 30 | 31 | public static readonly BindableProperty EmailSuggestionsProperty = 32 | BindableProperty.Create(nameof(EmailSuggestions), 33 | typeof(ObservableCollection), 34 | typeof(MainPage), 35 | new ObservableCollection()); 36 | 37 | public static readonly BindableProperty NameProperty = BindableProperty.Create(nameof(Name), 38 | typeof(string), 39 | typeof(MainPage), 40 | default(string)); 41 | 42 | public static readonly BindableProperty FooProperty = BindableProperty.Create(nameof(Foo), 43 | typeof(string), 44 | typeof(MainPageModel), 45 | default(string)); 46 | 47 | public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create(nameof(SelectedItem), 48 | typeof(object), 49 | typeof(MainPageModel)); 50 | 51 | public MainPageModel() 52 | { 53 | Name = "John Smith Jr."; 54 | EmailAddress = ""; 55 | } 56 | 57 | /// 58 | /// Text . This is a bindable property. 59 | /// 60 | public string EmailAddress 61 | { 62 | get => (string)GetValue(EmailAddressProperty); 63 | set => SetValue(EmailAddressProperty, value); 64 | } 65 | 66 | /// 67 | /// Email Suggestions collection . This is a bindable property. 68 | /// 69 | public ObservableCollection EmailSuggestions 70 | { 71 | get => (ObservableCollection)GetValue(EmailSuggestionsProperty); 72 | set => SetValue(EmailSuggestionsProperty, value); 73 | } 74 | 75 | /// 76 | /// Foo summary. This is a bindable property. 77 | /// 78 | public string Foo 79 | { 80 | get => (string)GetValue(FooProperty); 81 | set 82 | { 83 | SetValue(FooProperty, value); 84 | ValidateProperty(); 85 | } 86 | } 87 | 88 | /// 89 | /// Name summary. This is a bindable property. 90 | /// 91 | public string Name 92 | { 93 | get => (string)GetValue(NameProperty); 94 | set 95 | { 96 | SetValue(NameProperty, value); 97 | ValidateProperty(); 98 | } 99 | } 100 | 101 | 102 | /// 103 | /// SelectedItem summary. This is a bindable property. 104 | /// 105 | public object SelectedItem 106 | { 107 | get => GetValue(SelectedItemProperty); 108 | set 109 | { 110 | SetValue(SelectedItemProperty, value); 111 | Debug.WriteLine($"Selected Item from ViewModel {value}"); 112 | } 113 | } 114 | 115 | // you can customize your sorting algorithim to however you want it to work. 116 | public Func, ICollection> SortingAlgorithm { get; } = 117 | (text, values) => values 118 | .Where(x => x.ToLower().StartsWith(text.ToLower())) 119 | .OrderBy(x => x) 120 | .ToList(); 121 | 122 | private static void EmailAddressPropertyChanged(BindableObject bindable, object oldvalue, object newvalue) 123 | { 124 | var model = (MainPageModel)bindable; 125 | // make sure we have the latest string. 126 | var text = newvalue.ToString(); 127 | 128 | // if the text is empty or already contains an @ symbol, don't update anything. 129 | if (text.Contains("@")) return; 130 | 131 | /* 132 | note, you could use some sort of FastObservableCollection if 133 | you want the notification to only happen a single time. 134 | i'm not doing that here because I'm trying to K.I.S.S this example 135 | for reference: http://stackoverflow.com/a/13303245/124069 136 | */ 137 | 138 | // clear the old suggestions, you're starting over. This also can be more efficient, 139 | // I'll leave that for you to figure out. 140 | model.EmailSuggestions.Clear(); 141 | 142 | // side note: for loops will add a tiny performance boost over foreach 143 | for (var i = 0; i < _emails.Length; i++) 144 | model.EmailSuggestions.Add($"{text}{_emails[i]}"); 145 | } 146 | 147 | public override void ValidateProperty([CallerMemberName]string propertyName = null) 148 | { 149 | // I actually recommend using FluentValidation for this 150 | switch (propertyName) 151 | { 152 | case nameof(Name): { ValidateName(); break; } 153 | case nameof(Foo): { ValidateFoo(); break; } 154 | } 155 | 156 | IsValid = Errors.Any(); 157 | RaiseErrorsChanged(propertyName); 158 | } 159 | 160 | private void ValidateFoo() 161 | { 162 | const string nullMessage = "Foo cannot be empty"; 163 | var nameMessages = new List(); 164 | if (string.IsNullOrEmpty(Foo)) 165 | { 166 | nameMessages.Add(nullMessage); 167 | Errors[nameof(Foo)] = nameMessages; 168 | } 169 | else 170 | { 171 | if (Errors.ContainsKey(nameof(Foo))) 172 | { 173 | Errors.Remove(nameof(Foo)); 174 | } 175 | } 176 | } 177 | 178 | private void ValidateName() 179 | { 180 | const string nullMessage = "Name cannot be empty"; 181 | var nameMessages = new List(); 182 | if (string.IsNullOrEmpty(Name)) 183 | { 184 | nameMessages.Add(nullMessage); 185 | Errors[nameof(Name)] = nameMessages; 186 | } 187 | else 188 | { 189 | if (Errors.ContainsKey(nameof(Name))) 190 | { 191 | Errors.Remove(nameof(Name)); 192 | } 193 | } 194 | } 195 | } 196 | } -------------------------------------------------------------------------------- /example/Xfx.Controls.Example/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 27 |