├── .gitignore
├── LICENSE
├── README.md
├── XamUIDemo.Android
├── Assets
│ └── AboutAssets.txt
├── MainActivity.cs
├── Properties
│ ├── AndroidManifest.xml
│ └── AssemblyInfo.cs
├── RenderersAndroid
│ ├── BorderlessEntryRenderer.cs
│ ├── PancakeDrawable.cs
│ ├── PancakeViewRenderer.cs
│ ├── RoundedCornerOutlineProvider.cs
│ └── ShapeUtils.cs
├── Resources
│ ├── AboutResources.txt
│ ├── Resource.designer.cs
│ ├── drawable
│ │ ├── bg1.png
│ │ ├── bg9.png
│ │ └── logo.png
│ ├── layout
│ │ ├── Tabbar.xml
│ │ └── Toolbar.xml
│ ├── mipmap-anydpi-v26
│ │ ├── icon.xml
│ │ └── icon_round.xml
│ ├── mipmap-hdpi
│ │ ├── icon.png
│ │ ├── launcher_foreground.png
│ │ └── logo.png
│ ├── mipmap-mdpi
│ │ ├── icon.png
│ │ ├── launcher_foreground.png
│ │ └── logo.png
│ ├── mipmap-xhdpi
│ │ ├── icon.png
│ │ ├── launcher_foreground.png
│ │ └── logo.png
│ ├── mipmap-xxhdpi
│ │ ├── icon.png
│ │ ├── launcher_foreground.png
│ │ └── logo.png
│ ├── mipmap-xxxhdpi
│ │ ├── icon.png
│ │ ├── launcher_foreground.png
│ │ └── logo.png
│ └── values
│ │ ├── colors.xml
│ │ └── styles.xml
└── XamUIDemo.Android.csproj
├── XamUIDemo.iOS
├── AppDelegate.cs
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-1024.png
│ │ ├── Icon-120-1.png
│ │ ├── Icon-120.png
│ │ ├── Icon-152.png
│ │ ├── Icon-167.png
│ │ ├── Icon-180.png
│ │ ├── Icon-20.png
│ │ ├── Icon-29.png
│ │ ├── Icon-40-1.png
│ │ ├── Icon-40-2.png
│ │ ├── Icon-40.png
│ │ ├── Icon-58-1.png
│ │ ├── Icon-58.png
│ │ ├── Icon-60.png
│ │ ├── Icon-76.png
│ │ ├── Icon-80-1.png
│ │ ├── Icon-80.png
│ │ └── Icon-87.png
├── Entitlements.plist
├── Info.plist
├── Main.cs
├── Properties
│ └── AssemblyInfo.cs
├── RenderersiOS
│ ├── BorderlessEntryRenderer.cs
│ ├── PancakeViewRenderer.cs
│ └── ShapeUtils.cs
├── Resources
│ ├── Default-568h@2x.png
│ ├── Default-Portrait.png
│ ├── Default-Portrait@2x.png
│ ├── Default.png
│ ├── Default@2x.png
│ ├── LaunchScreen.storyboard
│ ├── bg1.png
│ ├── bg9.png
│ └── logo.png
└── XamUIDemo.iOS.csproj
├── XamUIDemo.sln
└── XamUIDemo
├── Animations
└── ViewAnimations.cs
├── App.xaml
├── App.xaml.cs
├── AssemblyInfo.cs
├── LoginPages
├── LoginPage10.xaml
├── LoginPage10.xaml.cs
├── LoginPage14.xaml
├── LoginPage14.xaml.cs
├── LoginPage2.xaml
└── LoginPage2.xaml.cs
├── MainPage.xaml
├── MainPage.xaml.cs
├── Renderers
├── BlurredImage.cs
├── BorderlessEntry.cs
└── PancakeView.cs
├── Styles
├── BorderDrawingStyle.cs
├── GradientStop.cs
└── GradientStopCollection.cs
└── XamUIDemo.csproj
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
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 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Coverlet is a free, cross platform Code Coverage Tool
141 | coverage*[.json, .xml, .info]
142 |
143 | # Visual Studio code coverage results
144 | *.coverage
145 | *.coveragexml
146 |
147 | # NCrunch
148 | _NCrunch_*
149 | .*crunch*.local.xml
150 | nCrunchTemp_*
151 |
152 | # MightyMoose
153 | *.mm.*
154 | AutoTest.Net/
155 |
156 | # Web workbench (sass)
157 | .sass-cache/
158 |
159 | # Installshield output folder
160 | [Ee]xpress/
161 |
162 | # DocProject is a documentation generator add-in
163 | DocProject/buildhelp/
164 | DocProject/Help/*.HxT
165 | DocProject/Help/*.HxC
166 | DocProject/Help/*.hhc
167 | DocProject/Help/*.hhk
168 | DocProject/Help/*.hhp
169 | DocProject/Help/Html2
170 | DocProject/Help/html
171 |
172 | # Click-Once directory
173 | publish/
174 |
175 | # Publish Web Output
176 | *.[Pp]ublish.xml
177 | *.azurePubxml
178 | # Note: Comment the next line if you want to checkin your web deploy settings,
179 | # but database connection strings (with potential passwords) will be unencrypted
180 | *.pubxml
181 | *.publishproj
182 |
183 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
184 | # checkin your Azure Web App publish settings, but sensitive information contained
185 | # in these scripts will be unencrypted
186 | PublishScripts/
187 |
188 | # NuGet Packages
189 | *.nupkg
190 | # NuGet Symbol Packages
191 | *.snupkg
192 | # The packages folder can be ignored because of Package Restore
193 | **/[Pp]ackages/*
194 | # except build/, which is used as an MSBuild target.
195 | !**/[Pp]ackages/build/
196 | # Uncomment if necessary however generally it will be regenerated when needed
197 | #!**/[Pp]ackages/repositories.config
198 | # NuGet v3's project.json files produces more ignorable files
199 | *.nuget.props
200 | *.nuget.targets
201 |
202 | # Microsoft Azure Build Output
203 | csx/
204 | *.build.csdef
205 |
206 | # Microsoft Azure Emulator
207 | ecf/
208 | rcf/
209 |
210 | # Windows Store app package directories and files
211 | AppPackages/
212 | BundleArtifacts/
213 | Package.StoreAssociation.xml
214 | _pkginfo.txt
215 | *.appx
216 | *.appxbundle
217 | *.appxupload
218 |
219 | # Visual Studio cache files
220 | # files ending in .cache can be ignored
221 | *.[Cc]ache
222 | # but keep track of directories ending in .cache
223 | !?*.[Cc]ache/
224 |
225 | # Others
226 | ClientBin/
227 | ~$*
228 | *~
229 | *.dbmdl
230 | *.dbproj.schemaview
231 | *.jfm
232 | *.pfx
233 | *.publishsettings
234 | orleans.codegen.cs
235 |
236 | # Including strong name files can present a security risk
237 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
238 | #*.snk
239 |
240 | # Since there are multiple workflows, uncomment next line to ignore bower_components
241 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
242 | #bower_components/
243 |
244 | # RIA/Silverlight projects
245 | Generated_Code/
246 |
247 | # Backup & report files from converting an old project file
248 | # to a newer Visual Studio version. Backup files are not needed,
249 | # because we have git ;-)
250 | _UpgradeReport_Files/
251 | Backup*/
252 | UpgradeLog*.XML
253 | UpgradeLog*.htm
254 | ServiceFabricBackup/
255 | *.rptproj.bak
256 |
257 | # SQL Server files
258 | *.mdf
259 | *.ldf
260 | *.ndf
261 |
262 | # Business Intelligence projects
263 | *.rdl.data
264 | *.bim.layout
265 | *.bim_*.settings
266 | *.rptproj.rsuser
267 | *- [Bb]ackup.rdl
268 | *- [Bb]ackup ([0-9]).rdl
269 | *- [Bb]ackup ([0-9][0-9]).rdl
270 |
271 | # Microsoft Fakes
272 | FakesAssemblies/
273 |
274 | # GhostDoc plugin setting file
275 | *.GhostDoc.xml
276 |
277 | # Node.js Tools for Visual Studio
278 | .ntvs_analysis.dat
279 | node_modules/
280 |
281 | # Visual Studio 6 build log
282 | *.plg
283 |
284 | # Visual Studio 6 workspace options file
285 | *.opt
286 |
287 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
288 | *.vbw
289 |
290 | # Visual Studio LightSwitch build output
291 | **/*.HTMLClient/GeneratedArtifacts
292 | **/*.DesktopClient/GeneratedArtifacts
293 | **/*.DesktopClient/ModelManifest.xml
294 | **/*.Server/GeneratedArtifacts
295 | **/*.Server/ModelManifest.xml
296 | _Pvt_Extensions
297 |
298 | # Paket dependency manager
299 | .paket/paket.exe
300 | paket-files/
301 |
302 | # FAKE - F# Make
303 | .fake/
304 |
305 | # CodeRush personal settings
306 | .cr/personal
307 |
308 | # Python Tools for Visual Studio (PTVS)
309 | __pycache__/
310 | *.pyc
311 |
312 | # Cake - Uncomment if you are using it
313 | # tools/**
314 | # !tools/packages.config
315 |
316 | # Tabs Studio
317 | *.tss
318 |
319 | # Telerik's JustMock configuration file
320 | *.jmconfig
321 |
322 | # BizTalk build output
323 | *.btp.cs
324 | *.btm.cs
325 | *.odx.cs
326 | *.xsd.cs
327 |
328 | # OpenCover UI analysis results
329 | OpenCover/
330 |
331 | # Azure Stream Analytics local run output
332 | ASALocalRun/
333 |
334 | # MSBuild Binary and Structured Log
335 | *.binlog
336 |
337 | # NVidia Nsight GPU debugger configuration file
338 | *.nvuser
339 |
340 | # MFractors (Xamarin productivity tool) working folder
341 | .mfractor/
342 |
343 | # Local History for Visual Studio
344 | .localhistory/
345 |
346 | # BeatPulse healthcheck temp database
347 | healthchecksdb
348 |
349 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
350 | MigrationBackup/
351 |
352 | # Ionide (cross platform F# VS Code tools) working folder
353 | .ionide/
354 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Ufuk
4 |
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # XamLoginUIDemo
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | XamUI Login Page UI Kit
13 | XamUI Login Page UI Kit
14 | It is an Android and iOS compatible Login Page design project made with Xamarin Forms.
15 |
16 | Includes 15 unique login screen designs.
17 | You can use these designs seamlessly in your applications, the design is made more functional with beautiful and clean animations.
18 |
19 | Application Features
20 |
21 |
22 | Unique Designs
23 |
24 |
25 | Dynamic Pages
26 |
27 |
28 | Detailed Code Structure
29 |
30 |
31 | Unique Animations
32 |
33 |
34 | Custom Controls
35 |
36 |
37 | Gradient View
38 |
39 |
40 |
41 | Want to use this Application for your business or reuse?
42 | We think that is fantastic! Already we have several clients that are using a similar template and love the results. If you are looking to use this application for production proposes you will need to purchase an extended license. For development and testing proposes you are able to use a regular license.
43 | What is Xamarin?
44 | Xamarin is an open-source platform for building modern and performant applications for iOS , Android , and Windows with .NET. Xamarin is an abstraction layer that manages communication of shared code with underlying platform code. Xamarin runs in a managed environment that provides conveniences such as memory allocation and garbage collection. Xamarin enables developers to share an average of 90% of their application across platforms. This pattern allows developers to write all of their business logic in a single language (or reuse existing application code) but achieve native performance, look, and feel on each platform. Xamarin applications can be written on PC or Mac and compile into native application packages, such as an .apk file on Android , or an .ipa file on iOS . More İnformation for Xamarin
45 |
46 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/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 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content.PM;
3 | using Android.Runtime;
4 | using Android.OS;
5 |
6 | namespace XamUIDemo.Droid
7 | {
8 | [Activity(Label = "XamUIDemo", Icon = "@mipmap/logo", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
9 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
10 | {
11 | protected override void OnCreate(Bundle savedInstanceState)
12 | {
13 | TabLayoutResource = Resource.Layout.Tabbar;
14 | ToolbarResource = Resource.Layout.Toolbar;
15 |
16 | base.OnCreate(savedInstanceState);
17 |
18 | Xamarin.Essentials.Platform.Init(this, savedInstanceState);
19 | global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
20 | LoadApplication(new App());
21 | }
22 | public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
23 | {
24 | Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
25 |
26 | base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/XamUIDemo.Android/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/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("XamUIDemo.Android")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("XamUIDemo.Android")]
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 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/RenderersAndroid/BorderlessEntryRenderer.cs:
--------------------------------------------------------------------------------
1 | using Android.Content;
2 | using Xamarin.Forms;
3 | using Xamarin.Forms.Platform.Android;
4 | using XamLoginUIDemo.Droid.RenderersAndroid;
5 | using XamUIDemo.Renderers;
6 |
7 | [assembly: ExportRenderer(typeof(BorderlessEntry), typeof(BorderlessBorderlessEntryRenderer))]
8 | namespace XamLoginUIDemo.Droid.RenderersAndroid
9 | {
10 | public class BorderlessBorderlessEntryRenderer : EntryRenderer
11 | {
12 | public BorderlessBorderlessEntryRenderer(Context context) : base(context)
13 | {
14 | }
15 |
16 | protected override void OnElementChanged(ElementChangedEventArgs e)
17 | {
18 | base.OnElementChanged(e);
19 | if (e.OldElement == null)
20 | {
21 | Control.Background = null;
22 | }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/XamUIDemo.Android/RenderersAndroid/PancakeDrawable.cs:
--------------------------------------------------------------------------------
1 | using Android.Graphics;
2 | using Android.Graphics.Drawables;
3 | using System;
4 | using System.ComponentModel;
5 | using System.Linq;
6 | using XamLoginUIDemo.Droid;
7 | using Xamarin.Forms;
8 | using ACanvas = Android.Graphics.Canvas;
9 | using Xamarin.Forms.Platform.Android;
10 | using XamUIDemo.Renderers;
11 |
12 | namespace XamUIDemo.Droid.Renderers
13 | {
14 | public class PancakeDrawable : Drawable
15 | {
16 | readonly PancakeView _pancake;
17 | readonly Func _convertToPixels;
18 | Bitmap _normalBitmap;
19 | bool _isDisposed;
20 |
21 | public override int Opacity
22 | {
23 | get { return 0; }
24 | }
25 |
26 | public PancakeDrawable(PancakeView pancake, Func convertToPixels)
27 | {
28 | _pancake = pancake;
29 | _convertToPixels = convertToPixels;
30 | _pancake.PropertyChanged += PancakeViewOnPropertyChanged;
31 | }
32 |
33 | public override void Draw(ACanvas canvas)
34 | {
35 | int width = Bounds.Width();
36 | int height = Bounds.Height();
37 |
38 | if (width <= 0 || height <= 0)
39 | {
40 | DisposeBitmap();
41 |
42 | return;
43 | }
44 |
45 | try
46 | {
47 | if (_normalBitmap == null || _normalBitmap.Height != height || _normalBitmap.Width != width)
48 | {
49 | // If the user changes the orientation of the screen, make sure to destroy reference before
50 | // reassigning a new bitmap reference.
51 | DisposeBitmap();
52 |
53 | _normalBitmap = CreateBitmap(false, width, height);
54 | }
55 | }
56 | catch (ObjectDisposedException)
57 | {
58 | // This bitmap will sometimes be disposed as ListView/CollectionView scrolling or refreshing happens,
59 | // so we re-create the bitmap again.
60 | _normalBitmap = CreateBitmap(false, width, height);
61 | }
62 |
63 | using (var paint = new Paint())
64 | {
65 | canvas.DrawBitmap(_normalBitmap, 0, 0, paint);
66 | }
67 | }
68 |
69 | private void DisposeBitmap()
70 | {
71 | if (_normalBitmap != null)
72 | {
73 | _normalBitmap.Dispose();
74 | _normalBitmap = null;
75 | }
76 | }
77 |
78 | public override void SetAlpha(int alpha)
79 | {
80 | }
81 |
82 | public override void SetColorFilter(ColorFilter colorFilter)
83 | {
84 | }
85 |
86 | protected override bool OnStateChange(int[] state)
87 | {
88 | return false;
89 | }
90 |
91 | Bitmap CreateBitmap(bool pressed, int width, int height)
92 | {
93 | Bitmap bitmap;
94 |
95 | using (Bitmap.Config config = Bitmap.Config.Argb8888)
96 | {
97 | bitmap = Bitmap.CreateBitmap(width, height, config);
98 | }
99 |
100 | using (var canvas = new ACanvas(bitmap))
101 | {
102 | DrawCanvas(canvas, width, height, pressed);
103 | }
104 |
105 | return bitmap;
106 | }
107 |
108 | void DrawBackground(ACanvas canvas, int width, int height, CornerRadius cornerRadius, bool pressed)
109 | {
110 | using (var paint = new Paint { AntiAlias = true })
111 | using (Path.Direction direction = Path.Direction.Cw)
112 | using (Paint.Style style = Paint.Style.Fill)
113 | {
114 | var path = new Path();
115 |
116 | if (_pancake.Sides != 4)
117 | {
118 | path = ShapeUtils.CreatePolygonPath(width, height, _pancake.Sides, _pancake.CornerRadius.TopLeft, _pancake.OffsetAngle);
119 | }
120 | else
121 | {
122 | float topLeft = _convertToPixels(cornerRadius.TopLeft);
123 | float topRight = _convertToPixels(cornerRadius.TopRight);
124 | float bottomRight = _convertToPixels(cornerRadius.BottomRight);
125 | float bottomLeft = _convertToPixels(cornerRadius.BottomLeft);
126 |
127 | path = ShapeUtils.CreateRoundedRectPath(width, height, topLeft, topRight, bottomRight, bottomLeft);
128 | }
129 |
130 | if ((_pancake.BackgroundGradientStartColor != default(Xamarin.Forms.Color) && _pancake.BackgroundGradientEndColor != default(Xamarin.Forms.Color)) || (_pancake.BackgroundGradientStops != null && _pancake.BackgroundGradientStops.Any()))
131 | {
132 | var angle = _pancake.BackgroundGradientAngle / 360.0;
133 |
134 | // Calculate the new positions based on angle between 0-360.
135 | var a = width * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.75) / 2)), 2);
136 | var b = height * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.0) / 2)), 2);
137 | var c = width * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.25) / 2)), 2);
138 | var d = height * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.5) / 2)), 2);
139 |
140 | if (_pancake.BackgroundGradientStops != null && _pancake.BackgroundGradientStops.Count > 0)
141 | {
142 | // A range of colors is given. Let's add them.
143 | var orderedStops = _pancake.BackgroundGradientStops.OrderBy(x => x.Offset).ToList();
144 | var colors = orderedStops.Select(x => x.Color.ToAndroid().ToArgb()).ToArray();
145 | var locations = orderedStops.Select(x => x.Offset).ToArray();
146 |
147 | var shader = new LinearGradient(width - (float)a, (float)b, width - (float)c, (float)d, colors, locations, Shader.TileMode.Clamp);
148 | paint.SetShader(shader);
149 | }
150 | else
151 | {
152 | // Only two colors provided, use that.
153 | var shader = new LinearGradient(width - (float)a, (float)b, width - (float)c, (float)d, _pancake.BackgroundGradientStartColor.ToAndroid(), _pancake.BackgroundGradientEndColor.ToAndroid(), Shader.TileMode.Clamp);
154 | paint.SetShader(shader);
155 | }
156 | }
157 | else
158 | {
159 | global::Android.Graphics.Color color = _pancake.BackgroundColor.ToAndroid();
160 | paint.SetStyle(style);
161 | paint.Color = color;
162 | }
163 |
164 | canvas.DrawPath(path, paint);
165 | }
166 | }
167 |
168 | void PancakeViewOnPropertyChanged(object sender, PropertyChangedEventArgs e)
169 | {
170 | if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName ||
171 | e.PropertyName == PancakeView.CornerRadiusProperty.PropertyName ||
172 | e.PropertyName == PancakeView.BackgroundGradientAngleProperty.PropertyName ||
173 | e.PropertyName == PancakeView.BackgroundGradientStartColorProperty.PropertyName ||
174 | e.PropertyName == PancakeView.BackgroundGradientEndColorProperty.PropertyName ||
175 | e.PropertyName == PancakeView.BackgroundGradientStopsProperty.PropertyName ||
176 | e.PropertyName == PancakeView.SidesProperty.PropertyName ||
177 | e.PropertyName == PancakeView.OffsetAngleProperty.PropertyName)
178 | {
179 | if (_normalBitmap == null)
180 | return;
181 |
182 | using (var canvas = new ACanvas(_normalBitmap))
183 | {
184 | int width = Bounds.Width();
185 | int height = Bounds.Height();
186 | canvas.DrawColor(global::Android.Graphics.Color.Black, PorterDuff.Mode.Clear);
187 | DrawCanvas(canvas, width, height, false);
188 | }
189 |
190 | InvalidateSelf();
191 | }
192 | }
193 |
194 | void DrawCanvas(ACanvas canvas, int width, int height, bool pressed)
195 | {
196 | DrawBackground(canvas, width, height, _pancake.CornerRadius, pressed);
197 | }
198 |
199 | protected override void Dispose(bool disposing)
200 | {
201 | if (disposing && !_isDisposed)
202 | {
203 | DisposeBitmap();
204 |
205 | if (_pancake != null)
206 | {
207 | _pancake.PropertyChanged -= PancakeViewOnPropertyChanged;
208 | }
209 |
210 | _isDisposed = true;
211 | }
212 |
213 | base.Dispose(disposing);
214 | }
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/RenderersAndroid/PancakeViewRenderer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using XamUIDemo.Droid.Renderers;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using Android.Content;
6 | using Android.Graphics;
7 | using Android.OS;
8 | using Android.Support.V4.View;
9 | using Xamarin.Forms;
10 | using ACanvas = Android.Graphics.Canvas;
11 | using Xamarin.Forms.Platform.Android;
12 | using XamUIDemo.Styles;
13 | using XamUIDemo.Renderers;
14 |
15 | [assembly: ExportRenderer(typeof(PancakeView), typeof(PancakeViewRenderer))]
16 |
17 | namespace XamUIDemo.Droid.Renderers
18 | {
19 | public class PancakeViewRenderer : VisualElementRenderer
20 | {
21 | bool _disposed;
22 | private PancakeDrawable _drawable;
23 |
24 | public PancakeViewRenderer(Context context) : base(context)
25 | {
26 | }
27 |
28 | ///
29 | /// This method ensures that we don't get stripped out by the linker.
30 | ///
31 | public static void Init()
32 | {
33 | #pragma warning disable 0219
34 | var ignore1 = typeof(PancakeViewRenderer);
35 | var ignore2 = typeof(PancakeView);
36 | #pragma warning restore 0219
37 | }
38 |
39 | protected override void OnElementChanged(ElementChangedEventArgs e)
40 | {
41 | base.OnElementChanged(e);
42 |
43 | if (e.NewElement != null && e.OldElement == null)
44 | {
45 | var pancake = (Element as PancakeView);
46 |
47 | // HACK: When there are no children we add a Grid element to trigger DrawChild.
48 | // This should be improved upon, but I haven't found out a nice way to be able to clip
49 | // the children and add the border on top without using DrawChild.
50 | if (pancake.Content == null)
51 | {
52 | pancake.Content = new Grid();
53 | }
54 |
55 | Validate(pancake);
56 |
57 | this.SetBackground(_drawable = new PancakeDrawable(pancake, Context.ToPixels));
58 |
59 | SetupShadow(pancake);
60 | }
61 | }
62 |
63 | private void Validate(PancakeView pancake)
64 | {
65 | // Angle needs to be between 0-360.
66 | if (pancake.BackgroundGradientAngle < 0 || pancake.BackgroundGradientAngle > 360)
67 | throw new ArgumentException("Please provide a valid background gradient angle.", nameof(PancakeView.BackgroundGradientAngle));
68 |
69 | if (pancake.OffsetAngle < 0 || pancake.OffsetAngle > 360)
70 | throw new ArgumentException("Please provide a valid offset angle.", nameof(PancakeView.OffsetAngle));
71 |
72 | // min value for sides is 3
73 | if (pancake.Sides < 3)
74 | throw new ArgumentException("Please provide a valid value for sides.", nameof(PancakeView.Sides));
75 |
76 | }
77 |
78 | private void SetupShadow(PancakeView pancake)
79 | {
80 | if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
81 | {
82 | // clear previous shadow/elevation
83 | this.Elevation = 0;
84 | this.TranslationZ = 0;
85 |
86 | bool hasShadowOrElevation = pancake.HasShadow || pancake.Elevation > 0;
87 |
88 | // If it has a shadow, give it a default Droid looking shadow.
89 | if (pancake.HasShadow)
90 | {
91 | this.Elevation = 10;
92 | this.TranslationZ = 10;
93 | }
94 |
95 | // However if it has a specified elevation add the desired one
96 | if (pancake.Elevation > 0)
97 | {
98 | this.Elevation = 0;
99 | this.TranslationZ = 0;
100 | ViewCompat.SetElevation(this, Context.ToPixels(pancake.Elevation));
101 | }
102 |
103 | if (hasShadowOrElevation)
104 | {
105 | // To have shadow show up, we need to clip.
106 | this.OutlineProvider = new RoundedCornerOutlineProvider(pancake, Context.ToPixels);
107 | this.ClipToOutline = true;
108 | }
109 | else
110 | {
111 | this.OutlineProvider = null;
112 | this.ClipToOutline = false;
113 | }
114 | }
115 | }
116 |
117 | protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
118 | {
119 | var pancake = Element as PancakeView;
120 | Validate(pancake);
121 |
122 | base.OnElementPropertyChanged(sender, e);
123 | if (e.PropertyName == PancakeView.BorderColorProperty.PropertyName ||
124 | e.PropertyName == PancakeView.BorderThicknessProperty.PropertyName ||
125 | e.PropertyName == PancakeView.BorderIsDashedProperty.PropertyName ||
126 | e.PropertyName == PancakeView.BorderDrawingStyleProperty.PropertyName ||
127 | e.PropertyName == PancakeView.BorderGradientAngleProperty.PropertyName ||
128 | e.PropertyName == PancakeView.BorderGradientEndColorProperty.PropertyName ||
129 | e.PropertyName == PancakeView.BorderGradientStartColorProperty.PropertyName ||
130 | e.PropertyName == PancakeView.BorderGradientStopsProperty.PropertyName)
131 | {
132 | Invalidate();
133 | }
134 | else if (e.PropertyName == PancakeView.SidesProperty.PropertyName ||
135 | e.PropertyName == PancakeView.OffsetAngleProperty.PropertyName ||
136 | e.PropertyName == PancakeView.HasShadowProperty.PropertyName ||
137 | e.PropertyName == PancakeView.ElevationProperty.PropertyName)
138 | {
139 | SetupShadow(pancake);
140 | }
141 | else if (e.PropertyName == PancakeView.CornerRadiusProperty.PropertyName)
142 | {
143 | Invalidate();
144 | SetupShadow(pancake);
145 | }
146 | else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
147 | {
148 | _drawable.Dispose();
149 | this.SetBackground(_drawable = new PancakeDrawable(pancake, Context.ToPixels));
150 | }
151 | }
152 |
153 | protected override void Dispose(bool disposing)
154 | {
155 | base.Dispose(disposing);
156 |
157 | if (disposing && !_disposed)
158 | {
159 | _drawable?.Dispose();
160 | _disposed = true;
161 | }
162 | }
163 |
164 | protected override void OnDraw(ACanvas canvas)
165 | {
166 | if (Element == null) return;
167 |
168 | var control = (PancakeView)Element;
169 |
170 | SetClipChildren(true);
171 |
172 | //Create path to clip the child
173 | if (control.Sides != 4)
174 | {
175 | using (var path = ShapeUtils.CreatePolygonPath(Width, Height, control.Sides, control.CornerRadius.TopLeft, control.OffsetAngle))
176 | {
177 | canvas.Save();
178 | canvas.ClipPath(path);
179 | }
180 | }
181 | else
182 | {
183 | using (var path = ShapeUtils.CreateRoundedRectPath(Width, Height,
184 | Context.ToPixels(control.CornerRadius.TopLeft),
185 | Context.ToPixels(control.CornerRadius.TopRight),
186 | Context.ToPixels(control.CornerRadius.BottomRight),
187 | Context.ToPixels(control.CornerRadius.BottomLeft)))
188 | {
189 | canvas.Save();
190 | canvas.ClipPath(path);
191 | }
192 | }
193 |
194 | DrawBorder(canvas, control);
195 | }
196 |
197 | protected override bool DrawChild(ACanvas canvas, global::Android.Views.View child, long drawingTime)
198 | {
199 | if (Element == null) return false;
200 |
201 | var control = (PancakeView)Element;
202 |
203 | SetClipChildren(true);
204 |
205 | //Create path to clip the child
206 | if (control.Sides != 4)
207 | {
208 | using (var path = ShapeUtils.CreatePolygonPath(Width, Height, control.Sides, control.CornerRadius.TopLeft, control.OffsetAngle))
209 | {
210 | canvas.Save();
211 | canvas.ClipPath(path);
212 | }
213 | }
214 | else
215 | {
216 | using (var path = ShapeUtils.CreateRoundedRectPath(Width, Height,
217 | Context.ToPixels(control.CornerRadius.TopLeft),
218 | Context.ToPixels(control.CornerRadius.TopRight),
219 | Context.ToPixels(control.CornerRadius.BottomRight),
220 | Context.ToPixels(control.CornerRadius.BottomLeft)))
221 | {
222 | canvas.Save();
223 | canvas.ClipPath(path);
224 | }
225 | }
226 |
227 | // Draw the child first so that the border shows up above it.
228 | var result = base.DrawChild(canvas, child, drawingTime);
229 | canvas.Restore();
230 |
231 | DrawBorder(canvas, control);
232 |
233 | return result;
234 | }
235 |
236 | private void DrawBorder(ACanvas canvas, PancakeView control)
237 | {
238 | if (control.BorderThickness > 0)
239 | {
240 | var borderThickness = Context.ToPixels(control.BorderThickness);
241 | var halfBorderThickness = borderThickness / 2;
242 | bool hasShadowOrElevation = control.HasShadow || (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop && control.Elevation > 0);
243 |
244 | // TODO: This doesn't look entirely right yet when using it with rounded corners.
245 | using (var paint = new Paint { AntiAlias = true })
246 | using (Path.Direction direction = Path.Direction.Cw)
247 | using (Paint.Style style = Paint.Style.Stroke)
248 | using (var rect = new RectF(control.BorderDrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? -halfBorderThickness : halfBorderThickness,
249 | control.BorderDrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? -halfBorderThickness : halfBorderThickness,
250 | control.BorderDrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? canvas.Width + halfBorderThickness : canvas.Width - halfBorderThickness,
251 | control.BorderDrawingStyle == BorderDrawingStyle.Outside && !hasShadowOrElevation ? canvas.Height + halfBorderThickness : canvas.Height - halfBorderThickness))
252 | {
253 | Path path = null;
254 | if (control.Sides != 4)
255 | {
256 | path = ShapeUtils.CreatePolygonPath(Width, Height, control.Sides, control.CornerRadius.TopLeft, control.OffsetAngle);
257 | }
258 | else
259 | {
260 | path = ShapeUtils.CreateRoundedRectPath(Width, Height,
261 | Context.ToPixels(control.CornerRadius.TopLeft),
262 | Context.ToPixels(control.CornerRadius.TopRight),
263 | Context.ToPixels(control.CornerRadius.BottomRight),
264 | Context.ToPixels(control.CornerRadius.BottomLeft));
265 | }
266 |
267 | if (control.BorderIsDashed)
268 | {
269 | // dashes merge when thickness is increased
270 | // off-distance should be scaled according to thickness
271 | paint.SetPathEffect(new DashPathEffect(new float[] { 10, 5 * control.BorderThickness }, 0));
272 | }
273 |
274 | if ((control.BorderGradientStartColor != default(Xamarin.Forms.Color) && control.BorderGradientEndColor != default(Xamarin.Forms.Color)) || (control.BorderGradientStops != null && control.BorderGradientStops.Any()))
275 | {
276 | var angle = control.BorderGradientAngle / 360.0;
277 |
278 | // Calculate the new positions based on angle between 0-360.
279 | var a = canvas.Width * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.75) / 2)), 2);
280 | var b = canvas.Height * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.0) / 2)), 2);
281 | var c = canvas.Width * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.25) / 2)), 2);
282 | var d = canvas.Height * Math.Pow(Math.Sin(2 * Math.PI * ((angle + 0.5) / 2)), 2);
283 |
284 | if (control.BorderGradientStops != null && control.BorderGradientStops.Count > 0)
285 | {
286 | // A range of colors is given. Let's add them.
287 | var orderedStops = control.BorderGradientStops.OrderBy(x => x.Offset).ToList();
288 | var colors = orderedStops.Select(x => x.Color.ToAndroid().ToArgb()).ToArray();
289 | var locations = orderedStops.Select(x => x.Offset).ToArray();
290 |
291 | var shader = new LinearGradient(canvas.Width - (float)a, (float)b, canvas.Width - (float)c, (float)d, colors, locations, Shader.TileMode.Clamp);
292 | paint.SetShader(shader);
293 | }
294 | else
295 | {
296 | // Only two colors provided, use that.
297 | var shader = new LinearGradient(canvas.Width - (float)a, (float)b, canvas.Width - (float)c, (float)d, control.BorderGradientStartColor.ToAndroid(), control.BorderGradientEndColor.ToAndroid(), Shader.TileMode.Clamp);
298 | paint.SetShader(shader);
299 | }
300 | }
301 | else
302 | {
303 | paint.Color = control.BorderColor.ToAndroid();
304 | }
305 |
306 | paint.StrokeCap = Paint.Cap.Square;
307 | paint.StrokeWidth = borderThickness;
308 | paint.SetStyle(style);
309 |
310 | canvas.DrawPath(path, paint);
311 | }
312 | }
313 | }
314 | }
315 | }
316 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/RenderersAndroid/RoundedCornerOutlineProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Android.Graphics;
3 | using Android.Views;
4 | using XamUIDemo.Renderers;
5 | namespace XamUIDemo.Droid.Renderers
6 | {
7 | public class RoundedCornerOutlineProvider : ViewOutlineProvider
8 | {
9 | private readonly PancakeView _pancake;
10 | private readonly Func _convertToPixels;
11 |
12 | public RoundedCornerOutlineProvider(PancakeView pancake, Func convertToPixels)
13 | {
14 | _pancake = pancake;
15 | _convertToPixels = convertToPixels;
16 | }
17 |
18 | public override void GetOutline(global::Android.Views.View view, Outline outline)
19 | {
20 | if (_pancake.Sides != 4)
21 | {
22 | var hexPath = XamUIDemo.Droid.Renderers.ShapeUtils.CreatePolygonPath(view.Width, view.Height, _pancake.Sides, _pancake.HasShadow ? 0 : _pancake.CornerRadius.TopLeft, _pancake.OffsetAngle);
23 |
24 | if (hexPath.IsConvex)
25 | {
26 | outline.SetConvexPath(hexPath);
27 | }
28 | }
29 | else
30 | {
31 | var path = ShapeUtils.CreateRoundedRectPath(view.Width, view.Height,
32 | _convertToPixels(_pancake.CornerRadius.TopLeft),
33 | _convertToPixels(_pancake.CornerRadius.TopRight),
34 | _convertToPixels(_pancake.CornerRadius.BottomRight),
35 | _convertToPixels(_pancake.CornerRadius.BottomLeft));
36 |
37 | if (path.IsConvex)
38 | {
39 | outline.SetConvexPath(path);
40 | }
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/RenderersAndroid/ShapeUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Android.Graphics;
3 | namespace XamUIDemo.Droid.Renderers
4 | {
5 | public static class ShapeUtils
6 | {
7 | public static Path CreateRoundedRectPath(float rectWidth, float rectHeight, float topLeft, float topRight, float bottomRight, float bottomLeft)
8 | {
9 | var path = new Path();
10 | var radii = new[] { topLeft, topLeft,
11 | topRight, topRight,
12 | bottomRight, bottomRight,
13 | bottomLeft, bottomLeft };
14 |
15 |
16 | path.AddRoundRect(new RectF(0, 0, rectWidth, rectHeight), radii, Path.Direction.Ccw);
17 | path.Close();
18 |
19 | return path;
20 | }
21 |
22 | public static Path CreatePolygonPath(double rectWidth, double rectHeight, int sides, double cornerRadius = 0.0, double rotationOffset = 0.0)
23 | {
24 | var offsetRadians = rotationOffset * Math.PI / 180;
25 |
26 | var path = new Path();
27 | var theta = 2 * Math.PI / sides;
28 |
29 | // depends on the rotation
30 | var width = (-cornerRadius + Math.Min(rectWidth, rectHeight)) / 2;
31 | var center = new Point(rectWidth / 2, rectHeight / 2);
32 |
33 | var radius = width + cornerRadius - (Math.Cos(theta) * cornerRadius) / 2;
34 |
35 | var angle = offsetRadians;
36 | var corner = new Point(center.X + (radius - cornerRadius) * Math.Cos(angle), center.Y + (radius - cornerRadius) * Math.Sin(angle));
37 | path.MoveTo((float)(corner.X + cornerRadius * Math.Cos(angle + theta)), (float)(corner.Y + cornerRadius * Math.Sin(angle + theta)));
38 |
39 | for (var i = 0; i < sides; i++)
40 | {
41 | angle += theta;
42 | corner = new Point(center.X + (radius - cornerRadius) * Math.Cos(angle), center.Y + (radius - cornerRadius) * Math.Sin(angle));
43 | var tip = new Point(center.X + radius * Math.Cos(angle), center.Y + radius * Math.Sin(angle));
44 | var start = new Point(corner.X + cornerRadius * Math.Cos(angle - theta), corner.Y + cornerRadius * Math.Sin(angle - theta));
45 | var end = new Point(corner.X + cornerRadius * Math.Cos(angle + theta), corner.Y + cornerRadius * Math.Sin(angle + theta));
46 |
47 | path.LineTo(start.X, start.Y);
48 | path.QuadTo(tip.X, tip.Y, end.X, end.Y);
49 | }
50 |
51 | path.Close();
52 |
53 | return path;
54 | }
55 |
56 | public class Point
57 | {
58 | public float X { get; set; }
59 | public float Y { get; set; }
60 | public Point(double X, double Y)
61 | {
62 | this.X = (float)X;
63 | this.Y = (float)Y;
64 | }
65 | }
66 | }
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/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 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/drawable/bg1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/drawable/bg1.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/drawable/bg9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/drawable/bg9.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/drawable/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/drawable/logo.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/layout/Tabbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/layout/Toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-anydpi-v26/icon.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-anydpi-v26/icon_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-hdpi/icon.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-hdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-hdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-hdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-hdpi/logo.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-mdpi/icon.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-mdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-mdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-mdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-mdpi/logo.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-xhdpi/icon.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-xhdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-xhdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-xhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-xhdpi/logo.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-xxhdpi/icon.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-xxhdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-xxhdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-xxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-xxhdpi/logo.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-xxxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-xxxhdpi/icon.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/mipmap-xxxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.Android/Resources/mipmap-xxxhdpi/logo.png
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 | #3F51B5
5 | #303F9F
6 | #FF4081
7 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
24 |
27 |
--------------------------------------------------------------------------------
/XamUIDemo.Android/XamUIDemo.Android.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}
7 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | {c9e5eea5-ca05-42a1-839b-61506e0a37df}
9 | Library
10 | XamUIDemo.Droid
11 | XamUIDemo.Android
12 | True
13 | Resources\Resource.designer.cs
14 | Resource
15 | Properties\AndroidManifest.xml
16 | Resources
17 | Assets
18 | v9.0
19 | true
20 | true
21 | Xamarin.Android.Net.AndroidClientHandler
22 |
23 |
24 |
25 |
26 | true
27 | portable
28 | false
29 | bin\Debug
30 | DEBUG;
31 | prompt
32 | 4
33 | None
34 |
35 |
36 | true
37 | portable
38 | true
39 | bin\Release
40 | prompt
41 | 4
42 | true
43 | false
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
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 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 | {1A72F333-4921-403E-B8D5-541D49EFBA28}
130 | XamUIDemo
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/XamUIDemo.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 XamUIDemo.iOS
9 | {
10 | // The UIApplicationDelegate for the application. This class is responsible for launching the
11 | // User Interface of the application, as well as listening (and optionally responding) to
12 | // application events from iOS.
13 | [Register("AppDelegate")]
14 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
15 | {
16 | //
17 | // This method is invoked when the application has loaded and is ready to run. In this
18 | // method you should instantiate the window, load the UI into it and then make the window
19 | // visible.
20 | //
21 | // You have 17 seconds to return from this method, or iOS will terminate your application.
22 | //
23 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
24 | {
25 | global::Xamarin.Forms.Forms.Init();
26 | LoadApplication(new App());
27 |
28 | return base.FinishedLaunching(app, options);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "filename": "Icon-40.png",
5 | "size": "20x20",
6 | "scale": "2x",
7 | "idiom": "iphone"
8 | },
9 | {
10 | "filename": "Icon-60.png",
11 | "size": "20x20",
12 | "scale": "3x",
13 | "idiom": "iphone"
14 | },
15 | {
16 | "filename": "Icon-58.png",
17 | "size": "29x29",
18 | "scale": "2x",
19 | "idiom": "iphone"
20 | },
21 | {
22 | "filename": "Icon-87.png",
23 | "size": "29x29",
24 | "scale": "3x",
25 | "idiom": "iphone"
26 | },
27 | {
28 | "filename": "Icon-80.png",
29 | "size": "40x40",
30 | "scale": "2x",
31 | "idiom": "iphone"
32 | },
33 | {
34 | "filename": "Icon-120.png",
35 | "size": "40x40",
36 | "scale": "3x",
37 | "idiom": "iphone"
38 | },
39 | {
40 | "filename": "Icon-120-1.png",
41 | "size": "60x60",
42 | "scale": "2x",
43 | "idiom": "iphone"
44 | },
45 | {
46 | "filename": "Icon-180.png",
47 | "size": "60x60",
48 | "scale": "3x",
49 | "idiom": "iphone"
50 | },
51 | {
52 | "filename": "Icon-20.png",
53 | "size": "20x20",
54 | "scale": "1x",
55 | "idiom": "ipad"
56 | },
57 | {
58 | "filename": "Icon-40-1.png",
59 | "size": "20x20",
60 | "scale": "2x",
61 | "idiom": "ipad"
62 | },
63 | {
64 | "filename": "Icon-29.png",
65 | "size": "29x29",
66 | "scale": "1x",
67 | "idiom": "ipad"
68 | },
69 | {
70 | "filename": "Icon-58-1.png",
71 | "size": "29x29",
72 | "scale": "2x",
73 | "idiom": "ipad"
74 | },
75 | {
76 | "filename": "Icon-40-2.png",
77 | "size": "40x40",
78 | "scale": "1x",
79 | "idiom": "ipad"
80 | },
81 | {
82 | "filename": "Icon-80-1.png",
83 | "size": "40x40",
84 | "scale": "2x",
85 | "idiom": "ipad"
86 | },
87 | {
88 | "filename": "Icon-167.png",
89 | "size": "83.5x83.5",
90 | "scale": "2x",
91 | "idiom": "ipad"
92 | },
93 | {
94 | "filename": "Icon-76.png",
95 | "size": "76x76",
96 | "scale": "1x",
97 | "idiom": "ipad"
98 | },
99 | {
100 | "filename": "Icon-152.png",
101 | "size": "76x76",
102 | "scale": "2x",
103 | "idiom": "ipad"
104 | },
105 | {
106 | "filename": "Icon-1024.png",
107 | "size": "1024x1024",
108 | "scale": "1x",
109 | "idiom": "ios-marketing"
110 | },
111 | {
112 | "size": "60x60",
113 | "scale": "2x",
114 | "idiom": "car"
115 | },
116 | {
117 | "size": "60x60",
118 | "scale": "3x",
119 | "idiom": "car"
120 | },
121 | {
122 | "role": "notificationCenter",
123 | "size": "24x24",
124 | "subtype": "38mm",
125 | "scale": "2x",
126 | "idiom": "watch"
127 | },
128 | {
129 | "role": "notificationCenter",
130 | "size": "27.5x27.5",
131 | "subtype": "42mm",
132 | "scale": "2x",
133 | "idiom": "watch"
134 | },
135 | {
136 | "role": "companionSettings",
137 | "size": "29x29",
138 | "scale": "2x",
139 | "idiom": "watch"
140 | },
141 | {
142 | "role": "companionSettings",
143 | "size": "29x29",
144 | "scale": "3x",
145 | "idiom": "watch"
146 | },
147 | {
148 | "role": "appLauncher",
149 | "size": "40x40",
150 | "subtype": "38mm",
151 | "scale": "2x",
152 | "idiom": "watch"
153 | },
154 | {
155 | "role": "appLauncher",
156 | "size": "44x44",
157 | "subtype": "40mm",
158 | "scale": "2x",
159 | "idiom": "watch"
160 | },
161 | {
162 | "role": "appLauncher",
163 | "size": "50x50",
164 | "subtype": "44mm",
165 | "scale": "2x",
166 | "idiom": "watch"
167 | },
168 | {
169 | "role": "quickLook",
170 | "size": "86x86",
171 | "subtype": "38mm",
172 | "scale": "2x",
173 | "idiom": "watch"
174 | },
175 | {
176 | "role": "quickLook",
177 | "size": "98x98",
178 | "subtype": "42mm",
179 | "scale": "2x",
180 | "idiom": "watch"
181 | },
182 | {
183 | "role": "quickLook",
184 | "size": "108x108",
185 | "subtype": "44mm",
186 | "scale": "2x",
187 | "idiom": "watch"
188 | },
189 | {
190 | "size": "1024x1024",
191 | "scale": "1x",
192 | "idiom": "watch-marketing"
193 | },
194 | {
195 | "size": "16x16",
196 | "scale": "1x",
197 | "idiom": "mac"
198 | },
199 | {
200 | "size": "16x16",
201 | "scale": "2x",
202 | "idiom": "mac"
203 | },
204 | {
205 | "size": "32x32",
206 | "scale": "1x",
207 | "idiom": "mac"
208 | },
209 | {
210 | "size": "32x32",
211 | "scale": "2x",
212 | "idiom": "mac"
213 | },
214 | {
215 | "size": "128x128",
216 | "scale": "1x",
217 | "idiom": "mac"
218 | },
219 | {
220 | "size": "128x128",
221 | "scale": "2x",
222 | "idiom": "mac"
223 | },
224 | {
225 | "size": "256x256",
226 | "scale": "1x",
227 | "idiom": "mac"
228 | },
229 | {
230 | "size": "256x256",
231 | "scale": "2x",
232 | "idiom": "mac"
233 | },
234 | {
235 | "size": "512x512",
236 | "scale": "1x",
237 | "idiom": "mac"
238 | },
239 | {
240 | "size": "512x512",
241 | "scale": "2x",
242 | "idiom": "mac"
243 | }
244 | ],
245 | "info": {
246 | "version": 1,
247 | "author": "xcode"
248 | }
249 | }
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-1024.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-120-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-120-1.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-120.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-152.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-167.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-180.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-20.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-29.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-40-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-40-1.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-40-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-40-2.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-40.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-58-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-58-1.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-58.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-60.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-76.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-80-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-80-1.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-80.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Assets.xcassets/AppIcon.appiconset/Icon-87.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/XamUIDemo.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 | 8.0
25 | CFBundleDisplayName
26 | XamUIDemo
27 | CFBundleIdentifier
28 | com.XamDesign.XamUIDemo
29 | CFBundleVersion
30 | 1.0
31 | UILaunchStoryboardName
32 | LaunchScreen
33 | CFBundleName
34 | XamUIDemo
35 | XSAppIconAssets
36 | Assets.xcassets/AppIcon.appiconset
37 |
38 |
39 |
--------------------------------------------------------------------------------
/XamUIDemo.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 XamUIDemo.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 |
--------------------------------------------------------------------------------
/XamUIDemo.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("XamUIDemo.iOS")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("XamUIDemo.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 |
--------------------------------------------------------------------------------
/XamUIDemo.iOS/RenderersiOS/BorderlessEntryRenderer.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using UIKit;
3 | using Xamarin.Forms;
4 | using Xamarin.Forms.Platform.iOS;
5 | using XamUIDemo.iOS.RenderersiOS;
6 | using XamUIDemo.Renderers;
7 |
8 | [assembly: ExportRenderer(typeof(BorderlessEntry), typeof(BorderlessBorderlessEntryRenderer))]
9 |
10 | namespace XamUIDemo.iOS.RenderersiOS
11 | {
12 | public class BorderlessBorderlessEntryRenderer : EntryRenderer
13 | {
14 | protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
15 | {
16 | base.OnElementPropertyChanged(sender, e);
17 | if (Control == null) return;
18 | Control.Layer.BorderWidth = 0;
19 | Control.BorderStyle = UITextBorderStyle.None;
20 |
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/XamUIDemo.iOS/RenderersiOS/PancakeViewRenderer.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Linq;
6 | using CoreAnimation;
7 | using CoreGraphics;
8 | using XamUIDemo.iOS.Rednerers;
9 |
10 | using Foundation;
11 | using UIKit;
12 | using Xamarin.Forms;
13 | using Xamarin.Forms.Platform.iOS;
14 | using XamUIDemo.Renderers;
15 |
16 | [assembly: ExportRenderer(typeof(PancakeView), typeof(PancakeViewRenderer))]
17 |
18 | namespace XamUIDemo.iOS.Rednerers
19 | {
20 | public class PancakeViewRenderer : ViewRenderer
21 | {
22 | private UIView _actualView;
23 | private UIView _wrapperView;
24 |
25 | private UIColor _colorToRender;
26 | private CGSize _previousSize;
27 | private nfloat _topLeft;
28 | private nfloat _topRight;
29 | private nfloat _bottomLeft;
30 | private nfloat _bottomRight;
31 |
32 | ///
33 | /// This method ensures that we don't get stripped out by the linker.
34 | ///
35 | public static new void Init()
36 | {
37 | #pragma warning disable 0219
38 | var ignore1 = typeof(PancakeViewRenderer);
39 | var ignore2 = typeof(PancakeView);
40 | #pragma warning restore 0219
41 | }
42 |
43 | protected override void OnElementChanged(ElementChangedEventArgs e)
44 | {
45 | base.OnElementChanged(e);
46 |
47 | if (e.NewElement != null)
48 | {
49 | Validate(Element as PancakeView);
50 |
51 | _actualView = new UIView();
52 | _wrapperView = new UIView();
53 |
54 |
55 |
56 | foreach (var item in NativeView.Subviews)
57 | {
58 | _actualView.AddSubview(item);
59 | }
60 |
61 | if (NativeView.GestureRecognizers != null)
62 | {
63 | foreach (var gesture in NativeView.GestureRecognizers)
64 | {
65 | _actualView.AddGestureRecognizer(gesture);
66 | }
67 | }
68 |
69 | if (Element.Handle == IntPtr.Zero)
70 | {
71 |
72 | Element.Handle = _actualView.Handle;
73 |
74 | _wrapperView.AddSubview(_actualView);
75 |
76 | SetNativeControl(_wrapperView);
77 |
78 | SetBackgroundColor(Element.BackgroundColor);
79 | SetCornerRadius();
80 | }
81 | }
82 | }
83 |
84 | protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
85 | {
86 | base.OnElementPropertyChanged(sender, e);
87 |
88 | Validate(Element as PancakeView);
89 |
90 | if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
91 | {
92 | SetBackgroundColor(Element.BackgroundColor);
93 | }
94 | else if (e.PropertyName == BoxView.CornerRadiusProperty.PropertyName)
95 | {
96 | SetCornerRadius();
97 | }
98 | else if ((e.PropertyName == PancakeView.BorderColorProperty.PropertyName) ||
99 | (e.PropertyName == PancakeView.BorderDrawingStyleProperty.PropertyName) ||
100 | (e.PropertyName == PancakeView.BorderGradientAngleProperty.PropertyName) ||
101 | (e.PropertyName == PancakeView.BorderGradientEndColorProperty.PropertyName) ||
102 | (e.PropertyName == PancakeView.BorderGradientStartColorProperty.PropertyName) ||
103 | (e.PropertyName == PancakeView.BorderGradientStopsProperty.PropertyName) ||
104 | (e.PropertyName == PancakeView.BorderIsDashedProperty.PropertyName) ||
105 | (e.PropertyName == PancakeView.BorderThicknessProperty.PropertyName))
106 | {
107 | DrawBorder();
108 | }
109 | else if ((e.PropertyName == PancakeView.BackgroundGradientStartColorProperty.PropertyName) ||
110 | (e.PropertyName == PancakeView.BackgroundGradientEndColorProperty.PropertyName) ||
111 | (e.PropertyName == PancakeView.BackgroundGradientAngleProperty.PropertyName) ||
112 | (e.PropertyName == PancakeView.BackgroundGradientStopsProperty.PropertyName) ||
113 | (e.PropertyName == VisualElement.IsVisibleProperty.PropertyName && Element.IsVisible) ||
114 | (e.PropertyName == PancakeView.OffsetAngleProperty.PropertyName) ||
115 | (e.PropertyName == PancakeView.HasShadowProperty.PropertyName) ||
116 | (e.PropertyName == PancakeView.ElevationProperty.PropertyName) ||
117 | (e.PropertyName == PancakeView.SidesProperty.PropertyName))
118 | {
119 | SetNeedsDisplay();
120 | }
121 | }
122 |
123 | private void Validate(PancakeView pancake)
124 | {
125 | // Angle needs to be between 0-360.
126 | if (pancake.BackgroundGradientAngle < 0 || pancake.BackgroundGradientAngle > 360)
127 | throw new ArgumentException("Please provide a valid background gradient angle.", nameof(PancakeView.BackgroundGradientAngle));
128 |
129 | if (pancake.OffsetAngle < 0 || pancake.OffsetAngle > 360)
130 | throw new ArgumentException("Please provide a valid offset angle.", nameof(PancakeView.OffsetAngle));
131 |
132 | // min value for sides is 3
133 | if (pancake.Sides < 3)
134 | throw new ArgumentException("Please provide a valid value for sides.", nameof(PancakeView.Sides));
135 | }
136 |
137 | public override void LayoutSubviews()
138 | {
139 | if (_previousSize != Bounds.Size)
140 | SetNeedsDisplay();
141 |
142 | base.LayoutSubviews();
143 | }
144 |
145 | public override void Draw(CGRect rect)
146 | {
147 | _actualView.Frame = Bounds;
148 | _wrapperView.Frame = Bounds;
149 |
150 | DrawBackground();
151 | DrawShadow();
152 | DrawBorder();
153 |
154 | base.Draw(rect);
155 |
156 | _previousSize = Bounds.Size;
157 | }
158 |
159 | private void SetCornerRadius()
160 | {
161 | if (Element == null)
162 | return;
163 |
164 | var elementCornerRadius = (Element as PancakeView).CornerRadius;
165 |
166 | _topLeft = (float)elementCornerRadius.TopLeft;
167 | _topRight = (float)elementCornerRadius.TopRight;
168 | _bottomLeft = (float)elementCornerRadius.BottomLeft;
169 | _bottomRight = (float)elementCornerRadius.BottomRight;
170 |
171 | SetNeedsDisplay();
172 | }
173 |
174 | protected override void SetBackgroundColor(Xamarin.Forms.Color color)
175 | {
176 | if (Element == null)
177 | return;
178 |
179 | var elementColor = Element.BackgroundColor;
180 |
181 | if (!elementColor.IsDefault)
182 | _colorToRender = elementColor.ToUIColor();
183 | else
184 | _colorToRender = color.ToUIColor();
185 |
186 | SetNeedsDisplay();
187 | }
188 |
189 | private void DrawBackground()
190 | {
191 | var pancake = Element as PancakeView;
192 | var layerName = "backgroundLayer";
193 |
194 | // Remove previous background layer if any
195 | var prevBackgroundLayer = _actualView.Layer.Sublayers?.FirstOrDefault(x => x.Name == layerName);
196 | prevBackgroundLayer?.RemoveFromSuperLayer();
197 |
198 | UIBezierPath cornerPath = null;
199 |
200 | if (pancake.Sides != 4)
201 | {
202 | cornerPath = ShapeUtils.CreatePolygonPath(Bounds, pancake.Sides, pancake.CornerRadius.TopLeft, pancake.OffsetAngle);
203 | }
204 | else
205 | {
206 | cornerPath = ShapeUtils.CreateRoundedRectPath(Bounds, pancake.CornerRadius);
207 | }
208 |
209 | // The layer used to mask other layers we draw on the background.
210 | var maskLayer = new CAShapeLayer
211 | {
212 | Frame = Bounds,
213 | Path = cornerPath.CGPath
214 | };
215 |
216 | _actualView.Layer.Mask = maskLayer;
217 | _actualView.Layer.MasksToBounds = true;
218 |
219 | if ((pancake.BackgroundGradientStartColor != default(Xamarin.Forms.Color) && pancake.BackgroundGradientEndColor != default(Xamarin.Forms.Color)) || (pancake.BackgroundGradientStops != null && pancake.BackgroundGradientStops.Any()))
220 | {
221 | // Create a gradient layer that draws our background.
222 | var gradientLayer = CreateGradientLayer(pancake.BackgroundGradientAngle, Bounds);
223 | gradientLayer.Name = layerName;
224 |
225 | if (pancake.BackgroundGradientStops != null && pancake.BackgroundGradientStops.Count > 0)
226 | {
227 | // A range of colors is given. Let's add them.
228 | var orderedStops = pancake.BackgroundGradientStops.OrderBy(x => x.Offset).ToList();
229 | gradientLayer.Colors = orderedStops.Select(x => x.Color.ToCGColor()).ToArray();
230 | gradientLayer.Locations = orderedStops.Select(x => new NSNumber(x.Offset)).ToArray();
231 | }
232 | else
233 | {
234 | // Only two colors provided, use that.
235 | gradientLayer.Colors = new CGColor[] { pancake.BackgroundGradientStartColor.ToCGColor(), pancake.BackgroundGradientEndColor.ToCGColor() };
236 | }
237 |
238 | AddLayer(gradientLayer, 0, _actualView);
239 | }
240 | else
241 | {
242 | // Create a shape layer that draws our background.
243 | var shapeLayer = new CAShapeLayer
244 | {
245 | Frame = Bounds,
246 | Path = cornerPath.CGPath,
247 | MasksToBounds = true,
248 | FillColor = _colorToRender.CGColor,
249 | Name = layerName
250 | };
251 |
252 | AddLayer(shapeLayer, 0, _actualView);
253 | }
254 | }
255 |
256 | private void DrawBorder()
257 | {
258 | var pancake = Element as PancakeView;
259 | var layerName = "borderLayer";
260 |
261 | // remove previous background layer if any
262 | var prevBorderLayer = _wrapperView.Layer.Sublayers?.FirstOrDefault(x => x.Name == layerName);
263 | prevBorderLayer?.RemoveFromSuperLayer();
264 |
265 | if (pancake.BorderThickness > 0)
266 | {
267 | var borderLayer = new CAShapeLayer
268 | {
269 | StrokeColor = pancake.BorderColor == Xamarin.Forms.Color.Default ? UIColor.Clear.CGColor : pancake.BorderColor.ToCGColor(),
270 | FillColor = null,
271 | LineWidth = pancake.BorderThickness,
272 | Name = layerName
273 | };
274 |
275 | // Create arcs for the given corner radius.
276 | bool hasShadowOrElevation = pancake.HasShadow || pancake.Elevation > 0;
277 |
278 | borderLayer.Path = pancake.Sides != 4 ?
279 | ShapeUtils.CreatePolygonPath(Bounds, pancake.Sides, pancake.CornerRadius.TopLeft, pancake.OffsetAngle).CGPath :
280 | ShapeUtils.CreateRoundedRectPath(Bounds, pancake.CornerRadius).CGPath; // insetBounds?
281 |
282 | var layerPosition = new CGPoint(borderLayer.Path.BoundingBox.Width / 2, borderLayer.Path.BoundingBox.Height / 2);
283 |
284 | borderLayer.Frame = borderLayer.Path.BoundingBox;
285 | borderLayer.Position = layerPosition;
286 |
287 | // Dash pattern for the border.
288 | if (pancake.BorderIsDashed)
289 | {
290 | borderLayer.LineDashPattern = new NSNumber[] { new NSNumber(6), new NSNumber(3) };
291 | }
292 |
293 | if ((pancake.BorderGradientStartColor != default(Xamarin.Forms.Color) && pancake.BorderGradientEndColor != default(Xamarin.Forms.Color)) || (pancake.BorderGradientStops != null && pancake.BorderGradientStops.Any()))
294 | {
295 | var gradientFrame = Bounds.Inset(-pancake.BorderThickness, -pancake.BorderThickness);
296 | var gradientLayer = CreateGradientLayer(pancake.BorderGradientAngle, gradientFrame);
297 | gradientLayer.Position = new CGPoint((gradientFrame.Width / 2) - (pancake.BorderThickness), (gradientFrame.Height / 2) - (pancake.BorderThickness));
298 |
299 | // Create a clone from the border layer and use that one as the mask.
300 | // Why? Because the mask and the border somehow can't be the same, so
301 | // don't want to do adjustments to borderLayer because it would influence the border.
302 | var maskLayer = new CAShapeLayer()
303 | {
304 | Path = borderLayer.Path,
305 | Position = new CGPoint(pancake.BorderThickness, pancake.BorderThickness),
306 | FillColor = null,
307 | LineWidth = pancake.BorderThickness,
308 | StrokeColor = UIColor.Red.CGColor,
309 | LineDashPattern = borderLayer.LineDashPattern
310 | };
311 |
312 | gradientLayer.Mask = maskLayer;
313 | gradientLayer.Name = layerName;
314 |
315 | if (pancake.BorderGradientStops != null && pancake.BorderGradientStops.Count > 0)
316 | {
317 | // A range of colors is given. Let's add them.
318 | var orderedStops = pancake.BorderGradientStops.OrderBy(x => x.Offset).ToList();
319 | gradientLayer.Colors = orderedStops.Select(x => x.Color.ToCGColor()).ToArray();
320 | gradientLayer.Locations = orderedStops.Select(x => new NSNumber(x.Offset)).ToArray();
321 | }
322 | else
323 | {
324 | // Only two colors provided, use that.
325 | gradientLayer.Colors = new CGColor[] { pancake.BorderGradientStartColor.ToCGColor(), pancake.BorderGradientEndColor.ToCGColor() };
326 | }
327 |
328 | AddLayer(gradientLayer, -1, _wrapperView);
329 | }
330 | else
331 | {
332 | AddLayer(borderLayer, -1, _wrapperView);
333 | }
334 | }
335 | }
336 |
337 | private void DrawShadow()
338 | {
339 | var pancake = Element;
340 |
341 | bool hasShadowOrElevation = pancake.HasShadow || pancake.Elevation > 0;
342 | nfloat cornerRadius = (nfloat)pancake.CornerRadius.TopLeft;
343 |
344 | if (pancake.HasShadow)
345 | {
346 | DrawDefaultShadow(_wrapperView.Layer, Bounds, cornerRadius);
347 | }
348 |
349 | if (pancake.Elevation > 0)
350 | {
351 | DrawElevation(_wrapperView.Layer, pancake.Elevation, Bounds, cornerRadius);
352 | }
353 |
354 | if (hasShadowOrElevation)
355 | {
356 | // _actualView.Layer.CornerRadius = (nfloat)pancake.CornerRadius.TopLeft;
357 | _actualView.ClipsToBounds = true;
358 | }
359 | else
360 | {
361 | _wrapperView.Layer.ShadowOpacity = 0;
362 | }
363 |
364 | // Set the rasterization for performance optimization.
365 | _wrapperView.Layer.RasterizationScale = UIScreen.MainScreen.Scale;
366 | _wrapperView.Layer.ShouldRasterize = true;
367 |
368 | _actualView.Layer.RasterizationScale = UIScreen.MainScreen.Scale;
369 | _actualView.Layer.ShouldRasterize = true;
370 | }
371 |
372 | private void DrawDefaultShadow(CALayer layer, CGRect bounds, nfloat cornerRadius)
373 | {
374 | var pancake = Element as PancakeView;
375 |
376 | // Ideally we want to be able to have individual corner radii + shadows
377 | // However, on iOS we can only do one radius + shadow.
378 | layer.CornerRadius = cornerRadius;
379 | layer.ShadowRadius = 10;
380 | layer.ShadowColor = UIColor.Black.CGColor;
381 | layer.ShadowOpacity = 0.4f;
382 | layer.ShadowOffset = new SizeF();
383 |
384 | if (pancake.Sides != 4)
385 | {
386 | layer.ShadowPath = ShapeUtils.CreatePolygonPath(bounds, pancake.Sides, pancake.CornerRadius.TopLeft, pancake.OffsetAngle).CGPath;
387 | }
388 | else
389 | {
390 | layer.ShadowPath = ShapeUtils.CreateRoundedRectPath(bounds, pancake.CornerRadius).CGPath;
391 | }
392 | }
393 |
394 | private void DrawElevation(CALayer layer, int elevation, CGRect bounds, nfloat cornerRadius)
395 | {
396 | // Source: https://medium.com/material-design-for-ios/part-1-elevation-e48ff795c693
397 | var pancake = Element as PancakeView;
398 |
399 | layer.CornerRadius = cornerRadius;
400 | layer.ShadowRadius = elevation;
401 | layer.ShadowColor = UIColor.Black.CGColor;
402 | layer.ShadowOpacity = 0.24f;
403 | layer.ShadowOffset = new CGSize(0, elevation);
404 |
405 | if (pancake.Sides != 4)
406 | {
407 | layer.ShadowPath = ShapeUtils.CreatePolygonPath(bounds, pancake.Sides, pancake.CornerRadius.TopLeft, pancake.OffsetAngle).CGPath;
408 | }
409 | else
410 | {
411 | layer.ShadowPath = ShapeUtils.CreateRoundedRectPath(bounds, pancake.CornerRadius).CGPath;
412 | }
413 |
414 | layer.MasksToBounds = false;
415 | }
416 |
417 | private CAGradientLayer CreateGradientLayer(int angle, CGRect rect)
418 | {
419 | var totalAngle = angle / 360.0;
420 |
421 | // Calculate the new positions based on angle between 0-360.
422 | var a = Math.Pow(Math.Sin(2 * Math.PI * ((totalAngle + 0.75) / 2)), 2);
423 | var b = Math.Pow(Math.Sin(2 * Math.PI * ((totalAngle + 0.0) / 2)), 2);
424 | var c = Math.Pow(Math.Sin(2 * Math.PI * ((totalAngle + 0.25) / 2)), 2);
425 | var d = Math.Pow(Math.Sin(2 * Math.PI * ((totalAngle + 0.5) / 2)), 2);
426 |
427 | // Create a gradient layer that draws our background.
428 | return new CAGradientLayer
429 | {
430 | Frame = rect,
431 | StartPoint = new CGPoint(1 - a, b),
432 | EndPoint = new CGPoint(1 - c, d)
433 | };
434 | }
435 |
436 | public void AddLayer(CALayer layer, int position, UIView viewToAddTo)
437 | {
438 | // If there is already a layer with the given name, remove it before inserting.
439 | if (layer != null)
440 | {
441 | // There's no background layer yet, insert it.
442 | if (position > -1)
443 | viewToAddTo.Layer.InsertSublayer(layer, position);
444 | else
445 | viewToAddTo.Layer.AddSublayer(layer);
446 | }
447 | }
448 | }
449 | }
450 |
--------------------------------------------------------------------------------
/XamUIDemo.iOS/RenderersiOS/ShapeUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using CoreGraphics;
3 | using UIKit;
4 | using Xamarin.Forms;
5 |
6 | namespace XamUIDemo.iOS.Rednerers
7 | {
8 | public static class ShapeUtils
9 | {
10 | public static UIBezierPath CreateRoundedRectPath(CGRect rect, CornerRadius cornerRadius)
11 | {
12 | var path = new UIBezierPath();
13 |
14 | path.MoveTo(new CGPoint(rect.Width - cornerRadius.TopRight, rect.Y));
15 | path.AddArc(new CGPoint((float)rect.X + rect.Width - cornerRadius.TopRight, (float)rect.Y + cornerRadius.TopRight), (nfloat)cornerRadius.TopRight, (float)(Math.PI * 1.5), (float)Math.PI * 2, true);
16 | path.AddLineTo(new CGPoint(rect.Width, rect.Height - cornerRadius.BottomRight));
17 | path.AddArc(new CGPoint((float)rect.X + rect.Width - cornerRadius.BottomRight, (float)rect.Y + rect.Height - cornerRadius.BottomRight), (nfloat)cornerRadius.BottomRight, 0, (float)(Math.PI * .5), true);
18 | path.AddLineTo(new CGPoint(cornerRadius.BottomLeft, rect.Height));
19 | path.AddArc(new CGPoint((float)rect.X + cornerRadius.BottomLeft, (float)rect.Y + rect.Height - cornerRadius.BottomLeft), (nfloat)cornerRadius.BottomLeft, (float)(Math.PI * .5), (float)Math.PI, true);
20 | path.AddLineTo(new CGPoint(rect.X, cornerRadius.TopLeft));
21 | path.AddArc(new CGPoint((float)rect.X + cornerRadius.TopLeft, (float)rect.Y + cornerRadius.TopLeft), (nfloat)cornerRadius.TopLeft, (float)Math.PI, (float)(Math.PI * 1.5), true);
22 |
23 | path.ClosePath();
24 |
25 | return path;
26 | }
27 |
28 | public static UIBezierPath CreatePolygonPath(CGRect rect, int sides, double cornerRadius = 0.0, double rotationOffset = 0.0)
29 | {
30 | var offsetRadians = rotationOffset * Math.PI / 180;
31 | var path = new UIBezierPath();
32 | var theta = 2 * Math.PI / sides;
33 |
34 | var width = (-cornerRadius + Math.Min(rect.Size.Width, rect.Size.Height)) / 2;
35 | var center = new CGPoint(rect.Width / 2, rect.Height / 2);
36 |
37 | var radius = width + cornerRadius - (Math.Cos(theta) * cornerRadius) / 2;
38 |
39 | var angle = offsetRadians;
40 | var corner = new CGPoint(center.X + (radius - cornerRadius) * Math.Cos(angle), center.Y + (radius - cornerRadius) * Math.Sin(angle));
41 | path.MoveTo(new CGPoint(corner.X + cornerRadius * Math.Cos(angle + theta), corner.Y + cornerRadius * Math.Sin(angle + theta)));
42 |
43 | for (var i = 0; i < sides; i++)
44 | {
45 | angle += theta;
46 | corner = new CGPoint(center.X + (radius - cornerRadius) * Math.Cos(angle), center.Y + (radius - cornerRadius) * Math.Sin(angle));
47 | var tip = new CGPoint(center.X + radius * Math.Cos(angle), center.Y + radius * Math.Sin(angle));
48 | var start = new CGPoint(corner.X + cornerRadius * Math.Cos(angle - theta), corner.Y + cornerRadius * Math.Sin(angle - theta));
49 | var end = new CGPoint(corner.X + cornerRadius * Math.Cos(angle + theta), corner.Y + cornerRadius * Math.Sin(angle + theta));
50 |
51 | path.AddLineTo(start);
52 | path.AddQuadCurveToPoint(end, tip);
53 | }
54 |
55 | path.ClosePath();
56 |
57 | return path;
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Resources/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Resources/Default-568h@2x.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Resources/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Resources/Default-Portrait.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Resources/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Resources/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Resources/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Resources/Default.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Resources/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Resources/Default@2x.png
--------------------------------------------------------------------------------
/XamUIDemo.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 |
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Resources/bg1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Resources/bg1.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Resources/bg9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Resources/bg9.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/Resources/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ufukhawk/XamUIDemo/7ba39dc3f98975207bb9fe7ced3a399fe0318bf4/XamUIDemo.iOS/Resources/logo.png
--------------------------------------------------------------------------------
/XamUIDemo.iOS/XamUIDemo.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | iPhoneSimulator
6 | 8.0.30703
7 | 2.0
8 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}
9 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10 | {6143fdea-f3c2-4a09-aafa-6e230626515e}
11 | Exe
12 | XamUIDemo.iOS
13 | Resources
14 | XamUIDemo.iOS
15 | true
16 | NSUrlSessionHandler
17 |
18 |
19 | true
20 | full
21 | false
22 | bin\iPhoneSimulator\Debug
23 | DEBUG
24 | prompt
25 | 4
26 | x86_64
27 | None
28 | true
29 |
30 |
31 | none
32 | true
33 | bin\iPhoneSimulator\Release
34 | prompt
35 | 4
36 | None
37 | x86_64
38 |
39 |
40 | true
41 | full
42 | false
43 | bin\iPhone\Debug
44 | DEBUG
45 | prompt
46 | 4
47 | ARM64
48 | iPhone Developer
49 | true
50 | Entitlements.plist
51 |
52 |
53 | none
54 | true
55 | bin\iPhone\Release
56 | prompt
57 | 4
58 | ARM64
59 | iPhone Developer
60 | Entitlements.plist
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | {1A72F333-4921-403E-B8D5-541D49EFBA28}
91 | XamUIDemo
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/XamUIDemo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamUIDemo.Android", "XamUIDemo.Android\XamUIDemo.Android.csproj", "{B085165E-2B8E-4CA4-865A-74CC0C38622C}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamUIDemo.iOS", "XamUIDemo.iOS\XamUIDemo.iOS.csproj", "{8ECEB38A-BC93-4099-B689-25A66EEF2F7B}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamUIDemo", "XamUIDemo\XamUIDemo.csproj", "{1A72F333-4921-403E-B8D5-541D49EFBA28}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
15 | Release|iPhoneSimulator = Release|iPhoneSimulator
16 | Debug|iPhone = Debug|iPhone
17 | Release|iPhone = Release|iPhone
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
25 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
26 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
27 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
28 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
29 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Debug|iPhone.Build.0 = Debug|Any CPU
30 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Release|iPhone.ActiveCfg = Release|Any CPU
31 | {B085165E-2B8E-4CA4-865A-74CC0C38622C}.Release|iPhone.Build.0 = Release|Any CPU
32 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
33 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
34 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
35 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
36 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
37 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
38 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
39 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
40 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Debug|iPhone.ActiveCfg = Debug|iPhone
41 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Debug|iPhone.Build.0 = Debug|iPhone
42 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Release|iPhone.ActiveCfg = Release|iPhone
43 | {8ECEB38A-BC93-4099-B689-25A66EEF2F7B}.Release|iPhone.Build.0 = Release|iPhone
44 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
49 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
50 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
51 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
52 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Debug|iPhone.ActiveCfg = Debug|Any CPU
53 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Debug|iPhone.Build.0 = Debug|Any CPU
54 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Release|iPhone.ActiveCfg = Release|Any CPU
55 | {1A72F333-4921-403E-B8D5-541D49EFBA28}.Release|iPhone.Build.0 = Release|Any CPU
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------
/XamUIDemo/Animations/ViewAnimations.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Xamarin.Forms;
4 |
5 | namespace XamUIDemo.Animations
6 | {
7 | public static class ViewAnimations
8 | {
9 | public static async Task FadeAnimY(View view)
10 | {
11 |
12 |
13 | await Task.WhenAll
14 | (
15 | view.FadeTo(1, 200),
16 | view.TranslateTo(0, 0, 200)
17 | );
18 | }
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/XamUIDemo/App.xaml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/XamUIDemo/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 | using Xamarin.Forms.Xaml;
4 |
5 | namespace XamUIDemo
6 | {
7 | public partial class App : Application
8 | {
9 | public App()
10 | {
11 | InitializeComponent();
12 |
13 | MainPage = new NavigationPage(new MainPage());
14 | }
15 |
16 | protected override void OnStart()
17 | {
18 | // Handle when your app starts
19 | }
20 |
21 | protected override void OnSleep()
22 | {
23 | // Handle when your app sleeps
24 | }
25 |
26 | protected override void OnResume()
27 | {
28 | // Handle when your app resumes
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/XamUIDemo/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms.Xaml;
2 |
3 | [assembly: XamlCompilation(XamlCompilationOptions.Compile)]
--------------------------------------------------------------------------------
/XamUIDemo/LoginPages/LoginPage10.xaml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
28 |
34 |
38 |
49 |
50 |
61 |
74 |
75 |
76 |
81 |
82 |
83 |
84 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/XamUIDemo/LoginPages/LoginPage10.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using Xamarin.Forms;
5 | using XamUIDemo.Animations;
6 |
7 | namespace XamUIDemo.LoginPages
8 | {
9 | public partial class LoginPage10 : ContentPage
10 | {
11 | public LoginPage10()
12 | {
13 | InitializeComponent();
14 |
15 | }
16 | protected override void OnAppearing()
17 | {
18 | base.OnAppearing();
19 | Task.Run(async () =>
20 | {
21 | await ViewAnimations.FadeAnimY(Logo);
22 | await ViewAnimations.FadeAnimY(FaceButton);
23 | await ViewAnimations.FadeAnimY(LoginButton);
24 | await ViewAnimations.FadeAnimY(SignupButton);
25 | });
26 | }
27 | protected void Back(object s, EventArgs e)
28 | {
29 | Navigation.PopAsync();
30 | }
31 | protected void Login(object s, EventArgs e)
32 | {
33 | Navigation.PushAsync(new LoginPage14());
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/XamUIDemo/LoginPages/LoginPage14.xaml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
21 |
26 |
36 |
41 |
42 |
52 |
58 |
59 |
60 |
67 |
68 |
69 |
70 |
71 |
89 |
90 |
91 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/XamUIDemo/LoginPages/LoginPage14.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using Xamarin.Forms;
5 | using XamUIDemo.Animations;
6 |
7 | namespace XamUIDemo.LoginPages
8 | {
9 | public partial class LoginPage14 : ContentPage
10 | {
11 | public LoginPage14()
12 | {
13 | InitializeComponent();
14 |
15 | }
16 | protected override void OnAppearing()
17 | {
18 | base.OnAppearing();
19 | Task.Run(async () =>
20 | {
21 | await ViewAnimations.FadeAnimY(Logo);
22 | await ViewAnimations.FadeAnimY(EmailPancake);
23 | await ViewAnimations.FadeAnimY(PassPancake);
24 | await ViewAnimations.FadeAnimY(LoginButton);
25 |
26 | });
27 | }
28 | protected void Back(object s, EventArgs e)
29 | {
30 | Navigation.PopAsync();
31 | }
32 | protected void Login(object s, EventArgs e)
33 | {
34 | Navigation.PopToRootAsync();
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/XamUIDemo/LoginPages/LoginPage2.xaml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
22 |
32 |
40 |
45 |
51 |
55 |
56 |
62 |
67 |
68 |
77 |
78 |
79 |
80 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/XamUIDemo/LoginPages/LoginPage2.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Xamarin.Forms;
4 | using XamUIDemo.Animations;
5 |
6 | namespace XamUIDemo.LoginPages
7 | {
8 | public partial class LoginPage2 : ContentPage
9 | {
10 | public LoginPage2()
11 | {
12 | InitializeComponent();
13 | }
14 | protected override void OnAppearing()
15 | {
16 | base.OnAppearing();
17 | Task.Run(async () =>
18 | {
19 | await ViewAnimations.FadeAnimY(Logo);
20 | await ViewAnimations.FadeAnimY(MainStack);
21 |
22 | });
23 | }
24 | protected void Back(object s, EventArgs e)
25 | {
26 | Navigation.PopAsync();
27 | }
28 | protected void Login(object s, EventArgs e)
29 | {
30 | Navigation.PushAsync(new LoginPage10());
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/XamUIDemo/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
17 |
23 |
28 |
29 |
35 |
43 |
44 |
45 |
46 |
51 |
52 |
59 |
60 |
61 |
62 |
67 |
68 |
75 |
76 |
77 |
78 |
83 |
84 |
85 |
89 |
96 |
97 |
98 |
99 |
105 |
106 |
107 |
108 |
115 |
116 |
117 |
118 |
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/XamUIDemo/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Xamarin.Forms;
8 |
9 | namespace XamUIDemo
10 | {
11 | // Learn more about making custom code visible in the Xamarin.Forms previewer
12 | // by visiting https://aka.ms/xamarinforms-previewer
13 | [DesignTimeVisible(false)]
14 | public partial class MainPage : ContentPage
15 | {
16 | public MainPage()
17 | {
18 | InitializeComponent();
19 | }
20 | protected void ClickLoginPage(object sender, EventArgs e)
21 | {
22 | Navigation.PushAsync(new LoginPages.LoginPage2());
23 | }
24 | protected void ClickDellyShop(object sender, EventArgs e)
25 | {
26 | Device.OpenUri(new Uri("https://codecanyon.net/item/dellyshop-ecommerce-application-template-xamarin-forms-androidios/25307064"));
27 | }
28 | protected void ClickXFShop(object sender, EventArgs e)
29 | {
30 | Device.OpenUri(new Uri("https://codecanyon.net/item/xfshop-ecommerce-application-template-cross-platformandroidios/24853588"));
31 |
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/XamUIDemo/Renderers/BlurredImage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 |
4 | namespace XamUIDemo.Renderers
5 | {
6 | public class BlurredImage : Image
7 | {
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/XamUIDemo/Renderers/BorderlessEntry.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace XamUIDemo.Renderers
4 | {
5 | public class BorderlessEntry : Entry
6 | {
7 |
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/XamUIDemo/Renderers/PancakeView.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using XamUIDemo.Styles;
3 | using Xamarin.Forms;
4 |
5 | namespace XamUIDemo.Renderers
6 | {
7 | public class PancakeView : ContentView
8 | {
9 | #region properties
10 |
11 | public static readonly BindableProperty SidesProperty = BindableProperty.Create(nameof(Sides), typeof(int), typeof(PancakeView), defaultValue: 4);
12 | public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CornerRadius), typeof(CornerRadius), typeof(PancakeView), default(CornerRadius));
13 | public static readonly BindableProperty HasShadowProperty = BindableProperty.Create(nameof(HasShadow), typeof(bool), typeof(PancakeView), default(bool));
14 | public static readonly BindableProperty ElevationProperty = BindableProperty.Create(nameof(Elevation), typeof(int), typeof(PancakeView), 0);
15 |
16 | public static readonly BindableProperty BorderThicknessProperty = BindableProperty.Create(nameof(BorderThickness), typeof(float), typeof(PancakeView), default(float));
17 | public static readonly BindableProperty BorderIsDashedProperty = BindableProperty.Create(nameof(BorderIsDashed), typeof(bool), typeof(PancakeView), default(bool));
18 | public static readonly BindableProperty BorderColorProperty = BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(PancakeView), default(Color));
19 | public static readonly BindableProperty BorderDrawingStyleProperty = BindableProperty.Create(nameof(BorderDrawingStyle), typeof(BorderDrawingStyle), typeof(PancakeView), defaultValue: BorderDrawingStyle.Inside);
20 |
21 | public static readonly BindableProperty BackgroundGradientStartColorProperty = BindableProperty.Create(nameof(BackgroundGradientStartColor), typeof(Color), typeof(PancakeView), defaultValue: default(Color));
22 | public static readonly BindableProperty BackgroundGradientEndColorProperty = BindableProperty.Create(nameof(BackgroundGradientEndColor), typeof(Color), typeof(PancakeView), defaultValue: default(Color));
23 | public static readonly BindableProperty BackgroundGradientAngleProperty = BindableProperty.Create(nameof(BackgroundGradientAngle), typeof(int), typeof(PancakeView), defaultValue: default(int));
24 |
25 | public static readonly BindableProperty BackgroundGradientStopsProperty = BindableProperty.Create(nameof(BackgroundGradientStops), typeof(GradientStopCollection), typeof(PancakeView), defaultValue: default(GradientStopCollection),
26 | defaultValueCreator: bindable =>
27 | {
28 | return new GradientStopCollection();
29 | });
30 |
31 | public static readonly BindableProperty BorderGradientStartColorProperty = BindableProperty.Create(nameof(BorderGradientStartColor), typeof(Color), typeof(PancakeView), defaultValue: default(Color));
32 | public static readonly BindableProperty BorderGradientEndColorProperty = BindableProperty.Create(nameof(BorderGradientEndColor), typeof(Color), typeof(PancakeView), defaultValue: default(Color));
33 | public static readonly BindableProperty BorderGradientAngleProperty = BindableProperty.Create(nameof(BorderGradientAngle), typeof(int), typeof(PancakeView), defaultValue: default(int));
34 |
35 | public static readonly BindableProperty BorderGradientStopsProperty = BindableProperty.Create(nameof(BorderGradientStops), typeof(GradientStopCollection), typeof(PancakeView), defaultValue: default(GradientStopCollection),
36 | defaultValueCreator: bindable =>
37 | {
38 | return new GradientStopCollection();
39 | });
40 |
41 | public static readonly BindableProperty OffsetAngleProperty = BindableProperty.Create(nameof(OffsetAngle), typeof(double), typeof(PancakeView), default(double));
42 |
43 | public int Sides
44 | {
45 | get { return (int)GetValue(SidesProperty); }
46 | set { SetValue(SidesProperty, value); }
47 | }
48 |
49 | public Color BackgroundGradientStartColor
50 | {
51 | get { return (Color)GetValue(BackgroundGradientStartColorProperty); }
52 | set { SetValue(BackgroundGradientStartColorProperty, value); }
53 | }
54 |
55 | public Color BackgroundGradientEndColor
56 | {
57 | get { return (Color)GetValue(BackgroundGradientEndColorProperty); }
58 | set { SetValue(BackgroundGradientEndColorProperty, value); }
59 | }
60 |
61 | public int BackgroundGradientAngle
62 | {
63 | get { return (int)GetValue(BackgroundGradientAngleProperty); }
64 | set { SetValue(BackgroundGradientAngleProperty, value); }
65 | }
66 |
67 | public GradientStopCollection BackgroundGradientStops
68 | {
69 | get { return (GradientStopCollection)GetValue(BackgroundGradientStopsProperty); }
70 | set { SetValue(BackgroundGradientStopsProperty, value); }
71 | }
72 |
73 | public Color BorderGradientStartColor
74 | {
75 | get { return (Color)GetValue(BorderGradientStartColorProperty); }
76 | set { SetValue(BorderGradientStartColorProperty, value); }
77 | }
78 |
79 | public Color BorderGradientEndColor
80 | {
81 | get { return (Color)GetValue(BorderGradientEndColorProperty); }
82 | set { SetValue(BorderGradientEndColorProperty, value); }
83 | }
84 |
85 | public int BorderGradientAngle
86 | {
87 | get { return (int)GetValue(BorderGradientAngleProperty); }
88 | set { SetValue(BorderGradientAngleProperty, value); }
89 | }
90 |
91 | public GradientStopCollection BorderGradientStops
92 | {
93 | get { return (GradientStopCollection)GetValue(BorderGradientStopsProperty); }
94 | set { SetValue(BorderGradientStopsProperty, value); }
95 | }
96 |
97 | public CornerRadius CornerRadius
98 | {
99 | get { return (CornerRadius)GetValue(CornerRadiusProperty); }
100 | set { SetValue(CornerRadiusProperty, value); }
101 | }
102 |
103 | public float BorderThickness
104 | {
105 | get { return (float)GetValue(BorderThicknessProperty); }
106 | set { SetValue(BorderThicknessProperty, value); }
107 | }
108 |
109 | public bool BorderIsDashed
110 | {
111 | get { return (bool)GetValue(BorderIsDashedProperty); }
112 | set { SetValue(BorderIsDashedProperty, value); }
113 | }
114 |
115 | public Color BorderColor
116 | {
117 | get { return (Color)GetValue(BorderColorProperty); }
118 | set { SetValue(BorderColorProperty, value); }
119 | }
120 |
121 | public bool HasShadow
122 | {
123 | get { return (bool)GetValue(HasShadowProperty); }
124 | set { SetValue(HasShadowProperty, value); }
125 | }
126 |
127 | public int Elevation
128 | {
129 | get { return (int)GetValue(ElevationProperty); }
130 | set { SetValue(ElevationProperty, value); }
131 | }
132 |
133 | public BorderDrawingStyle BorderDrawingStyle
134 | {
135 | get { return (BorderDrawingStyle)GetValue(BorderDrawingStyleProperty); }
136 | set { SetValue(BorderDrawingStyleProperty, value); }
137 | }
138 |
139 | public double OffsetAngle
140 | {
141 | get { return (double)GetValue(OffsetAngleProperty); }
142 | set { SetValue(OffsetAngleProperty, value); }
143 | }
144 |
145 | //Helps keep track of Native Object assignment
146 | public IntPtr Handle { get; set; }
147 |
148 | #endregion
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/XamUIDemo/Styles/BorderDrawingStyle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace XamUIDemo.Styles
3 | {
4 | public enum BorderDrawingStyle
5 | {
6 | Inside,
7 | Outside
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/XamUIDemo/Styles/GradientStop.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 |
4 | namespace XamUIDemo.Styles
5 | {
6 | public class GradientStop
7 | {
8 | private float offset;
9 |
10 | public float Offset
11 | {
12 | get => offset;
13 | set
14 | {
15 | // Value needs to be 0-1.
16 | if (value > 1)
17 | value = 1;
18 | else if (value < 0)
19 | value = 0;
20 |
21 | offset = value;
22 | }
23 | }
24 |
25 | public Color Color { get; set; }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/XamUIDemo/Styles/GradientStopCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System;
3 | using System.Collections;
4 | using System.Collections.Generic;
5 | namespace XamUIDemo.Styles
6 | {
7 | public class GradientStopCollection : IList
8 | {
9 | readonly IList _internalList;
10 |
11 | public int Count => _internalList.Count;
12 |
13 | public bool IsReadOnly => false;
14 |
15 | public GradientStop this[int index]
16 | {
17 | get => _internalList[index];
18 | set => _internalList[index] = value;
19 | }
20 |
21 | public GradientStopCollection()
22 | {
23 | _internalList = new List();
24 | }
25 |
26 | public int IndexOf(GradientStop item)
27 | {
28 | return _internalList.IndexOf(item);
29 | }
30 |
31 | public void Insert(int index, GradientStop item)
32 | {
33 | if (item == null)
34 | {
35 | throw new ArgumentNullException(nameof(item));
36 | }
37 |
38 | _internalList.Insert(index, item);
39 | }
40 |
41 | public void RemoveAt(int index)
42 | {
43 | _internalList.RemoveAt(index);
44 | }
45 |
46 | public void Add(GradientStop item)
47 | {
48 | if (item == null)
49 | {
50 | throw new ArgumentNullException(nameof(item));
51 | }
52 |
53 | _internalList.Add(item);
54 | }
55 |
56 | public void Clear()
57 | {
58 | _internalList.Clear();
59 | }
60 |
61 | public bool Contains(GradientStop item)
62 | {
63 | return _internalList.Contains(item);
64 | }
65 |
66 | public void CopyTo(GradientStop[] array, int arrayIndex)
67 | {
68 | _internalList.CopyTo(array, arrayIndex);
69 | }
70 |
71 | public bool Remove(GradientStop item)
72 | {
73 | if (item == null)
74 | {
75 | throw new ArgumentNullException(nameof(item));
76 | }
77 |
78 | return _internalList.Remove(item);
79 | }
80 |
81 | public IEnumerator GetEnumerator()
82 | {
83 | return _internalList.GetEnumerator();
84 | }
85 |
86 | IEnumerator IEnumerable.GetEnumerator()
87 | {
88 | return ((IEnumerable)_internalList).GetEnumerator();
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/XamUIDemo/XamUIDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | true
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------