mirror of
https://github.com/LukeHagar/jims-blog.git
synced 2025-12-09 04:20:13 +00:00
14 lines
20 KiB
HTML
14 lines
20 KiB
HTML
<!doctype html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=x-ua-compatible content="ie=edge"><link rel=icon href=/fav.png type=image/png><link rel=preconnect href=https://fonts.googleapis.com><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=preload as=style href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"><link rel=stylesheet href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" media=print onload='this.media="all"'><noscript><link href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel=stylesheet></noscript><link rel=stylesheet href=/css/font.css media=all><meta property="og:title" content="Building a Xamarin Android app - part 1"><meta property="og:description" content="I’ve got a bit of time off between finishing my career as a slave to the world of finance IT and starting a new and exciting job as a Xamarin mobile app developer in New Zealand, so I thought I’d try to brush up on my Xamarin.Android knowledge as in the past I’ve mainly focused on iOS.
|
|
So to help me do this, I’ve decided to build and publish an app, and document the process."><meta property="og:type" content="article"><meta property="og:url" content="https://jimbobbennett.dev/blogs/building-an-android-app-part-1/"><meta property="og:image" content="https://jimbobbennett.dev/blogs/building-an-android-app-part-1/banner.png"><meta property="article:section" content="blogs"><meta property="article:published_time" content="2016-01-13T17:26:15+00:00"><meta property="article:modified_time" content="2016-01-13T17:26:15+00:00"><meta property="og:site_name" content="JimBobBennett"><meta name=twitter:card content="summary_large_image"><meta name=twitter:image content="https://jimbobbennett.dev/blogs/building-an-android-app-part-1/banner.png"><meta name=twitter:title content="Building a Xamarin Android app - part 1"><meta name=twitter:description content="I’ve got a bit of time off between finishing my career as a slave to the world of finance IT and starting a new and exciting job as a Xamarin mobile app developer in New Zealand, so I thought I’d try to brush up on my Xamarin.Android knowledge as in the past I’ve mainly focused on iOS.
|
|
So to help me do this, I’ve decided to build and publish an app, and document the process."><meta name=twitter:site content="@jimbobbennett"><meta name=twitter:creator content="@jimbobbennett"><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css integrity=sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3 crossorigin=anonymous><link rel=stylesheet href=/css/header.css media=all><link rel=stylesheet href=/css/footer.css media=all><link rel=stylesheet href=/css/theme.css media=all><link rel="shortcut icon" type=image/png href=/fav.png><link rel="shortcut icon" sizes=192x192 href=/fav.png><link rel=apple-touch-icon href=/fav.png><link rel=alternate type=application/rss+xml href=https://jimbobbennett.dev/index.xml title=JimBobBennett><script type=text/javascript>(function(e,t,n,s,o,i,a){e[n]=e[n]||function(){(e[n].q=e[n].q||[]).push(arguments)},i=t.createElement(s),i.async=1,i.src="https://www.clarity.ms/tag/"+o,a=t.getElementsByTagName(s)[0],a.parentNode.insertBefore(i,a)})(window,document,"clarity","script","dctc2ydykv")</script><style>:root{--text-color:#343a40;--text-secondary-color:#6c757d;--background-color:#000;--secondary-background-color:#64ffda1a;--primary-color:#007bff;--secondary-color:#f8f9fa;--text-color-dark:#e4e6eb;--text-secondary-color-dark:#b0b3b8;--background-color-dark:#000000;--secondary-background-color-dark:#212529;--primary-color-dark:#ffffff;--secondary-color-dark:#212529}body{background-color:#000;font-size:1rem;font-weight:400;line-height:1.5;text-align:left}</style><meta name=description content><link rel=stylesheet href=/css/index.css><link rel=stylesheet href=/css/single.css><link rel=stylesheet href=/css/projects.css media=all><script defer src=/fontawesome-5/all-5.15.4.js></script><title>Building a Xamarin Android app - part 1 | JimBobBennett</title></head><body class=light onload=loading()><header><nav class="pt-3 navbar navbar-expand-lg"><div class="container-fluid mx-xs-2 mx-sm-5 mx-md-5 mx-lg-5"><a class="navbar-brand primary-font text-wrap" href=/><img src=/fav.png width=30 height=30 class="d-inline-block align-top">
|
|
JimBobBennett</a>
|
|
<button class=navbar-toggler type=button data-bs-toggle=collapse data-bs-target=#navbarContent aria-controls=navbarContent aria-expanded=false aria-label="Toggle navigation"><svg aria-hidden="true" height="24" viewBox="0 0 16 16" width="24" data-view-component="true"><path fill-rule="evenodd" d="M1 2.75A.75.75.0 011.75 2h12.5a.75.75.0 110 1.5H1.75A.75.75.0 011 2.75zm0 5A.75.75.0 011.75 7h12.5a.75.75.0 110 1.5H1.75A.75.75.0 011 7.75zM1.75 12a.75.75.0 100 1.5h12.5a.75.75.0 100-1.5H1.75z"/></svg></button><div class="collapse navbar-collapse text-wrap primary-font" id=navbarContent><ul class="navbar-nav ms-auto text-center"><li class="nav-item navbar-text"><a class=nav-link href=/ aria-label=home>Home</a></li><li class="nav-item navbar-text"><a class=nav-link href=/#about aria-label=about>About</a></li><li class="nav-item navbar-text"><a class=nav-link href=/#projects aria-label=projects>Recent Highlights</a></li><li class="nav-item navbar-text"><a class=nav-link href=/blogs title="Blog posts">Blog</a></li><li class="nav-item navbar-text"><a class=nav-link href=/videos title=Videos>Videos</a></li><li class="nav-item navbar-text"><a class=nav-link href=/livestreams title=Livestreams>Livestreams</a></li><li class="nav-item navbar-text"><a class=nav-link href=/conferences title=Conferences>Conferences</a></li><li class="nav-item navbar-text"><a class=nav-link href=/resume title=Resume>Resume</a></li></ul></div></div></nav></header><div id=content><section id=projects><div class="container pt-5" id=list-page><div class="row justify-content-center px-3 px-md-5"><h1 class="text-left pb-2 content">Building a Xamarin Android app - part 1</h1><div class="text-left content">Jim Bennett
|
|
<small>|</small>
|
|
Jan 13, 2016</div></div></div></section><section id=single><div class=container><div class="row justify-content-center"><div class="col-sm-12 col-md-12 col-lg-9"><div class=pr-lg-4><article class="page-content p-2"><p>I’ve got a bit of time off between finishing my career as a slave to the world of finance IT and starting a new and exciting job as a Xamarin mobile app developer in New Zealand, so I thought I’d try to brush up on my Xamarin.Android knowledge as in the past I’ve mainly focused on iOS.</p><p>So to help me do this, I’ve decided to build and publish an app, and document the process. So over the next few posts I’ll be covering the development of Stupendous Counter - the most amazing counter app ever!</p><h3 id=stupendous-counter>Stupendous Counter</h3><p>The purpose of this app is simple - to count things. Think of it as an automated version of something like this:</p><div class=image-div style=width:200px><p><img src=61WNfiRPhoL-_SX522_.jpg alt="Click counter"></p></div><p>Obviously being an app it should be a bit more advanced, so I’ll be adding multiple named counters, count history with fancy charts, location based counts and other funky tools.</p><h4 id=design>Design</h4><p>First thing to do is to design the UI and flow of the app. I find this a good way to start as it gives me a feel for the views I need to create, the structure of the data I need to store and manipulate and allows me to test the UI out on paper before committing to writing code.</p><p>I’ve been playing with a few tools to aid in design, and currently using <a href=https://www.fluidui.com>Fluid UI</a>. It has a free tier that allows wireframe design, which is what I’ve been using. As well as allowing you to wireframe your UI, you can also setup transitions between screens to test out your UI flow.</p><p>The design I’ve come up with is a fairly boring, bog standard Android app with all the usual bits - a navigation drawer that’s poor UI, a <a href=http://exisweb.net/mobile-menu-abtest>hamburger menu</a> and a <a href=https://medium.com/tech-in-asia/material-design-why-the-floating-action-button-is-bad-ux-design-acd5b32c5ef#.babzdcoxi>floating action button that does something you don’t do very often</a>.</p><p>Here’s a screenshot of the final design for the first version of the app:
|
|
<img src=Screen-Shot-2016-01-13-at-14-13-13.png alt="Final UI design"></p><p>And heres the transitions:</p><div class=image-div style=width:200px><p><img src=CounterTransitions.gif alt="UI transitions"></p></div></br><p>For the colour scheme I used <a href=http://www.materialpalette.com>Material Palette</a> which is an awesome tool for choosing colours that work well together in a material design app or website. As a traditional developer I’m bad at design and UI so I enlisted the help of my 3 year old daughter to choose the colours - a process that took ages as she was enjoying ‘playing colours on daddy’s computer’.</p><div class=image-div style=width:200px><p><img src=Screen-Shot-2016-01-13-at-16-13-24.png alt="Colour scheme"></p></div></br><h4 id=lets-get-coding>Let’s get coding</h4><p>And the best way to write code? Get a tool to do it. To create the basic app structure with styles, navigation buttons etc. you need a lot of boiler plate code. Luckily James Montemagno from Xamarin has done the hard work for us with his <a href=http://motzcod.es/post/123682330002/new-improved-xamarinandroid-templates-for>Xamarin.Android templates for Visual Studio</a>. These templates provide the boiler plate code for a basic AppCompat app, or an AppCompat app with a navigation drawer.</p><div class=image-div style=width:700px><p><img src=Screen-Shot-2016-01-13-at-15-07-14.png alt="New project types"></p></div></br><p>To start with, I’m going to create a Navigation Drawer App called StupendousCounter.Droid. Note the name ends in .Droid, not .Android - otherwise you get a load of namespace clashes with the Android namespace).</p><div class=image-div style=width:200px><p><img src=CYNmIrJWcAYuxrq.png alt="Keep calm and .Droid it"></p></div></br><p>Once the app is created, it looks like this:</p><div class=image-div style=width:300px><p><img src=FirstAppVersion.gif alt="Initial navigation drawer app"></p></div></br><p>First thing to do is to make it more like what I’m after. The App name is wrong, the colours don’t match the scheme chosen by my daughter.</p><h6 id=colours>Colours</h6><p>Setting the colours is easy. In the template there is already a style defined in <code>Resources/values/styles.xml</code> which references colours defined in <code>Resources/values/colors.xml</code>. In the colors.xml file are a set of colour properties that match the output from Material Palette:</p></br><p><img src=Screen-Shot-2016-01-13-at-16-20-45.png alt="Colour values from material palette"></p></br><p>These colours can be downloaded as an XML file and the values copied in - you can’t just drop the xml file in as the names don’t write match - for example it’s primaryDark in the template generated code and primary_dark in the material Palette output, but it’s pretty obvious which value to copy into each field.
|
|
Once done the app looks a bit more like what we’re after:</p><div class=image-div style=width:500px><p><img src=Screen-Shot-2016-01-13-at-16-25-18.png alt="Correctly coloured app"></p></div></br><h6 id=app-name>App name</h6><p>The App name is in two parts - first the app name in the manifest file which defines the name given in the app settings, second the activity name that appears on the launcher.
|
|
The app name in the manifest file (<code>Properties\AndroidManifest.xml</code>) is defined as <code>android:label="@string/app_name"</code>, so correctly referring to a strings resource file located at <code>Resouces\values\strings.xml</code>. This is the recommended way to handle all text in your app so that you can easily localise it as described on the <a href=http://developer.android.com/training/basics/supporting-devices/languages.html>Android developer docs</a>. Setting the app name is therefore nice and easy, just change the strings.xml to have <code><string name="app_name">Stupendous Counter</string></code>. You may need to restart you emulator after re-deploying the app - XAP doesn’t update the name in the settings until you restart.</p><p>The main activity is not set up like this though - the template creates it with a hard-coded label of “Home”. I’d like this to match the app name so it’s consistent, so it’s a simple case of changing it to match the manifest: <code>[Activity(Label = "@string/app_name", ...)]</code>. Android uses the @ symbol to indicate a resource, so this syntax will correctly load the activities label from the string resources.</p><p>Once done it looks like this:</p><table cellspacing=0 cellpadding=0 style=border:none;border-collapse:collapse><tr style=padding:0;vertical-align:top><td style=padding:0;vertical-align:top><div class=image-div style=width:300px><p><img src=Screen-Shot-2016-01-13-at-17-19-14.png alt="App settings"></p></div></td><td style='padding:0 10px;vertical-align:top'><div class=image-div style=width:300px><p><img src=Screen-Shot-2016-01-13-at-16-42-22.png alt=Activity></p></div></td><td style=padding:0;vertical-align:top><div class=image-div style=width:79px><p><img src=Screen-Shot-2016-01-13-at-16-42-08.png alt="App icon"></p></div></td></tr></table></br><p>Done! Now we have a nice navigation drawer based app shell with the right name and the correct colours. In the <a href=/blogs/building-an-android-app-part-2/>next part</a> we’ll start adding some functionality.
|
|
The code for this is on Github here: <a href=https://github.com/jimbobbennett/StupendousCounter/tree/Part1>https://github.com/jimbobbennett/StupendousCounter/tree/Part1</a>
|
|
The code in the Part1 branch is the code for this part. The changes we make in later blog posts will be in other branches.</p><br><hr><h4 id=some-useful-bits>Some useful bits</h4><p>Here’s a couple of useful tips I cam across when writing this:</p><h6 id=debugging-xap-when-using-a-vm>Debugging XAP when using a VM</h6><p>My developer setup is a MacBook Pro running Windows 10 through Parallels and using Visual Studio 2015, with Xamarin Android Player installed as a Mac app, not a windows App (I use it from Xamarin Studio running on the Mac as well, so saving space/download time when upgrading etc. by only having it once). It’s pretty easy to run and debug Android apps on a player running natively on the Mac from VS on a Windows VM - instructions are <a href=https://developer.xamarin.com/guides/android/deployment,_testing,_and_metrics/android-player-with-visual-studio-in-vm/>here</a>.</p><h6 id=big-shoutout-to-cockos>Big shoutout to Cockos</h6><p>The animated Gifs in this blog post were captured using <a href=http://www.cockos.com/licecap/>LICEcap from Cockos</a>, an awesome free .Gif capture tool.</p><hr><p><table cellspacing=0 cellpadding=0 style=border:none;border-collapse:collapse><tr style=padding:0><td style=padding:0;vertical-align:top><iframe style=width:120px;height:240px marginwidth=0 marginheight=0 scrolling=no frameborder=0 src="//ws-eu.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&OneJS=1&Operation=GetAdHtml&MarketPlace=GB&source=ss&ref=ss_til&ad_type=product_link&tracking_id=expecti-21&marketplace=amazon®ion=GB&placement=B00FLW5G74&asins=B00FLW5G74&linkId=&show_border=false&link_opens_in_new_window=true"></iframe></td><td style='padding:0 30px'><p style=color:#686868;!important>And as a side line I'll also be listing the music I'm listening to when developing. Right now I'm listening to 'The Shocking Miss Emerald' by <a href=http://www.caroemerald.com>Caro Emerald</a>.</p><p style=color:#686868;!important>Note - this is an affiliate link - if you click here and buy I get a small cut.</p></td></tr></table></p></article></div></div><div class="col-sm-12 col-md-12 col-lg-3"><div class=sticky-sidebar><aside class=toc><h5>Table Of Contents</h5><div class=toc-content><nav id=TableOfContents><ul><li><ul><li><a href=#stupendous-counter>Stupendous Counter</a></li></ul></li></ul></nav></div></aside><aside class=tags><h5>Tags</h5><ul class="tags-ul list-unstyled list-inline"><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/xamarin target=_blank>xamarin</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/technology target=_blank>Technology</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/tutorial target=_blank>tutorial</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/xamarin.android target=_blank>xamarin.android</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/material-design target=_blank>material design</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/fluidui target=_blank>fluidui</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/design target=_blank>design</a></li></ul></aside></div></div></div><div class=row><div class="col-sm-12 col-md-12 col-lg-9 p-4"><div id=disqus_thread></div><script>var disqus_config=function(){this.page.url="https://jimbobbennett.dev/blogs/building-an-android-app-part-1/",this.page.identifier="56060bf0a3622df480589fc20192b1b2"};(function(){if(window.location.hostname=="localhost")return;var e=document,t=e.createElement("script");t.src="https://jimbobbennett.disqus.com/embed.js",t.setAttribute("data-timestamp",+new Date),(e.head||e.body).appendChild(t)})()</script><noscript>Please enable JavaScript to view the <a href=https://disqus.com/?ref_noscript>comments powered by Disqus.</a></noscript></div></div></div><button class="p-2 px-3" onclick=topFunction() id=topScroll>
|
|
<i class="fas fa-angle-up"></i></button></section><script>var topScroll=document.getElementById("topScroll");window.onscroll=function(){scrollFunction()};function scrollFunction(){document.body.scrollTop>20||document.documentElement.scrollTop>20?topScroll.style.display="block":topScroll.style.display="none"}function topFunction(){document.body.scrollTop=0,document.documentElement.scrollTop=0}</script></div><footer><div class="container py-4"><div class="row justify-content-center"><div class="col-md-4 text-center">© 2023 All Rights Reserved</div></div></div></div></footer><script src=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js integrity=sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13 crossorigin=anonymous></script>
|
|
<script>document.body.className.includes("light")&&(document.body.classList.add("dark"),localStorage.setItem("pref-theme","dark"))</script><script>let loadingIcons;function loading(){myVar=setTimeout(showPage,100)}function showPage(){try{document.getElementById("loading-icons").style.display="block"}catch{}}</script><script>function createCopyButton(e,t){const n=document.createElement("button");n.className="copy-code-button",n.type="button",n.innerText="Copy",n.addEventListener("click",()=>copyCodeToClipboard(n,e,t)),addCopyButtonToDom(n,e)}async function copyCodeToClipboard(e,t,n){const s=t.querySelector("pre > code").innerText;try{n.writeText(s)}finally{codeWasCopied(e)}}function codeWasCopied(e){e.blur(),e.innerText="Copied!",setTimeout(function(){e.innerText="Copy"},2e3)}function addCopyButtonToDom(e,t){t.insertBefore(e,t.firstChild);const n=document.createElement("div");n.className="highlight-wrapper",t.parentNode.insertBefore(n,t),n.appendChild(t)}if(navigator&&navigator.clipboard)document.querySelectorAll(".highlight").forEach(e=>createCopyButton(e,navigator.clipboard));else{var script=document.createElement("script");script.src="https://cdnjs.cloudflare.com/ajax/libs/clipboard-polyfill/2.7.0/clipboard-polyfill.promise.js",script.integrity="sha256-waClS2re9NUbXRsryKoof+F9qc1gjjIhc2eT7ZbIv94=",script.crossOrigin="anonymous",script.onload=function(){addCopyButtons(clipboard)},document.querySelectorAll(".highlight").forEach(e=>createCopyButton(e,script)),document.body.appendChild(script)}</script></body></html> |