<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Declares &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/declares/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Tue, 09 Jun 2026 01:34:34 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.7</generator>
	<item>
		<title>Detecting UI Compatibility Mode in macOS Apps with Xojo</title>
		<link>https://blog.xojo.com/2026/01/14/detecting-ui-compatibility-mode-in-macos-apps-with-xojo/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 14 Jan 2026 22:49:34 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15762</guid>

					<description><![CDATA[As you may already know, starting with Xojo 2025r3, macOS apps can be developed and compiled with UI Compatibility Mode either enabled or disabled. Now&#8230;]]></description>
										<content:encoded><![CDATA[
<p>As you may already know, starting with Xojo 2025r3, macOS apps can be developed and compiled with UI Compatibility Mode either enabled or disabled. Now imagine you are creating a Library intended for use in other projects and, as part of its UI-related functionality, the Library needs to determine whether the host application is running with UI Compatibility Mode enabled. How can you do that? Read on to find out.</p>



<span id="more-15762"></span>



<p>To determine whether a macOS app is running with UI Compatibility Mode enabled, we’ll use a small set of <a href="https://documentation.xojo.com/topics/declares/calling_native_macos_apis.html">Declares</a> inside a method contained in a Module, purely for the purposes of this example. Begin by creating a new Desktop project and adding a new Module to it (for example, a simple “Module1”). Next, add a new method to the Module with the following signature:</p>



<p><code>IsCompatibilityModeEnabled As Boolean</code></p>



<p>Then add the following code to the method:</p>



<pre class="wp-block-code"><code>#If TargetMacOS Then
  
  If System.Version.MajorVersion >= 26 Then
    
    Declare Function NSClassFromString Lib "Foundation" (clsName As CFStringRef) As Ptr
    Declare Function NSMainBundle Lib "AppKit" Selector "mainBundle" (obj As Ptr) As Ptr
    Declare Function NSInfoDictionary Lib "AppKit" Selector "infoDictionary" (obj As Ptr) As Ptr
    Declare Function NSDictValueForKey Lib "AppKit" Selector "valueForKey:" (obj As Ptr, key As CFStringRef) As Ptr
    Declare Function NSGetBoolValue Lib "AppKit" Selector "boolValue" (obj As Ptr) As Boolean
    
    Var Bundle As Ptr = NSClassFromString("NSBundle")
    
    If Bundle &lt;> Nil Then
      Var MainBundle As Ptr = NSMainBundle(Bundle)
      
      If MainBundle &lt;> Nil then
        Var infoDictionaryPlist As Ptr = NSInfoDictionary(MainBundle)
        
        If infoDictionaryPlist &lt;> Nil Then
          Var valueObj As Ptr = NSDictValueForKey(infoDictionaryPlist, "UIDesignRequiresCompatibility")
          
          If valueObj &lt;> Nil Then 
            Return NSGetBoolValue(valueObj)
          End If
          
        End If
        
      End If
      
    End If
  End If
  
  Return False
  
#EndIf</code></pre>



<p>In short, the previous code retrieves the app’s Info.plist from the macOS bundle and loads it into an NSDictionary object (similar to Xojo’s Dictionary). It then attempts to access the value associated with the key <code>UIDesignRequiresCompatibility</code>. If the returned object is Nil, it means the Info.plist does not contain that key and the app is therefore running in native macOS Tahoe mode. If the key is present, the method returns the Boolean value associated with it; a value of True indicates that the app is running with UI Compatibility Mode enabled under macOS Tahoe. That’s all there is to it!</p>



<h2 class="wp-block-heading">Testing the Method</h2>



<p>Now add a DesktopButton to the project’s default window and implement its Pressed event. Next, insert the following line of code into the associated Code Editor:</p>



<pre class="wp-block-code"><code>MessageBox("Compatibility Mode Enabled: " +  IsCompatibilityModeEnabled.ToString)</code></pre>



<p>For testing purposes, select Build Settings &gt; macOS in the Project Browser and enable UI Compatibility Mode, which can be found under the Build section of the Inspector. Run the app and, if your Mac is running macOS 26 or later, you will see the following message:</p>



<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="1204" height="860" src="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54.png" alt="" class="wp-image-15763" srcset="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54.png 1204w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54-300x214.png 300w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54-1024x731.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54-768x549.png 768w" sizes="(max-width: 1204px) 100vw, 1204px" /></figure>



<p>Quit the app and return to Build Settings &gt; macOS to disable UI Compatibility Mode. Run the app again and this time you will see the following message:</p>



<figure class="wp-block-image"><img decoding="async" width="1204" height="866" src="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22.png" alt="" class="wp-image-15764" srcset="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22.png 1204w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22-300x216.png 300w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22-1024x737.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22-768x552.png 768w" sizes="(max-width: 1204px) 100vw, 1204px" /></figure>



<h2 class="wp-block-heading">In Summary</h2>



<p>As you can see, Declares are a powerful feature in Xojo’s extensive toolbox, allowing developers to directly access and use APIs provided by the operating system. In this case, they enable you to retrieve the app’s Info.plist from the main bundle, load it into a dictionary, and read the value associated with a specific key.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Hide the Tabs in an Android MobileTabPanel Using Declares</title>
		<link>https://blog.xojo.com/2025/09/25/hide-the-tabs-in-an-android-mobiletabpanel-using-declares/</link>
		
		<dc:creator><![CDATA[Martin T.]]></dc:creator>
		<pubDate>Thu, 25 Sep 2025 16:47:58 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[PagePanel]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15409</guid>

					<description><![CDATA[Here’s how you can modify Xojo Android’s MobileTabPanel to behave more like the PagePanel found in Xojo Desktop and Web. A TabPanel, as the name&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Here’s how you can modify Xojo Android’s MobileTabPanel to behave more like the PagePanel found in Xojo Desktop and Web. A TabPanel, as the name suggests, shows tabs for the panels, while a PagePanel does not. Using PagePanel can be very useful in situations where you need greater freedom in designing your UI. With just a few lines of code, you can use Declares to turn a MobileTabPanel into a PagePanel on Android. Read on to see how.</p>



<p>Create a new Android project with two container controls in the IDE, to which you add some controls. Then switch back to Screen1 in the Navigator and add a MobileSegmentedButton and a MobileTabPanel. In the Inspector, set the locking for the TabPanel to all four sides and assign both container controls to the TabPanel via the Inspector. Those are the basic preparations.</p>



<p>The MobileTabPanel is a subclass of Android’s <a href="https://developer.android.com/reference/com/google/android/material/tabs/TabLayout" target="_blank" rel="noreferrer noopener">TabLayout</a> view (com.google.android.material.tabs.TabLayout). This consists of the tabs themselves and a so-called ViewPager that holds the containers.</p>



<p>First, we remove the top tab bar from the control. After that, we update the position of the area where the containers are displayed. Then we disable the swipe gesture (optional). And that’s it. </p>



<p>Now add the Opening event to TabPanel1. First, we add two Android-specific import Declares so that the following Declares don’t take up too much space and readability is maintained:</p>



<pre class="wp-block-code"><code>Declare Sub import1 Lib "android.view.*:Import"
Declare Sub import2 Lib "android.widget.*:Import"</code></pre>



<p>Next, we remove the tab bar from the control:</p>



<pre class="wp-block-code"><code>' Removes the tab bar from the MobileTabPanel.
Declare Function RemoveTabs Lib "Kotlin" Alias "(ref as ViewGroup).apply { visibility = View.GONE }" (ref As Ptr) As Ptr
Call RemoveTabs(Me.Handle)</code></pre>



<p>After that, we adjust the top position of the ViewPager by setting it to 0:</p>



<pre class="wp-block-code"><code>' Update control bounds.
Declare Function GetLayoutParams Lib "Object:Me:MobileTabPanel" Alias "_tabPager!!.layoutParams" As Ptr
Declare Function UpdateLayoutParams Lib "Kotlin" Alias "(ref as FrameLayout.LayoutParams).apply { topMargin = 0 }" (ref As Ptr) As Ptr
Call UpdateLayoutParams(GetLayoutParams)</code></pre>



<p>Now add the Pressed event to the MobileSegmentedButton with this code, which ensures switching between the panels:</p>



<pre class="wp-block-code"><code>TabPanel1.SelectedPanelIndex = segmentedIndex</code></pre>



<p>And that’s it – click Run to start the project.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" width="912" height="1024" src="https://blog.xojo.com/wp-content/uploads/2025/09/9F36A412-1902-449D-A3DD-FD062BCA4BC9-912x1024.png" alt="" class="wp-image-15411" style="width:616px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/09/9F36A412-1902-449D-A3DD-FD062BCA4BC9-912x1024.png 912w, https://blog.xojo.com/wp-content/uploads/2025/09/9F36A412-1902-449D-A3DD-FD062BCA4BC9-267x300.png 267w, https://blog.xojo.com/wp-content/uploads/2025/09/9F36A412-1902-449D-A3DD-FD062BCA4BC9-768x862.png 768w, https://blog.xojo.com/wp-content/uploads/2025/09/9F36A412-1902-449D-A3DD-FD062BCA4BC9-1369x1536.png 1369w, https://blog.xojo.com/wp-content/uploads/2025/09/9F36A412-1902-449D-A3DD-FD062BCA4BC9-1825x2048.png 1825w" sizes="(max-width: 912px) 100vw, 912px" /></figure>



<p><br>To make the control feel even more like a PagePanel, we now want to eliminate the ability to switch between panels with swipe gestures. To do this, go back into the TabPanel1 Opening event and add this code:</p>



<pre class="wp-block-code"><code>' Disable swipe.
Declare Sub setUserInputEnabled Lib "Object:Me:MobileTabPanel" Alias "_tabPager!!.setUserInputEnabled" (value As Boolean) setUserInputEnabled(False)</code></pre>



<p>And that’s it: the control is now a PagePanel – without tabs and within the same bounds as the TabPanel.</p>



<p>Here you can see the PagePanel in action.</p>



<div class="wp-block-media-text is-stacked-on-mobile is-vertically-aligned-top" style="grid-template-columns:37% auto"><figure class="wp-block-media-text__media"><video controls src="https://blog.xojo.com/wp-content/uploads/2025/09/pagepanel-1.mp4"></video></figure><div class="wp-block-media-text__content">
<p></p>
</div></div>



<p>Once you know where and what to look for in the Android API, there’s almost nothing you can’t already do with Declares in Xojo Android. But if you are looking for a native solution, you can join my <a href="https://tracker.xojo.com/xojoinc/xojo/-/issues/79929" target="_blank" rel="noreferrer noopener">feature request</a> to implement MobilePagePanel on Android.  </p>



<p>Happy Coding!</p>



<p><em>Martin T. is a Xojo MVP and has been very involved in testing Android support.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/09/pagepanel-1.mp4" length="2676015" type="video/mp4" />

			</item>
		<item>
		<title>DesktopTextArea Without Soft Wrapping Lines on macOS</title>
		<link>https://blog.xojo.com/2025/09/09/desktoptextarea-without-soft-wrapping-lines-on-macos/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 09 Sep 2025 19:31:26 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15083</guid>

					<description><![CDATA[When adding a DesktopTextArea to your macOS app, just drag it from the Library into a Window (or Container) in the layout editor of the&#8230;]]></description>
										<content:encoded><![CDATA[
<p>When adding a DesktopTextArea to your macOS app, just drag it from the Library into a Window (or Container) in the layout editor of the Xojo IDE. It works out of the box with native macOS behavior. But what if you want to change that native behavior, like, for example, disabling soft wrapping? Keep reading to learn how.</p>



<span id="more-15083"></span>



<p>On macOS, <a href="https://documentation.xojo.com/api/user_interface/desktop/desktoptextarea.html#desktoptextarea">DesktopTextArea</a> uses the native macOS control. When you need to tweak its behavior, <a href="https://documentation.xojo.com/api/language/declare.html#declare">Declares</a> can help. For example, by default text lines are soft-wrapped to the control’s width. But sometimes you may want to turn that off so each line displays in full, making the text easier to read line by line.</p>



<p>If you need to do just that, without resorting to other options because the use of a DesktopTextArea is what you really need to use, then put the following snippet of code into the Opening event handler for the DesktopTextArea instance:</p>



<p>If that’s exactly what you need to do and you want to stick with DesktopTextArea, just add the following code to the Opening event of your DesktopTextArea:</p>



<pre class="wp-block-code"><code>#If TargetMacOS Then
  // At this point we are getting really the handle to
  // the wrapping object: NSScrollView
  Var tAObj As Ptr = Me.Handle
  
  Declare Function Subviews Lib "AppKit" Selector "subviews" (obj As Ptr) As Ptr
  Declare Function ObjectAtIndex Lib "AppKit" Selector "objectAtIndex:" (obj As Ptr, index As Integer) As Ptr
  
  // We need to get the real NSTextView view that is set
  // inside the clip view set inside the NSScrollView
  Var subViewsFromScroll As Ptr = Subviews(tAObj)
  Var clipView As Ptr = ObjectAtIndex(subViewsFromScroll, 1)
  Var subViewsFromClipView As Ptr = Subviews(clipView)
  
  //…and here it is
  Var textAreaView As Ptr = ObjectAtIndex(subViewsFromClipView, 2)
  
  // At this point we have the real NSTextView from the wrapping NSScrollerView!
  
  Declare Function TextContainer Lib "AppKit" Selector "textContainer" (obj As Ptr) As Ptr
  Declare Sub SetWidthTracksTextView Lib "AppKit" Selector "setWidthTracksTextView:" (obj As Ptr, value As Boolean)
  Declare Sub SetContainerSize Lib "AppKit" Selector "setContainerSize:" (obj As Ptr, size As CGSize)
  Declare Sub SetMaxSize Lib "AppKit" Selector "setMaxSize:" (obj As Ptr, size As CGSize)
  
  // Retrieving the NSTextContainer
  Var tcObj As Ptr = TextContainer(textAreaView)
  SetWidthTracksTextView(tcObj, False)
  
  Var newSize As CGSize
  newSize.Width = 100000 // Arbitrary value… we only need to set it to a really high value!
  newSize.Height = 100000
  
  // And setting a new max width size to it.
  SetMaxSize(tAObj, newSize)
  
  // …and also using the same value for the size of the NSTextContainer
  SetContainerSize(tcObj, newSize)
#Endif</code></pre>



<p>The code above uses the <a href="https://developer.apple.com/documentation/corefoundation/cgsize?language=objc">CGSize</a> data type, a Struct added to the Window (though you’ll likely want to place it in a Module instead). It has two members:</p>



<ul class="wp-block-list">
<li>Width As Integer</li>



<li>Height As Integer</li>
</ul>



<p>We need to use this Data Type / Struct because some macOS framework methods from <a href="https://developer.apple.com/documentation/appkit/nsscrollview?language=objc">NSScrollView</a> and <a href="https://developer.apple.com/documentation/uikit/nstextcontainer?language=objc">NSTextContainer</a> expect it.</p>



<p>After adding the code, enable the &#8216;Has Horizontal Scrollbar&#8217; property in the Inspector for your DesktopTextArea. Run the app and you’ll see that soft wrapping is no longer applied!</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1424" height="1082" src="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-07-at-3.17.46 PM.png" alt="" class="wp-image-15084" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-07-at-3.17.46 PM.png 1424w, https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-07-at-3.17.46 PM-300x228.png 300w, https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-07-at-3.17.46 PM-1024x778.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-07-at-3.17.46 PM-768x584.png 768w" sizes="auto, (max-width: 1424px) 100vw, 1424px" /></figure>



<p>What other customized behaviors have you added to macOS DesktopTextArea instances via Declares? Go ahead and <a href="https://forum.xojo.com/c/code-sharing/">share the code</a> so other users can benefit from them.</p>



<p>Happy coding!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>4 Setting the Badge Color for Tabs on iOS</title>
		<link>https://blog.xojo.com/2025/08/20/4-setting-the-badge-color-for-tabs-on-ios/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 20 Aug 2025 14:00:00 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Navigation Bar]]></category>
		<category><![CDATA[TabBar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15208</guid>

					<description><![CDATA[This is the final article in our series on customizing the appearance of the NavigationBar and TabBar. In this post, we’ll go a step further&#8230;]]></description>
										<content:encoded><![CDATA[
<p>This is the final article in our series on customizing the appearance of the <code>NavigationBar</code> and <code>TabBar</code>. In this post, we’ll go a step further and show how to change the default color of the tab badge which is red by default.</p>



<p>As you might expect, we’ll need a few more Declares to accomplish this. Continue reading to learn how!</p>



<span id="more-15208"></span>



<p>Since we’re building on the example project from the first blog post in this series, I strongly recommend completing that post if you haven’t already, then continuing with the second and third articles before proceeding here.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="706" height="202" src="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-29-at-2.33.33-PM.png" alt="" class="wp-image-15209" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-29-at-2.33.33-PM.png 706w, https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-29-at-2.33.33-PM-300x86.png 300w" sizes="auto, (max-width: 706px) 100vw, 706px" /></figure>
</div>


<p>Select the &#8220;DeclaresForiOS&#8221; module and add a new method to it, using the following values for its signature in the Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>TabBarBadgeColor</code></li>



<li><strong>Parameters:</strong> Extends tab As <code>iOSTabBar</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And put the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>Var tabController As Ptr = tab.ViewControllerHandle

If value = Nil Then Return

Declare Function GetTabBar Lib "UIKit" Selector "tabBar" (obj As Ptr) As Ptr
Var tabBar As Ptr = GetTabBar(tabController)

Var colorPtr As Ptr = ColorGroupToUIColor(value)

Declare Function BarAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub SetAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)

Var appearance As Ptr = BarAppearance(tabBar)

Declare Function StackedLayout Lib "UIKit" Selector "stackedLayoutAppearance" (obj As Ptr) As Ptr
Declare Function InlineLayout Lib "UIKit" Selector "compactInlineLayoutAppearance" (obj As Ptr) As Ptr
Declare Function NormalState Lib "UIKit" Selector "normal" (obj As Ptr) As Ptr

Var stackLayout As Ptr = StackedLayout(appearance)
Var inLayout As Ptr = InlineLayout(appearance)
Var normalState As Ptr = NormalState(stackLayout)
Var normalInlineState As Ptr = NormalState(inLayout)

Declare Sub SetBadgeColor Lib "UIKit" Selector "setBadgeBackgroundColor:" (obj As Ptr, value As Ptr)

SetBadgeColor(normalState, colorPtr)
SetBadgeColor(normalInlineState, colorPtr)

SetAppearance(tabBar, appearance)

If System.Version.MajorVersion &gt;= 15 Then
  Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)
  SetScrollEdgeAppearance(tabBar, appearance)
End If</code></pre>



<p>Next, select the Screen1 item in the Navigator and add a new property to it using the following values in the Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>MyTabBadgeColor</code></li>



<li><strong>Type:</strong> <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<h3 class="wp-block-heading">Setting the Badge Text Color</h3>



<p>What’s next? I’m sure you guessed it! Now that we can customize the badge color, the default white text color on the badge may not always provide the best contrast.</p>



<p>Let’s add a new method to our &#8220;DeclaresForiOS&#8221; module with the following signature values in the Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>TabBarBadgeTextColor</code></li>



<li><strong>Parameters:</strong> Extends tab As <code>iOSTabBar</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And type (or paste) the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>Var tabController As Ptr = tab.ViewControllerHandle

If value = Nil Then Return

Declare Function GetTabBar Lib "UIKit" Selector "tabBar" (obj As Ptr) As Ptr
Var tabBar As Ptr = GetTabBar(tabController)

Var colorPtr As Ptr = ColorGroupToUIColor(value)

Declare Function BarAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub SetAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)

Var appearance As Ptr = BarAppearance(tabBar)

Declare Function StackedLayout Lib "UIKit" Selector "stackedLayoutAppearance" (obj As Ptr) As Ptr
Declare Function InlineLayout Lib "UIKit" Selector "compactInlineLayoutAppearance" (obj As Ptr) As Ptr
Declare Function NormalState Lib "UIKit" Selector "normal" (obj As Ptr) As Ptr

Var stackLayout As Ptr = StackedLayout(appearance)
Var inLayout As Ptr = InlineLayout(appearance)

Var normalState As Ptr = NormalState(stackLayout)
Var normalInlineState As Ptr = NormalState(inLayout)

Declare Sub SetBadgeTextAttr Lib "UIKit" Selector "setBadgeTextAttributes:" (obj As Ptr, value As Ptr)

Declare Function NSClassFromString Lib "Foundation" (name As CFStringRef) As Ptr
Declare Function DictionaryWithObjectForKey Lib "UIKit" Selector "dictionaryWithObject:forKey:" (obj As Ptr, value As Ptr, key As CFStringRef) As Ptr

Var dict As Ptr = DictionaryWithObjectForKey( NSClassFromString("NSMutableDictionary") , colorPtr, "NSColor")

SetBadgeTextAttr(normalState, dict)
SetBadgeTextAttr(normalInlineState, dict)

SetAppearance(tabBar, appearance)

If System.Version.MajorVersion >= 15 Then
  Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)
  SetScrollEdgeAppearance(tabBar, appearance)
End If</code></pre>



<p>Next, select the <code>Screen1</code> item in the Navigator and add a new property to it using the following values in the Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>MyTabBadgeTextColor</code></li>



<li><strong>Type:</strong> <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>Then, select the <code>Screen1.Opening</code> event handler and add these lines of code to it:</p>



<pre class="wp-block-code"><code>MyTabBadgeColor = New ColorGroup(Color.Green, Color.Blue)
MyTabBadgeTextColor = New ColorGroup(Color.Black, Color.Yellow)

Me.ParentTabBar.BadgeAt(0) = "33"
Me.ParentTabBar.BadgeAt(1) = "42"</code></pre>



<p>Lastly, select the <code>Screen1.AppearanceChanged</code> event handler and add this line of code at the end:</p>



<pre class="wp-block-code"><code>Me.ParentTabBar.TabBarBadgeColor = MyTabBadgeColor
Me.ParentTabBar.TabBarBadgeTextColor = MyTabBadgeTextColor</code></pre>



<h3 class="wp-block-heading">Testing the App</h3>



<p>Everything is set! Run the app on your iPhone or in the Simulator, and you’ll see each tab in the <code>TabBar</code> displaying its own badge with the custom background and text colors we configured in the Opening Event.</p>



<p>Download the example project from <a href="https://drive.google.com/file/d/1NJ7A3JHf60Fzo23AoY8dLA6m6phFSvpT/view?usp=sharing">this link</a>.</p>



<p>Happy Xojo Coding!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>3 Coloring the Tab Bar on iOS</title>
		<link>https://blog.xojo.com/2025/08/19/3-coloring-the-tab-bar-on-ios/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 19 Aug 2025 15:37:37 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Navigation Bar]]></category>
		<category><![CDATA[TabBar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15195</guid>

					<description><![CDATA[In the first two blog posts, we saw how important it is to customize the NavigationBar when theming your iOS app. However, that’s only part&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In the first two blog posts, we saw how important it is to customize the <code>NavigationBar</code> when theming your iOS app. However, that’s only part of the equation, especially if your app also uses a <code>TabBar</code>. In that case, you&#8217;ll likely want to customize not only the background color of the <code>TabBar</code>, but also the text color of the selected tab and the color used for the unselected tabs.</p>



<p>Continue reading to learn how to do all of this thanks to the powerful flexibility of Declares!</p>



<span id="more-15195"></span>



<p>Before we dive in, keep in mind that we&#8217;re building on the example project introduced in the first blog post of this series. If you haven’t read it yet, I encourage you to start there. Then, follow up with the second post to make sure you&#8217;re fully up to speed and ready to continue adding even more color customization to your iOS screens!</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="704" height="220" src="https://blog.xojo.com/wp-content/uploads/2025/07/TabBar.png" alt="" class="wp-image-15196" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/TabBar.png 704w, https://blog.xojo.com/wp-content/uploads/2025/07/TabBar-300x94.png 300w" sizes="auto, (max-width: 704px) 100vw, 704px" /></figure>
</div>


<h3 class="wp-block-heading">Background Color for the TabBar</h3>



<p>In order to colorize the <code>TabBar</code> background, we need to add a new method to the &#8220;DeclaresForiOS&#8221; Module using the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>TabBarBackgroundColor</code></li>



<li><strong>Parameters:</strong> Extends tab As <code>iOSTabBar</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>Add the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>Var tabController As Ptr = tab.ViewControllerHandle

If value = Nil Then Return

Declare Function GetTabBar Lib "UIKit" Selector "tabBar" (obj As Ptr) As Ptr
Var tabBar As Ptr = GetTabBar(tabController)

Var colorPtr As Ptr = ColorGroupToUIColor(value)

Declare Function BarAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub ConfigureWithOpaqueBackground Lib "UIKit" Selector "configureWithOpaqueBackground" (obj As Ptr)
Declare Sub SetBackgroundColor Lib "UIKit" Selector "setBackgroundColor:" (obj As Ptr, value As Ptr)
Declare Sub SetAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)

Var appearance As Ptr = BarAppearance(tabBar)
SetBackgroundColor(appearance, colorPtr)

SetAppearance(tabBar, appearance)

If System.Version.MajorVersion >= 15 Then
  Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)
  SetScrollEdgeAppearance(tabBar, appearance)
End If</code></pre>



<p>Essentially, we’re setting the color by assigning it to the <code>backgroundColor</code> property of the <code>appearance</code> object associated with the <code>TabBar</code>.</p>



<h3 class="wp-block-heading">Setting the Text Color</h3>



<p>Now let’s add the code responsible for setting the text color of the selected tab in the <code>TabBar</code>. To do this, we just need to set the <code>tintColor</code> property. So, go ahead and add a new method to the &#8220;DeclaresForiOS&#8221; module with the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>TabBarTextColor</code></li>



<li><strong>Parameters:</strong> Extends tab As <code>iOSTabBar</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And put the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>Var tabController As Ptr = tab.ViewControllerHandle

If value = Nil Then Return

Declare Function GetTabBar Lib "UIKit" Selector "tabBar" (obj As Ptr) As Ptr
Var tabBar As Ptr = GetTabBar(tabController)

Var colorPtr As Ptr = ColorGroupToUIColor(value)

Declare Sub SetTintColor Lib "UIKit" Selector "setTintColor:" (obj As Ptr, value As Ptr)

SetTintColor(tabBar, colorPtr)</code></pre>



<h3 class="wp-block-heading">Setting Unselected Tabs Text Color</h3>



<p>To set the text color for unselected tabs, we’ll need to use a few additional Declares. This is because the color must be applied to the <em>normal</em> state of the <code>stackedLayoutAppearance</code> object from the TabBar’s appearance. Additionally, we need to set the same value for the <code>compactInlineLayoutAppearance</code>, which is used when the device is in landscape orientation.</p>



<p>Add a new method to the &#8220;DeclaresForiOS&#8221; Module using the following values for its signature:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>TabBarUnselectedTextColor</code></li>



<li><strong>Parameters:</strong> Extends tab As <code>iOSTabBar</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And add the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>Var tabController As Ptr = tab.ViewControllerHandle

If value = Nil Then Return

Declare Function GetTabBar Lib "UIKit" Selector "tabBar" (obj As Ptr) As Ptr
Var tabBar As Ptr = GetTabBar(tabController)

Var colorPtr As Ptr = ColorGroupToUIColor(value)

Declare Function BarAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub SetAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)

Declare Function StackedLayout Lib "UIKit" Selector "stackedLayoutAppearance" (obj As Ptr) As Ptr
Declare Function InlineLayout Lib "UIKit" Selector "compactInlineLayoutAppearance" (obj As Ptr) As Ptr
Declare Function NormalState Lib "UIKit" Selector "normal" (obj As Ptr) As Ptr

Var appearance As Ptr = BarAppearance(tabBar)
Var stackLayout As Ptr = StackedLayout(appearance)
Var inLayout As Ptr = InlineLayout(appearance)

Var normalState As Ptr = normalState(stackLayout)
Var normalInlineState As Ptr = NormalState(inLayout)

Declare Function NSClassFromString Lib "Foundation" (name As CFStringRef) As Ptr
Declare Function DictionaryWithObjectForKey Lib "UIKit" Selector "dictionaryWithObject:forKey:" (obj As Ptr, value As Ptr, key As CFStringRef) As Ptr

Var dict As Ptr = DictionaryWithObjectForKey( NSClassFromString("NSMutableDictionary") , colorPtr, "NSColor")

Declare Sub SetTextAttributes Lib "UIKit" Selector "setTitleTextAttributes:" (obj As Ptr, value As Ptr)

SetTextAttributes(normalState, dict)
SetTextAttributes(normalInlineState, dict)
SetAppearance(tabBar, appearance)

If System.Version.MajorVersion >= 15 Then
  Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)
  SetScrollEdgeAppearance(tabBar, appearance)
End If</code></pre>



<h3 class="wp-block-heading">Testing the TabBar Color</h3>



<p>Add a new screen to the project so that our example app includes at least two screens. You can do this by selecting Insert &gt; Screen from the IDE toolbar.</p>



<p>To test the new methods, we need the app to use a <code>TabBar</code>. To enable that, select the iPhoneLayout item in the Navigator. Then, in the Inspector Panel, locate the Content label and choose Tabs from the associated popup menu. Finally, set <code>Screen1</code> as the content for Tab 0 using the &#8220;Tab 0 Content&#8221; popup menu.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1860" height="1292" src="https://blog.xojo.com/wp-content/uploads/2025/07/SettingTab0.png" alt="" class="wp-image-15197" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/SettingTab0.png 1860w, https://blog.xojo.com/wp-content/uploads/2025/07/SettingTab0-300x208.png 300w, https://blog.xojo.com/wp-content/uploads/2025/07/SettingTab0-1024x711.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/07/SettingTab0-768x533.png 768w, https://blog.xojo.com/wp-content/uploads/2025/07/SettingTab0-1536x1067.png 1536w" sizes="auto, (max-width: 1860px) 100vw, 1860px" /></figure>
</div>


<p>Next, with <code>Screen1</code> still selected in the Navigator, click on the &#8220;Tab 1&#8221; label in the Layout Editor. Then, in the Inspector<strong> </strong>Panel, use the popup menu next to the &#8220;Tab 1 Content&#8221; label to select <code>Screen2</code>.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1890" height="1262" src="https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1.png" alt="" class="wp-image-15198" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1.png 1890w, https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1-300x200.png 300w, https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1-1024x684.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1-768x513.png 768w, https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1-1536x1026.png 1536w" sizes="auto, (max-width: 1890px) 100vw, 1890px" /></figure>
</div>


<p>With <code>Screen1</code> still selected in the Navigator, add a new property to it using the following values:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>MyTabBarUnselectedTextColor</code></li>



<li><strong>Type:</strong> <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>Now select the <code>Screen1.Opening</code> event handler and add this line of code:</p>



<pre class="wp-block-code"><code>MyTabBarUnselectedTextColor = New ColorGroup(Color.White, Color.LightGray)</code></pre>



<p>As the last step, select the <code>Screen1.AppearanceChanged</code> event handler and add this line of code:</p>



<pre class="wp-block-code"><code>Me.ParentTabBar.TabBarBackgroundColor = mNavigationBarColor
Me.ParentTabBar.TabBarTextColor = MyNavigationBarTextColor
Me.ParentTabBar.TabBarUnselectedTextColor = MyTabBarUnselectedTextColor</code></pre>



<p>All set! Now it’s time to run the example project in the Simulator or on your iPhone. You’ll see that the <code>TabBar</code> background color matches the one set for the <code>NavigationBar</code>, and the selected tab text color is consistent as well. The unselected tab text appears white in Light Mode and light gray in Dark Mode, reflecting the <code>ColorGroup</code> settings.</p>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationAndTabBar.mp4"></video></figure>



<p>As we’ve seen, Declares are a powerful way to tap into native iOS framework functions and routines. The most challenging part is often figuring out which ones to use since that requires digging into Apple’s developer documentation.</p>



<p>Download the example project from <a href="https://drive.google.com/file/d/1dN6mIe55FkUPEUl-_fanCMvXX3fdarr1/view?usp=sharing">this link</a>.</p>



<p>Happy Xojo coding!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p></p>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationAndTabBar.mp4" length="145232" type="video/mp4" />

			</item>
		<item>
		<title>2 Coloring the Navigation Bar Text on iOS</title>
		<link>https://blog.xojo.com/2025/08/18/2-coloring-the-navigation-bar-text-on-ios/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 18 Aug 2025 21:53:11 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Navigation Bar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15184</guid>

					<description><![CDATA[In a previous blog post, we covered how to set the color of the NavigationBar on a MobileScreen in iOS projects. However, if you&#8217;re customizing&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In a previous blog post, we covered how to set the color of the <code>NavigationBar</code> on a <code>MobileScreen</code> in iOS projects. However, if you&#8217;re customizing the Navigation Bar’s background, you&#8217;ll likely want control over the title text color and the color of any buttons added to it as well.</p>



<p>Continue reading to learn how to customize those elements too.</p>



<span id="more-15184"></span>



<p>Just like in the previous blog post, we’ll need to use several Declares to access the necessary iOS framework functions and retrieve the underlying objects we want to modify.</p>



<p>If you haven’t followed the previous post yet, be sure to check it out first—we’ll be building on the same example project to add these new customizations.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="714" height="480" src="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-28-at-3.54.32-PM.png" alt="" class="wp-image-15188" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-28-at-3.54.32-PM.png 714w, https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-28-at-3.54.32-PM-300x202.png 300w" sizes="auto, (max-width: 714px) 100vw, 714px" /></figure>
</div>


<p>Let&#8217;s add a new method to our previously created &#8220;DeclaresForiOS&#8221; Module using the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>NavigationBarTextColor</code></li>



<li><strong>Parameters:</strong> Extends screen As <code>MobileScreen</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And add the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>If value = Nil Then Return

Var controller As Ptr = screen.ViewControllerHandle

Declare Function NavigationController Lib "UIKit" Selector "navigationController" (controller As Ptr) As Ptr
Declare Function NavigationBar Lib "UIKit" Selector "navigationBar" (controller As Ptr) As Ptr

Var nc As Ptr = NavigationController(controller)
Var nv As Ptr = NavigationBar(nc)

Var colPtr As Ptr
colPtr = ColorGroupToUIColor(value)

Declare Function DictionaryWithObjectForKey Lib "UIKit" Selector "dictionaryWithObject:forKey:" (obj As Ptr, value As Ptr, key As CFStringRef) As Ptr

// https://developer.apple.com/documentation/foundation/nsclassfromstring(_:)?language=objc
Declare Function NSClassFromString Lib "Foundation" (name As CFStringRef) As Ptr

Declare Function StandardAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub SetStandardAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)
Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)

Declare Sub SetTitleTextAttributedText Lib "UIKit" Selector "setTitleTextAttributes:" (obj As Ptr, value As Ptr)
Declare Sub SetLargeTitleTextAttributedText Lib "UIKit" Selector "setLargeTitleTextAttributes:" (obj As Ptr, value As Ptr)

Declare Sub SetTintColor Lib "UIKit" Selector "setTintColor:" (obj As Ptr, value As Ptr)

// We need to create a NSDictionary with the attribute we want to set on text for the NavigationBar Appearance
Var dict As Ptr = DictionaryWithObjectForKey(NSClassFromString("NSMutableDictionary"), colPtr, "NSColor")

Var appear As Ptr = StandardAppearance(nv)

// Setting the new appearance settings both for the regular-sized title
// and the Large one
SetTitleTextAttributedText(appear, dict)
SetLargeTitleTextAttributedText(appear, dict)

// And we apply the modified appearance to the StandardAppearance
SetStandardAppearance(nv, appear)

// And to the scrollEdgeAppearance if the app is run on iOS 15+
If (System.Version.MajorVersion >= 15.0) Then
   SetScrollEdgeAppearance(nv, appear)
End If

// The TintColor is applied on the text of the added buttons to the NavigationBar
// So we need to use the same color for them!
SetTintColor(nv, colPtr)</code></pre>



<p>And that&#8217;s all the code we need.</p>



<h3 class="wp-block-heading">Colorizing!</h3>



<p>Select the <code>Screen1</code> item in the Navigator and add a new property to it using the following values:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>MyNavigationBarTextColor</code></li>



<li><strong>Type:</strong> <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>Now select the <code>Screen1.Opening</code> event and add the following line of code:</p>



<pre class="wp-block-code"><code>MyNavigationBarTextColor = New ColorGroup(Color.Yellow, Color.Red)</code></pre>



<p>Finally, select the <code>Screen1.AppearanceChanged</code> event handler and add the following line:</p>



<pre class="wp-block-code"><code>Me.NavigationBarTextColor = MyNavigationBarTextColor</code></pre>



<p>Run the example project, and you’ll see that the title text remains correctly displayed, even when switching between Light and Dark modes.</p>



<p>Download the example project from <a href="https://drive.google.com/file/d/1nLqY6Vaq2eeUr-qeTGpxA-LmMERYOSEk/view?usp=sharing">this link</a>.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>1 Coloring Your iOS App Navigation Bar</title>
		<link>https://blog.xojo.com/2025/08/11/1-coloring-your-ios-app-navigation-bar/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 11 Aug 2025 18:08:31 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Navigation Bar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15175</guid>

					<description><![CDATA[This is the first of a series of 4 posts about customizing the Navigation and Tab Bars. One of the best ways to give your&#8230;]]></description>
										<content:encoded><![CDATA[
<p>This is the first of a series of 4 posts about customizing the Navigation and Tab Bars. One of the best ways to give your iOS app a custom look is by theming the Navigation Bar. While it’s possible to do this using a <code>ContainerControl</code> or a <code>Rectangle</code> with carefully applied constraints, there’s a better and more direct approach—using Declares.</p>



<p>Keep reading to learn how to style your Navigation Bar.</p>



<span id="more-15175"></span>



<p>Declares in Xojo allow you to access functions and constants from compiled libraries and system frameworks such as those provided by iOS or third-party developers. They’re a powerful way to extend your app’s capabilities beyond what is available in the Xojo framework.</p>



<p>In this case, we’ll use Declares to tap into the native iOS APIs and customize the appearance of a <code>MobileScreen</code>&#8216;s <code>NavigationBar</code>, specifically to set its background color.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2411" height="940" src="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp.png" alt="" class="wp-image-15181" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp.png 2411w, https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp-300x117.png 300w, https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp-1024x399.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp-768x299.png 768w, https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp-1536x599.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp-2048x798.png 2048w" sizes="auto, (max-width: 2411px) 100vw, 2411px" /></figure>



<p>Start by adding a new module to your existing or empty iOS project. I&#8217;ve named this <code>DeclaresForiOS</code>. Within this module, add a new method using the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>NavigationBarColor</code></li>



<li><strong>Parameters:</strong> Extends Screen As <code>MobileScreen</code>, Assigns Value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>Add the following snippet of code in the Associated Code Editor:</p>



<pre class="wp-block-code"><code>// Getting the ViewController for the received Screen
Var controller As Ptr = Screen.ViewControllerHandle

// https://developer.apple.com/documentation/uikit/uiviewcontroller/navigationcontroller?language=objc
Declare Function NavigationController Lib "UIKit" Selector "navigationController" (controller As Ptr) As Ptr

// https://developer.apple.com/documentation/uikit/uinavigationcontroller/navigationbar?language=objc
Declare Function NavigationBar Lib "UIKit" Selector "navigationBar" (controller As Ptr) As Ptr

// Getting the NavigationBarController associated with the ViewController
Var nc As Ptr = NavigationController(controller)

// …and the NavigationBar itself from the NavigationBarController
Var nv As Ptr = NavigationBar(nc)

Var colPtr As Ptr
If value &lt;> Nil Then
  colPtr = ColorGroupToUIColor(value)
End If

// https://developer.apple.com/documentation/uikit/uinavigationbar/standardappearance?language=objc
Declare Function StandardAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub SetStandardAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)

// https://developer.apple.com/documentation/uikit/uinavigationbar/scrolledgeappearance?language=objc
Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)

// https://developer.apple.com/documentation/uikit/uibarappearance/backgroundcolor?language=objc
Declare Sub SetBackgroundColor Lib "UIKit" Selector "setBackgroundColor:" (obj As Ptr, value As Ptr)

// Getting the StandardAppearance object from the NavigationBar
Var appear As Ptr = StandardAppearance(nv)

// Setting the BackgroundColor to the StandardAppearance…
SetBackgroundColor(appear, colPtr)

// …and assigning the Standard Appearance again to the NavigationBar
SetStandardAppearance(nv, appear)

// If our app is running on iOS >= 15.0, then we need to set
// the same appearance to the scrollEdgeAppearance attribute on the NavigationBar
if (System.Version.MajorVersion >= 15.0) then
  SetScrollEdgeAppearance(nv, appear)
end if</code></pre>



<p>As shown in the previous code, we’re calling the <code>ColorGroupToUIColor</code> method to convert a <code>ColorGroup</code> instance into a pointer to a valid <code>UIColor</code>. To support this, let’s add that helper method to our <code>DeclaresForiOS</code> module using the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>ColorGroupToUIColor</code></li>



<li><strong>Parameters:</strong> value As <code>ColorGroup</code></li>



<li><strong>Return Type:</strong> Ptr</li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And type (or paste) the following snippet of code:</p>



<pre class="wp-block-code"><code>Var colorPtr As Ptr
Var c As Color

Select Case value.Mode
  
Case ColorGroup.Modes.Dual
  Var valueColors() As Color = value.Values
  If Color.IsDarkMode And valueColors.LastIndex > 0 Then
    c = valueColors(1)
  Else
    c = valueColors(0)
  End If
Case ColorGroup.Modes.Single
  Var valueColors() As Color = value.Values
  c = valueColors(0)
End Select

If colorPtr = Nil Then
  
  // https://developer.apple.com/documentation/foundation/nsclassfromstring(_:)?language=objc
  Declare Function NSClassFromString Lib "Foundation" (name As CFStringRef) As Ptr
  
  // https://developer.apple.com/documentation/uikit/uicolor/1621930-colorwithred
  Declare Function RGBA Lib "UIKit" selector "colorWithRed:green:blue:alpha:" (cls As Ptr, r As Double, g As Double, b As Double, a As Double) As Ptr
  
  colorPtr = RGBA(NSClassFromString("UIColor"), c.Red/255, c.Green/255, c.Blue/255, 1-(c.Alpha/255))
  
End If

return colorPtr</code></pre>



<h3 class="wp-block-heading">Let&#8217;s Color That!</h3>



<p>And that is all the code we need! Now select the <code>Screen1</code> item in the Navigator for the iOS project and add the following property to it:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>MyNavigationBarColor</code></li>



<li><strong>Type:</strong> <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>With the Screen1 still selected in the Navigator, add the Opening event to it and add the following line of code:</p>



<pre class="wp-block-code"><code>MyNavigationBarColor = New ColorGroup( color.Red, color.Yellow )</code></pre>



<p>As the last step, add the <code>AppearanceChanged</code> event to the <code>Screen1</code> item; and add the following line of code to it:</p>



<pre class="wp-block-code"><code>me.NavigationBarColor = MyNavigationBarColor</code></pre>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBariOSSwitchingColor.mp4"></video></figure>



<p>Make sure the &#8220;Has Navigation Bar&#8221; attribute is enabled in the Inspector for <code>Screen1</code>, then run the project. If your Simulator or device is set to Light Mode, the Navigation Bar will appear red; if it’s in Dark Mode, it will appear yellow. You can switch between Light and Dark modes to see the Navigation Bar color transition between the two colors defined in your <code>ColorGroup</code>.</p>



<p>Download the example project from <a href="https://drive.google.com/file/d/15Seqvo8FKx_nYiMSHc5tecS2OC-HcnI7/view?usp=sharing">this link</a>.</p>



<p>Happy coding!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBariOSSwitchingColor.mp4" length="133233" type="video/mp4" />

			</item>
		<item>
		<title>Use AndroidMobileUserControl to Create Custom Controls</title>
		<link>https://blog.xojo.com/2025/03/25/use-androidmobileusercontrol-to-create-custom-controls/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 25 Mar 2025 15:30:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[2025r1]]></category>
		<category><![CDATA[Control]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[User Interface]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14637</guid>

					<description><![CDATA[Xojo for Android has robust Declare and Library support that allows you to call into many native Android libraries and frameworks. With the newly added&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo for Android has robust <a href="https://blog.xojo.com/2024/10/01/android-declare-and-library-enhancements/">Declare and Library support</a> that allows you to call into many native Android libraries and frameworks. With the newly added AndroidMobileUserControl you can also create your own native UI controls as well.</p>



<p>This control is available in the Xojo Library panel and works similarly to iOSMobileUserControl: drag it onto a layout and implement the CreateView event.</p>



<pre class="wp-block-code"><code>Declare Function Button Lib "Kotlin" Alias "android.widget.Button(context as android.content.Context)" (context As Ptr) As Ptr

Var bp As Ptr = Button(App.AndroidContextHandle)

Return bp</code></pre>



<p>The above code uses a Declare to create a native Button and returns it so that it can be displayed in a layout.</p>



<p>By using AndroidMobileUserControl and Declares to access the Android UI library, you can create your own UI controls. I look forward to seeing what the community creates!</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>macOS: Add More Options to the Window Menu</title>
		<link>https://blog.xojo.com/2024/12/16/macos-add-more-options-to-the-window-menu/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 16 Dec 2024 16:00:00 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[App Localization]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14163</guid>

					<description><![CDATA[By default, macOS adds several menu options to the Window menu of any Desktop app. Those options have been getting more interesting in the latest&#8230;]]></description>
										<content:encoded><![CDATA[
<p>By default, macOS adds several menu options to the Window menu of any Desktop app. Those options have been getting more interesting in the latest releases of the operating system, allowing, among other things, to set the position and arrangement of the Window on the screen, split the screen between the Window of one app and another app, or even sending a window of an app to an iPad as an &#8220;extended&#8221; screen in your macOS setup. Read on, adding these options to your Xojo-built macOS apps is just a few Declares away!</p>



<span id="more-14163"></span>



<p>Once you add this ability to your macOS apps, they will fit better when compared with other apps running alongside them. Even better, you don&#8217;t need to write additional code in order to handle these additional menu options.</p>



<p>Create a new Desktop project and add a new Module to it called &#8220;macOSExtra&#8221;. Then add a new method to it using the following signature, make sure to set the Scope of the property to Global:</p>



<pre class="wp-block-code"><code>AddMacOSWindowMenu(item as DesktopMenuItem)</code></pre>



<p>As you can see, this method expects to receive a DesktopMenuItem instance; but before we write a line of code for this method, select the MainMenuBar item in the project Navigator.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="84" height="62" src="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.50.03 p. m.png" alt="" class="wp-image-14164"/></figure>
</div>


<p>The previous action will bring up the Menu Editor. Click on the toolbar button in charge of adding a new first level menu item to the menu bar:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="2058" height="696" src="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.49.08 p. m.png" alt="" class="wp-image-14165" srcset="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.49.08 p. m.png 2058w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.49.08 p. m-300x101.png 300w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.49.08 p. m-1024x346.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.49.08 p. m-768x260.png 768w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.49.08 p. m-1536x519.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.49.08 p. m-2048x693.png 2048w" sizes="auto, (max-width: 2058px) 100vw, 2058px" /></figure>
</div>


<p>Next, with the new menu item selected in the Navigator, change the following properties in the associated Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> WindowMenu</li>



<li><strong>Text:</strong> Window</li>
</ul>



<p>Now, let&#8217;s go back to the AddMacOSWindowMenu method in the &#8220;macOSEXtra&#8221; module, type the following code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>// This code will be only executed when compiling the project
// for the macOS target

#if TargetMacOS then
  
  // We declare the function allowing us to get the reference to a class
  // from the macOS framework (Foundation, in this case), from the parameter passed
  // to it as a String (the class name we want to get the reference to).
  // You can get additional information about this from the Apple Documentation at: https://developer.apple.com/documentation/foundation/1395135-nsclassfromstring?language=objc
  Declare Function NSClassFromString Lib "Foundation" ( name As CFStringRef) As Ptr
  Var theClass As Ptr = NSClassFromString("NSApplication")
  
  // Now that we have the reference to the class
  // we will use it to call the shared method / selector from the NSApplication
  // class in charge or returning a reference to the running app (that is "our" app in this case).
  // You can get additional information about this from the Apple Documentation at:
https:&#47;&#47;developer.apple.com/documentation/appkit/nsapplication/shared?language=objc
  
  Declare Function GetSharedApplication Lib "AppKit" Selector "sharedApplication" (Application As ptr) As Ptr
  Var theApp As Ptr = GetSharedApplication(theClass)
  
  // Now that we have a reference to the app object, we need to get a reference to the "submenu" hanging from the menu instance received as parameter by the method. For that
  // we need to call the method / selector "submenu" passing along the underlying native
  // menu object retrieved via the "Handle" property from DesktopMenuItem.
  
  Declare Function GetSubmenu Lib "AppKit" Selector "submenu" (menuReference As Ptr) As Ptr
  Var subMenu As Ptr = GetSubmenu(item.Handle)
  
  // The last step is to assign the previous reference to the window property from the app reference.
  // You can get additional information about this from the Apple Documentation at: https://developer.apple.com/documentation/appkit/nsapplication/windowsmenu?language=objc
  
  Declare Sub setWindowMenu Lib "AppKit" selector "setWindowsMenu:" ( appReference As Ptr, menuReference As Ptr)
  setWindowMenu(theApp, subMenu)
  
#EndIf
</code></pre>



<h2 class="wp-block-heading">Testing it!</h2>



<p>In order to see how this new method works, select the App item under the IDE Navigator and add the Opening event. Then, type the following line of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">AddMacOSWindowMenu(WindowMenu)</pre>



<p>Run the app and click on the Window item in the main menu bar. You should see that the operating system has added several menu options, similar to the ones displayed in this screenshot (they will vary depending the macOS version the app is running on):</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1686" height="1054" src="https://blog.xojo.com/wp-content/uploads/2024/12/WindowMenu.png" alt="" class="wp-image-14166" srcset="https://blog.xojo.com/wp-content/uploads/2024/12/WindowMenu.png 1686w, https://blog.xojo.com/wp-content/uploads/2024/12/WindowMenu-300x188.png 300w, https://blog.xojo.com/wp-content/uploads/2024/12/WindowMenu-1024x640.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/12/WindowMenu-768x480.png 768w, https://blog.xojo.com/wp-content/uploads/2024/12/WindowMenu-1536x960.png 1536w" sizes="auto, (max-width: 1686px) 100vw, 1686px" /></figure>
</div>


<p>Choose any of the options added and you will see how macOS handles them, without the need to write a line of code in you Xojo project to do it.</p>



<h2 class="wp-block-heading">Localizing the Window Menu</h2>



<p>At this point, the Window menu with the added menu options will look great, but if your app is localized to other languages, then it will be a bit odd to read &#8220;Window&#8221; for the menu (as well as the English text in the added menu items). To improve this experience, let&#8217;s localize the WindowMenu item too!</p>



<p>Let&#8217;s add a new Constant to the &#8220;macOSExtra&#8221; Module and name it &#8220;kWindowName&#8221; setting its default value to &#8220;Window&#8221; and switching on the &#8220;Localized&#8221; field in the Inspector Panel:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="606" height="502" src="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.33.42 p. m.png" alt="" class="wp-image-14167" srcset="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.33.42 p. m.png 606w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.33.42 p. m-300x249.png 300w" sizes="auto, (max-width: 606px) 100vw, 606px" /></figure>
</div>


<p>Then, use the associated Constant Editor to add new entries (in as many as languages you support). In this case we will just add the entries to support both English and Spanish:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="920" height="378" src="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.34.17 p. m.png" alt="" class="wp-image-14168" srcset="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.34.17 p. m.png 920w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.34.17 p. m-300x123.png 300w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.34.17 p. m-768x316.png 768w" sizes="auto, (max-width: 920px) 100vw, 920px" /></figure>
</div>


<p>Next, select the WindowMenu item hanging from the MainMenuBar item in the Navigator, and change the value of the Text property to use the new constant:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="2058" height="738" src="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.44 p. m.png" alt="" class="wp-image-14169" srcset="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.44 p. m.png 2058w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.44 p. m-300x108.png 300w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.44 p. m-1024x367.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.44 p. m-768x275.png 768w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.44 p. m-1536x551.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.44 p. m-2048x734.png 2048w" sizes="auto, (max-width: 2058px) 100vw, 2058px" /></figure>
</div>


<p>Change the macOS Settings &gt; General &gt; Idiom and Region so the Spanish language is the main language. Then run the Xojo project again from the IDE and you will see how the &#8220;Window&#8221; menu entry now reads &#8220;Ventana&#8221;. Moreover, macOS will add the right localizations for the added menu items so they are in Spanish too.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1654" height="1508" src="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.31.27 p. m.png" alt="" class="wp-image-14170" srcset="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.31.27 p. m.png 1654w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.31.27 p. m-300x274.png 300w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.31.27 p. m-1024x934.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.31.27 p. m-768x700.png 768w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.31.27 p. m-1536x1400.png 1536w" sizes="auto, (max-width: 1654px) 100vw, 1654px" /></figure>
</div>

<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1764" height="1104" src="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.04 p. m.png" alt="" class="wp-image-14171" srcset="https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.04 p. m.png 1764w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.04 p. m-300x188.png 300w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.04 p. m-1024x641.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.04 p. m-768x481.png 768w, https://blog.xojo.com/wp-content/uploads/2024/12/Captura-de-pantalla-2024-12-09-a-las-1.37.04 p. m-1536x961.png 1536w" sizes="auto, (max-width: 1764px) 100vw, 1764px" /></figure>
</div>


<h2 class="wp-block-heading">In Brief</h2>



<p>As you have seen, using just a few Declares we have been able to add the expected options for the Window menu to our macOS apps, without the need to write the code in charge of handling them! This doesn&#8217;t just mean more options for your users, it also means your Xojo apps will look and feel better when running on macOS.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Android Design Extensions 3.5 for Xojo 2024r4+</title>
		<link>https://blog.xojo.com/2024/12/10/android-design-extensions-3-5-for-xojo-2024r4/</link>
		
		<dc:creator><![CDATA[Martin T.]]></dc:creator>
		<pubDate>Tue, 10 Dec 2024 16:38:03 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Android Design Extensions]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Declares]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14175</guid>

					<description><![CDATA[With the release of Xojo 2024r4, it’s time to unveil a new version of the Android Design Extensions. The focus of version 3.5 (compatible with&#8230;]]></description>
										<content:encoded><![CDATA[
<p>With the release of Xojo 2024r4, it’s time to unveil a new version of the Android Design Extensions. The focus of version 3.5 (compatible with all Xojo versions starting from 2024r4+) was on code maintenance and introducing exceptions for unsupported API calls, depending on the running Android version. This should make your work as a developer easier.</p>



<p>You can now use the <em>SetBottomAppBarMenuAlignmentModeXC </em>extension method for MobileScreen to set the alignment of the buttons in your MobileScreen.Toolbar.</p>



<p>Additionally, new declares for MobileMessageBox have been added, allowing you to display an icon next to the title as well as next to individual buttons.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="498" height="1024" src="https://blog.xojo.com/wp-content/uploads/2024/12/3C6F953F-1315-4016-8A7B-F2427E7F54BC-498x1024.png" alt="" class="wp-image-14176" srcset="https://blog.xojo.com/wp-content/uploads/2024/12/3C6F953F-1315-4016-8A7B-F2427E7F54BC-498x1024.png 498w, https://blog.xojo.com/wp-content/uploads/2024/12/3C6F953F-1315-4016-8A7B-F2427E7F54BC-146x300.png 146w, https://blog.xojo.com/wp-content/uploads/2024/12/3C6F953F-1315-4016-8A7B-F2427E7F54BC-768x1579.png 768w, https://blog.xojo.com/wp-content/uploads/2024/12/3C6F953F-1315-4016-8A7B-F2427E7F54BC-747x1536.png 747w, https://blog.xojo.com/wp-content/uploads/2024/12/3C6F953F-1315-4016-8A7B-F2427E7F54BC-996x2048.png 996w, https://blog.xojo.com/wp-content/uploads/2024/12/3C6F953F-1315-4016-8A7B-F2427E7F54BC.png 1080w" sizes="auto, (max-width: 498px) 100vw, 498px" /></figure>



<p>Give it a try! More exciting Android features are coming soon. Stay tuned!</p>



<p>Feel free to take a look at the developer repository, create feature requests, and provide feedback on extending this extension library.</p>



<p>I’m happy to receive any voluntary financial support for the work I’ve done so far, which you are welcome to <a href="https://www.paypal.com/paypalme/MTrippensee">share here</a>. You can download the project with many examples at <a href="https://github.com/XojoGermany/AndroidDesignExtensions">https://github.com/XojoGermany/AndroidDesignExtensions</a>.</p>



<p>Happy coding.</p>



<p><em>Martin T. is a Xojo MVP and has been very involved in testing Android support.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Android Design Extensions 3.0 for Xojo 2024r3+</title>
		<link>https://blog.xojo.com/2024/10/01/android-design-extensions-3-0-for-xojo-2024r3/</link>
		
		<dc:creator><![CDATA[Martin T.]]></dc:creator>
		<pubDate>Tue, 01 Oct 2024 15:55:28 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Android Design Extensions]]></category>
		<category><![CDATA[Declares]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13827</guid>

					<description><![CDATA[Version 2024r3 of Xojo has just been released. So it&#8217;s time for an update of the Android Design Extension 3.0. This version works from version&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Version 2024r3 of Xojo has just been released. So it&#8217;s time for an update of the Android Design Extension 3.0. This version works from version 2024r3+, because in this version Xojo has revised the Declare Framework enormously and Declares now work in Android projects in the same way as in the other targets. This means that we are no longer bound to the Object Declares introduced in Android. So what are the new features of the Android Design Extensions 3.0?</p>



<p>From now on, Buttons and TextFields can use Xojo Pictures directly and you no longer need to save images that you want to use. Take a look at the “Deprecations Version 3.0” section in the Read me to find out which methods are deprecated in this regard.</p>



<h2 class="wp-block-heading">Now it&#8217;s getting colorful!</h2>



<p>In this version, support for over 180 system colors has been added, depending on which Android version your app is running on. The sample app has a new page with the system colors. It gives you a good overview. Using these colors can help you to design your apps according to the Material Design Guidelines in light &amp; dark mode.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="498" height="1024" src="https://blog.xojo.com/wp-content/uploads/2024/10/android-screenshots-1-498x1024.png" alt="" class="wp-image-13831" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/android-screenshots-1-498x1024.png 498w, https://blog.xojo.com/wp-content/uploads/2024/10/android-screenshots-1-146x300.png 146w, https://blog.xojo.com/wp-content/uploads/2024/10/android-screenshots-1-768x1579.png 768w, https://blog.xojo.com/wp-content/uploads/2024/10/android-screenshots-1-747x1536.png 747w, https://blog.xojo.com/wp-content/uploads/2024/10/android-screenshots-1-996x2048.png 996w, https://blog.xojo.com/wp-content/uploads/2024/10/android-screenshots-1.png 1080w" sizes="auto, (max-width: 498px) 100vw, 498px" /></figure>



<p>Picture objects and the content of a MobileHTMLViewer can now also be printed.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="996" height="1024" src="https://blog.xojo.com/wp-content/uploads/2024/10/android-made-with-xojo-996x1024.png" alt="" class="wp-image-13829" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/android-made-with-xojo-996x1024.png 996w, https://blog.xojo.com/wp-content/uploads/2024/10/android-made-with-xojo-292x300.png 292w, https://blog.xojo.com/wp-content/uploads/2024/10/android-made-with-xojo-768x789.png 768w, https://blog.xojo.com/wp-content/uploads/2024/10/android-made-with-xojo-1494x1536.png 1494w, https://blog.xojo.com/wp-content/uploads/2024/10/android-made-with-xojo-1993x2048.png 1993w" sizes="auto, (max-width: 996px) 100vw, 996px" /></figure>



<p>We are familiar with the DrawInto method from the Desktop Framework, which draws DesktopUIControls and DesktopWindows into a Graphics object. These methods have now also been added for MobileUIControls and MobileScreen.</p>



<p>The title bar and the NavigationBar can now also be highlighted in color. The font, color and alignment of the NavigationBar can also be changed.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="498" height="1024" src="https://blog.xojo.com/wp-content/uploads/2024/10/android-019EFFD9-4A4A-48A1-A477-B1948F7B9D58-498x1024.png" alt="" class="wp-image-13832" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/android-019EFFD9-4A4A-48A1-A477-B1948F7B9D58-498x1024.png 498w, https://blog.xojo.com/wp-content/uploads/2024/10/android-019EFFD9-4A4A-48A1-A477-B1948F7B9D58-146x300.png 146w, https://blog.xojo.com/wp-content/uploads/2024/10/android-019EFFD9-4A4A-48A1-A477-B1948F7B9D58-768x1579.png 768w, https://blog.xojo.com/wp-content/uploads/2024/10/android-019EFFD9-4A4A-48A1-A477-B1948F7B9D58-747x1536.png 747w, https://blog.xojo.com/wp-content/uploads/2024/10/android-019EFFD9-4A4A-48A1-A477-B1948F7B9D58-996x2048.png 996w, https://blog.xojo.com/wp-content/uploads/2024/10/android-019EFFD9-4A4A-48A1-A477-B1948F7B9D58.png 1080w" sizes="auto, (max-width: 498px) 100vw, 498px" /></figure>



<h2 class="wp-block-heading">How? What? Where?</h2>



<p>The system paths for various folders (SpecialFolder) have also been added.</p>



<p>Almost all modules have been updated according to the new Declare data types. The example app has also been further optimized for dark mode in this version.</p>



<p>The new Declare capabilities in Xojo 2024r3 are another huge step forward. You now have the possibility to declare in almost every Android API without having to go through an Android library.</p>



<p>Feel free to take a look at the developer repository, create feature requests, and provide feedback on extending this extension library.</p>



<p>I’m happy to receive any voluntary financial support for the work I’ve done so far, which you are welcome to <a href="https://www.paypal.com/paypalme/MTrippensee" target="_blank" rel="noreferrer noopener">share here</a>. You can download the project with many examples at <a href="https://github.com/XojoGermany/AndroidDesignExtensions" target="_blank" rel="noreferrer noopener">https://github.com/XojoGermany/AndroidDesignExtensions</a>.</p>



<p>Happy coding.</p>



<p><em>Martin T. is a Xojo MVP and has been very involved in testing Android support.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Android Declare and Library Enhancements</title>
		<link>https://blog.xojo.com/2024/10/01/android-declare-and-library-enhancements/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 01 Oct 2024 15:30:45 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[2024r3]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13442</guid>

					<description><![CDATA[There have been several enhancements to Declare and Kotlin Library support in Xojo 2024 Release 3 which, along with previous improvements, should allow you to&#8230;]]></description>
										<content:encoded><![CDATA[
<p>There have been several enhancements to Declare and Kotlin Library support in Xojo 2024 Release 3 which, along with previous improvements, should allow you to interface your Android projects with more from the native ecosystem.</p>



<p>This post describes the things you can do with Declares and Libraries with Android projects.</p>



<h2 class="wp-block-heading">Declare Integer Types</h2>



<p>The size-specific Integer types are now precise when used with Declares. The mappings are as follows:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td><strong>Xojo Type</strong></td><td><strong>Kotlin Type</strong></td></tr><tr><td>Int8, Byte</td><td>Byte</td></tr><tr><td>UInt8</td><td>UByte</td></tr><tr><td>Int16</td><td>Short</td></tr><tr><td>UInt16</td><td>UShort</td></tr><tr><td>Int32</td><td>Int</td></tr><tr><td>UInt32</td><td>UInt</td></tr><tr><td>Integer, Int64</td><td>Long</td></tr><tr><td>UInteger, UInt64</td><td>ULong</td></tr></tbody></table></figure>



<p>When mapping to Android API functions or Library functions, be sure to use the correct Xojo type that matches what is expected on Android. By far you will use Int32 and Integer.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>If you previously created Declares, you will likely need to change usage of Integer to Int32 as the mapping for that have changed compared to prior versions.</p>
</blockquote>



<h2 class="wp-block-heading">Nullable Types</h2>



<p>Xojo object variables (also properties, parameters and return values) can be Nil. With Kotlin, the default is that these things cannot be null (the equivalent of Nil). To ensure that you don’t get compile errors with your parameters, declare them as nullable in Kotlin by appending the “?” to the end of the type name.</p>



<h2 class="wp-block-heading">Application Context</h2>



<p>Many Android APIs require the application context. This is not available in a Library so it has to be supplied by the app itself. There is a property for this:</p>



<pre class="wp-block-code"><code>MobileApplication.AndroidContextHandle As Ptr</code></pre>



<p>You can pass this value to a function on the Library that then either saves it or uses it directly.</p>



<h2 class="wp-block-heading">Using Ptr</h2>



<p>Xojo uses the Ptr type to interface with Declares, however Kotlin does not have a Ptr type. Instead the Any type is used with Kotlin. This means that if you are passing something that is a Ptr to Kotlin (such as the app context above), your library function declaration should use “Any?” as the type of the parameter.</p>



<p>In your function, cast the parameter to the actual type you want. The same rule applies to return values. If the return value in the Declare is a Ptr, then in Kotlin the function declaration should be “Any?”.</p>



<p>You can also use Ptr with API calls to save object references as described below.</p>



<h2 class="wp-block-heading">Library Permissions</h2>



<p>Depending on the API you are using, you may need to add permissions to the app manifest.xml for the Library. These permissions also need to be applied to the main app. This can be done using the Advanced tab of the Android Build Settings. There you’ll find the Permissions property in the Inspector where you can add one Permission per line.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Previous versions let you separate permissions by spaces or commas. Going forward, each permission must be on its own line. Empty lines are ignored.</p>
</blockquote>



<p>There you can add the permission constants that are required by your Library. In addition, you can follow the constant with additional attributes and they will also be applied to the app’s manifest file.</p>



<p>For example, to include the android:maxSdkVersion attribute with the BLUETOOTH permission:</p>



<pre class="wp-block-code"><code>android.permission.BLUETOOTH android:maxSdkVersion="30"</code></pre>



<h2 class="wp-block-heading">Library Dependencies</h2>



<p>Similarly to permissions, your Library may make use of additional dependencies, which could even be other Libraries. These are added to the build.gradle file for the Library, but also need to be included in the main app.</p>



<p>You can add these dependencies using the Dependencies property on the Advanced Android Build Settings.</p>



<h2 class="wp-block-heading">Creating Objects</h2>



<p>Previous versions of Xojo only let you call Companion (essentially shared) methods on Library classes. Now you can also work with class instances and call instance methods. This gives you even better control and ability to interface with Android APIs.</p>



<p>To create an object, your Library class should have a factory method on the Companion that returns a new instance. It is clearest to use create() as this method name.</p>



<p>In Xojo you create a Declare to this create() method and call it, saving the result in a Ptr.</p>



<pre class="wp-block-code"><code>Declare Function create Lib "com.example.utility.counter" () As Ptr<br>Var counter As Ptr = create</code></pre>



<p>Instead of using a shared factory method, you can also call the Class constructor using this syntax:</p>



<pre class="wp-block-code"><code>Declare Function counter Lib "com.example.utility.counter" () As Ptr</code></pre>



<p>Because the function name has the same name as the class itself, this will call the constructor of the class.</p>



<p>When you want to call a method on the instance, you pass the instance as a Ptr. First, Declare to the method adding “.instance” to the library location to indicate you are calling a class instance.</p>



<pre class="wp-block-code"><code>Declare Function increment Lib "com.example.utility.counter.instance" (ref As Ptr) As Integer</code></pre>



<p>Then you can call the method and save its value.</p>



<pre class="wp-block-code"><code>Var count As Integer = increment(counter)</code></pre>



<p>The reference as the Ptr must be the first parameter passed in the Declare. Follow it with other parameters as usual.</p>



<p>You can also call instance methods directly in the Android API in this manner.</p>



<h2 class="wp-block-heading">Method Callbacks</h2>



<p>There are Android APIs that use callbacks to methods that you provide. In Xojo these methods are Delegates and are methods that you supply using <a href="https://documentation.xojo.com/api/language/addressof.html#addressof" target="_blank" rel="noreferrer noopener">AddressOf</a>. It is very important that the signature of this method exactly matches what the callback expects which means you’ll be limited to just the Boolean and Ptr types.</p>



<p>If you want to use an API that uses its own callbacks, you’ll be better served by creating a Library and having the API do the callback to your own Library methods, which you can then call back to your Xojo methods.</p>



<p>You can pass the reference to the Xojo method using AddressOf like this:</p>



<pre class="wp-block-code"><code>Var cb As Ptr = AddressOf TestCallback<br>Declare Sub xojocallback Lib "com.example.utility.callback" (cb As Ptr)<br>xojocallback(cb)</code></pre>



<p>The Xojo method can only use parameter types of Boolean and Ptr. It looks like this:</p>



<pre class="wp-block-code"><code>Public Sub TestCallback(b As Boolean, i As Ptr, s As Ptr)</code></pre>



<p>In the Kotlin library you have to cast the incoming parameter to a function reference. This is a two-step process where you verify the function has the correct number of parameters and then you cast it to the specific parameter types. Sample code:</p>



<pre class="wp-block-code"><code>if (cb is Function3&lt;*, *, *, *&gt;) {
    try {
         (cb as Function3&lt;Boolean, Long, String, Unit&gt;).invoke(true, 42, "Hello")
         println("Sent callback to Xojo")
    } catch (e: ClassCastException) {
         println("Casting failed: ${e.message}")
    }
}</code></pre>



<p>The &#8220;Function3&#8221; indicates a function with 3 parameters (the last &#8220;*&#8221; indicates the return type), but you can change that as needed using Function1, Function2, etc. You can pass anything back through a Ptr type, but the Xojo code has to convert them using Ptr methods so you should not change the types of the values you send back to be different than what your Xojo code expects.</p>



<h2 class="wp-block-heading">Object Declares</h2>



<p>Object Declares are not new, but for completeness are described here. Essentially an Object Declare uses special syntax to Declare to a UI control.</p>



<p>The typical way to use an Object Declare is by adding an Extends method to a Module. For example, an extension method to allow MobileButton to change its colors could look like this:</p>



<pre class="wp-block-code"><code>SetBackColor(Extends ctrl As MobileButton, c As Color)</code></pre>



<p>The Object Declare looks like this:</p>



<pre class="wp-block-code xojo"><code>Declare Sub setBackgroundColor Lib "Object:ctrl:MobileButton" (myColor As Int32)
setBackgroundColor(c.ToInteger)</code></pre>



<p>Breaking this down, we’re calling the setBackgroundColor function. The Lib denotes this new type of Object declare: an Object, separated by a colon, the Xojo name of the object (in this case, our “ctrl” parameter), followed by another colon, and the Xojo type of the object.</p>



<h2 class="wp-block-heading">Kotlin Declares</h2>



<p>You can use the Android-specific  &#8220;Kotlin&#8221; Declare designation to indicates that what is specified in the Alias section of the Declare should be used as is. This is particularly helpful when you want to cast Ptr values to a specific type for use with OS APIs.</p>



<p>This code gets a ColorStateList object for a Xojo Color value:</p>



<pre class="wp-block-code"><code>Var c As Color = Color.Blue

Declare Function valueOf Lib "android.content.res.ColorStateList:Kotlin" Alias _
"android.content.res.ColorStateList.valueOf(android.graphics.Color.argb(alpha.toInt(), r.toInt(), g.toInt(), b.toInt()))" _
(alpha As Int32, r As Int32, g As Int32, b As Int32) As Ptr

Var csl As Ptr = valueOf(255 - c.Alpha, c.Red, c.Green, c.Blue)</code></pre>



<p>This code can then be used to call <a href="https://developer.android.com/reference/com/google/android/material/button/MaterialButton#setStrokeColor(android.content.res.ColorStateList)" target="_blank" rel="noreferrer noopener">setStrokeColor</a> on a MobileButton:</p>



<pre class="wp-block-code"><code>Declare Sub import Lib "android.content.res.ColorStateList:Import" // Imports the ColorStateList class

Declare Sub setStrokeColor Lib "Object:ctrl:MobileDateTimePicker:Kotlin" Alias "setStrokeColor(strokecolor as ColorStateList)" (strokeColor As Ptr)
setStrokeColor(csl)</code></pre>



<p>As you can see, in the Alias is the Kotlin method call that casts the incoming Ptr value to a ColorStateList.</p>



<h3 class="wp-block-heading">Import</h3>



<p>Note the &#8220;import&#8221; declare in the code snippet above. This is also specific to Android. This Declare indicates that a specific class should be imported so that it can be used for casting purposes. If you left off that import, then the cast to ColorStateList would cause a compile error because ColorStateList would not be known.</p>



<p>You only need to import a specific class once. After you&#8217;ve done so it can be referenced by any other Declare, even ones in different methods.</p>



<p>The use of an import Declare is optional and is meant to simply the Kotlin method call code in the Alias. Instead of using import you can specify the full class path in the cast like this:</p>



<pre class="wp-block-code xojo"><code>Declare Sub setStrokeColor Lib "Object:ctrl:MobileDateTimePicker:Kotlin" Alias "setStrokeColor(strokecolor as android.content.res.ColorStateList)" (strokeColor As Ptr)
setStrokeColor(csl)</code></pre>



<h2 class="wp-block-heading">Handles</h2>



<p>Many classes in the framework now have Handle properties (or methods) which you can use with various Declare techniques described above. These include: FolderItem, Font, GraphicsPath, Locale, TimeZone, Graphics, Picture. In addition, the mobile controls have Handle properties that can serve as an alternative for an Object Declare.</p>



<h2 class="wp-block-heading">Sample Project</h2>



<p>You can download the sample project that demonstrates a library and some of the concepts described above. You can use this as a template or starting point for creating your own libraries or Declares.</p>



<p><a href="https://files.xojo.com/BlogExamples/UtilityLibrary2.zip" target="_blank" rel="noreferrer noopener">Sample Utility Library Project</a></p>



<p>You might also want to take a look at the <a href="https://github.com/XojoGermany/AndroidDesignExtensions" target="_blank" rel="noreferrer noopener">Android Design Extensions open source project</a>, which has hundreds of Declares that can enhance your Android apps.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2023/08/15/creating-an-android-library-with-kotlin-for-use-with-xojo/" target="_blank" rel="noreferrer noopener">Android Libraries blog post</a></li>



<li><a href="https://blog.xojo.com/2023/08/09/android-declares/" target="_blank" rel="noreferrer noopener">Android Declares blog post</a></li>
</ul>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Android Design Extensions 2.5 for Xojo 2024r1 +</title>
		<link>https://blog.xojo.com/2024/03/26/android-design-extensions-2-5-for-xojo-2024r1/</link>
		
		<dc:creator><![CDATA[Martin T.]]></dc:creator>
		<pubDate>Tue, 26 Mar 2024 15:40:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[2024r1]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12818</guid>

					<description><![CDATA[The first Xojo version in 2024 is ready and so it's time again for an update of the Android Design Extensions, which are now available in version 2.5. This version runs for all Xojo versions from 2024r1 upwards and offers over 70 new declares. The focus of this release was on the integration of pictures in controls, such as MobileButton, MobileDateTimePicker, MobileTextFields, MobileSlider etc.]]></description>
										<content:encoded><![CDATA[
<p>The first Xojo version in 2024 is ready and so it&#8217;s time again for an update of the Android Design Extensions, which are now available in version 2.5. This version runs for all Xojo versions from 2024r1 upwards and offers over 70 new declares.</p>



<p>The focus of this release was on the integration of pictures in controls, such as MobileButton, MobileDateTimePicker, MobileTextFields, MobileSlider etc.</p>



<p>Let&#8217;s take a look at some new possibilities using examples.</p>



<h2 class="wp-block-heading">Create a MobileButton with a Picture</h2>



<p>This is a feature that is in demand in Xojo Issue Tracker and has not yet found its way into the Android framework. So let&#8217;s just do it ourselves with the help of the Android Design Extensions.</p>



<p>Create a new Android project. Now copy the Android Design Extensions folder into the project or drag and drop it into the Navigator. Now select Screen1 in the Navigator and add a MobileButton &#8211; Button1 &#8211; and give it the Opening event. Add the following code to the Opening event: </p>



<pre id="xojo" class="wp-block-code"><code>Me.SetIconXC(SaveSystemImage("camera")) 
Me.SetIconGravityXC(IconGravity.TextStart)</code></pre>



<p><em>SaveSystemImage </em>is an extension method that returns a <em>FolderItem </em>and saves a <em>Picture.SystemImage </em>with the specified name (here „camera“) in the Documents folder. Why? Xojo Declares do not support Picture as a data type and therefore we have to take the detour and save images once in order to load them into controls via the file path.</p>



<p>You can of course also use any other image and are not restricted to Picture.SystemImage. All Android Design Extensions extension methods that have to do with the display of pictures are prepared for this and expect a FolderItem as a parameter, which must of course be a picture (PNG, JPEG etc.).</p>



<p><em>SetIconGravityXC </em>ensures that the Picture is displayed in front of the button text. And that&#8217;s all there is to it. Execute the project and you have a button with an image.</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="531" src="https://blog.xojo.com/wp-content/uploads/2024/03/untitled-1024x531.png" alt="" class="wp-image-12821" srcset="https://blog.xojo.com/wp-content/uploads/2024/03/untitled-1024x531.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/03/untitled-300x156.png 300w, https://blog.xojo.com/wp-content/uploads/2024/03/untitled-768x398.png 768w, https://blog.xojo.com/wp-content/uploads/2024/03/untitled.png 1080w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p><strong>Tip: </strong>If you create a MobileButton subclass, you can cache the FolderItem via Static to create the image file only once. Of course, this only applies to the fact that all button instances of this subclass should always display the same image.</p>



<p>To see how to add an image to a MobileScreen, MobileSlider or MobileSwitch, simply take a look at the Android Design Extensions sample app.</p>



<h2 class="wp-block-heading">TabPanel Badge Extension</h2>



<p>MobileTabPanel tabs now also support text badges. How is it done?</p>



<p>Add a MobileTabPanel &#8211; TabPanel1 &#8211; to your project and add the Opening event to it with the following code: </p>



<pre class="wp-block-code"><code>Me.SetBadgeTextAtXC(0, "Exclusive")</code></pre>



<p>And that&#8217;s all there is to it. The result is as follows:</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="474" src="https://blog.xojo.com/wp-content/uploads/2024/03/jewlery-1024x474.png" alt="" class="wp-image-12820" srcset="https://blog.xojo.com/wp-content/uploads/2024/03/jewlery-1024x474.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/03/jewlery-300x139.png 300w, https://blog.xojo.com/wp-content/uploads/2024/03/jewlery-768x356.png 768w, https://blog.xojo.com/wp-content/uploads/2024/03/jewlery.png 1080w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>There are other MobileTabPanel extension methods with which you can customize the badges (color, position, etc.). Give it a try!</p>



<h2 class="wp-block-heading">TextFields on a New Level</h2>



<p>TextFields can also be enhanced with the new Android Design Extensions version.</p>



<p>The <em>SetBoxCornerFamilyXC </em>call now offers the option of choosing whether you want rounded or flattened corners. You can also use <em>SetCursorColorXC </em>to define the color of the cursor for each individual TextField.</p>



<p>TextFields can now also have leading or trailing icons. The helper methods for this are <em>SetStartIconXC </em>and <em>SetEndIconXC</em>, which in turn expect a FolderItem (Picture) as a parameter.</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="289" src="https://blog.xojo.com/wp-content/uploads/2024/03/defaut-text-1024x289.png" alt="" class="wp-image-12819" srcset="https://blog.xojo.com/wp-content/uploads/2024/03/defaut-text-1024x289.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/03/defaut-text-300x85.png 300w, https://blog.xojo.com/wp-content/uploads/2024/03/defaut-text-768x217.png 768w, https://blog.xojo.com/wp-content/uploads/2024/03/defaut-text.png 1080w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>There are many other new declares. Have a look here too.</p>



<p>Feel free to take a look at the developer repository, create feature requests, and provide feedback on extending this extension library.</p>



<p>I’m happy to receive any voluntary financial support for the work I’ve done so far, which you are welcome to <a href="https://www.paypal.com/paypalme/MTrippensee">share</a> here. You can download the project with many examples <a href="https://github.com/XojoGermany/AndroidDesignExtensions">here</a>.</p>



<p>Happy Coding.</p>



<p><em>Martin T. is a Xojo MVP and has been very involved in testing Android support.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Android Improvements in Xojo 2023r3</title>
		<link>https://blog.xojo.com/2023/10/10/android-improvements-in-xojo-2023r3/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 10 Oct 2023 13:30:44 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2023r3]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12123</guid>

					<description><![CDATA[Android remains in Beta, but there have been many fixes and improvements in Xojo 2023r3 and I'd like to highlight a few including: more support for dark mode, additions to MobileTextField, a Destination property, a HasBackButton property, MobilePopupMenu, enhancements to MobileHTMLViewer, support for running JavaScript, the new Kotlin Declare and more detailed in this post.]]></description>
										<content:encoded><![CDATA[
<p>Android remains in Beta, but there have been many fixes and improvements in Xojo 2023r3 and I&#8217;d like to highlight a few including: more support for dark mode, additions to MobileTextField, a Destination property, a HasBackButton property, MobilePopupMenu, enhancements to MobileHTMLViewer, support for running JavaScript, the new Kotlin Declare and more.</p>



<p>Although Xojo for Android does not yet have full dark mode support, things continue to head in that direction. Previously your app would adjust its UI for light/dark if the Support Dark Mode property was turned on in the Android Build Settings. Starting in Xojo 2023r3, Color.TextColor and Color.FillColor also adjust their values when run in light mode or dark mode, making it easier for your custom drawing to also adapt.</p>



<p>MobileTextField gets a couple new additions. The ReturnPressed event is now called when, as the name suggests, return is pressed. The AllowSpellChecking property is now also available for MobileTextField and MobileTextArea.</p>



<p>In the Shared Build Settings Inspector there is now a Destination property as there is with other platforms.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="377" height="434" src="https://blog.xojo.com/wp-content/uploads/2023/10/image.png" alt="" class="wp-image-12124" srcset="https://blog.xojo.com/wp-content/uploads/2023/10/image.png 377w, https://blog.xojo.com/wp-content/uploads/2023/10/image-261x300.png 261w" sizes="auto, (max-width: 377px) 100vw, 377px" /></figure>



<p>Many Android devices have physical back buttons and all let you turn on global software controls that have a back button, but sometimes you want to have the back button clearly shown on the navigation toolbar. With Xojo 2023r3, the new HasBackButton property of MobileScreen can show a back button on the navigation toolbar.</p>



<p>To make it easier to write code that is applicable to both iOS and Android, but not other platforms, there is a new <a href="https://documentation.xojo.com/api/compiler_directives/targetmobile.html">TargetMobile</a> constant available for conditional compilation.</p>



<p><a href="https://documentation.xojo.com/api/user_interface/mobile/mobilepopupmenu.html">MobilePopupMenu</a> is an all-new control for Android that makes it possible to simplify some of your user interfaces. It works similarly to a PopupMenu on Desktop or Web: when the user taps this control a list of items appears and they can choose one.</p>



<p>On the Advanced tab of the Android Build Settings there is a new Manifest section with a Permissions property. Here you can specify the names of <a href="https://developer.android.com/reference/android/Manifest.permission">Android permission constants</a> that are needed by Declares or libraries. They are added to the AndroidManifest.xml file when the app is run/built.</p>



<p>MobileHTMLViewer got several enhancements. It now has various processing events, including: DocumentBegin, DocumentComplete, CancelLoad, Error, NewWindow, DocumentProgressChanged and TitleChanged.</p>



<p>And there is now support for running JavaScript using the ExecuteJavaScript method along with the JavaScriptResult and JavaScriptRequest events. ExecuteJavaScript is asynchronous and results appear in the JavaScriptResult event. To call the JavaScriptRequest event, use xojo.execute() in the JavaScript code. A method name and up to 5 parameters can be passed back to Xojo. <a href="https://documentation.xojo.com/api/user_interface/mobile/mobilehtmlviewer.html#mobilehtmlviewer-javascriptrequest">Learn more</a> in the Xojo Programming Documentation.</p>



<p>The last thing I want to highlight is the new Kotlin <a href="https://documentation.xojo.com/api/language/declare.html">Declare</a>. For advanced users, this adds the ability to create Android declares that can pass untouched calls via Alias (with the exception of required type/object handling) to the Kotlin compilation step. This is done by specifying Lib &#8220;Kotlin&#8221; or adding &#8220;:Kotlin&#8221; to the end of Lib. Here are a couple examples of what this can look like:</p>



<pre class="wp-block-code"><code>Declare Function AndroidVersion Lib "Kotlin" Alias "android.os.Build.VERSION.RELEASE" As CString</code></pre>



<pre class="wp-block-code"><code>Declare Sub findAllAsync Lib "Object:ctrl:MobileHTMLViewer:Kotlin" Alias "findAllAsync(myfind.toString())" (myFind As CString)</code></pre>



<p>Of course there were many bug fixes as well. Be sure to check out the <a href="https://documentation.xojo.com/versions/2023r3/resources/release_notes/2023r3.html">full release notes</a> for all the details.</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Android Design Extensions 1.5 for Xojo 2023r3</title>
		<link>https://blog.xojo.com/2023/10/10/android-design-extensions-1-5-for-xojo-2023r3/</link>
		
		<dc:creator><![CDATA[Martin T.]]></dc:creator>
		<pubDate>Tue, 10 Oct 2023 13:30:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[2023r3]]></category>
		<category><![CDATA[Android Design Extensions]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12201</guid>

					<description><![CDATA[The Android Design Extensions 1.5 are now available. This version works with Xojo 2023r3 and brings about 90 new extensions.]]></description>
										<content:encoded><![CDATA[
<p>The Android Design Extensions 1.5 are now available. This version works with Xojo 2023r3<strong> </strong>and brings about 90 new extensions:</p>



<ul class="wp-block-list">
<li>Declares for the new MobilePopupMenu </li>



<li>Declares for MobileMoviePlayer</li>



<li>Extensions for all MobileUIControl subclasses </li>



<li>New extensions for AndroidMobileTable</li>



<li>New extensions for MobileScrollableArea </li>



<li>New extensions for MobileSwitch</li>



<li>New extensions for MobileTabPanel</li>



<li>New extensions for MobileTextArea</li>



<li>New extensions for MobileTextField</li>
</ul>



<h3 class="wp-block-heading"><strong>Use MobilePopupMenu to Display it in Other Controls</strong></h3>



<p>The new MobilePopupMenu is a nice new addition to Xojo&#8217;s Android control library. Wouldn&#8217;t it be nice to display the popup menu when clicking on a Button or Canvas as well? With the Android Design Extensions you can achieve this.</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="517" height="1024" src="https://blog.xojo.com/wp-content/uploads/2023/10/01A34D47-6DA9-40F8-BA71-5B51781BA373-1-517x1024.png" alt="" class="wp-image-12203" srcset="https://blog.xojo.com/wp-content/uploads/2023/10/01A34D47-6DA9-40F8-BA71-5B51781BA373-1-517x1024.png 517w, https://blog.xojo.com/wp-content/uploads/2023/10/01A34D47-6DA9-40F8-BA71-5B51781BA373-1-151x300.png 151w, https://blog.xojo.com/wp-content/uploads/2023/10/01A34D47-6DA9-40F8-BA71-5B51781BA373-1-768x1521.png 768w, https://blog.xojo.com/wp-content/uploads/2023/10/01A34D47-6DA9-40F8-BA71-5B51781BA373-1-775x1536.png 775w, https://blog.xojo.com/wp-content/uploads/2023/10/01A34D47-6DA9-40F8-BA71-5B51781BA373-1.png 846w" sizes="auto, (max-width: 517px) 100vw, 517px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="498" height="1024" src="https://blog.xojo.com/wp-content/uploads/2023/10/51450EFA-BB92-4443-9196-2AF4D3F68D71-498x1024.png" alt="" class="wp-image-12204" style="width:425px;height:874px" srcset="https://blog.xojo.com/wp-content/uploads/2023/10/51450EFA-BB92-4443-9196-2AF4D3F68D71-498x1024.png 498w, https://blog.xojo.com/wp-content/uploads/2023/10/51450EFA-BB92-4443-9196-2AF4D3F68D71-146x300.png 146w, https://blog.xojo.com/wp-content/uploads/2023/10/51450EFA-BB92-4443-9196-2AF4D3F68D71-768x1579.png 768w, https://blog.xojo.com/wp-content/uploads/2023/10/51450EFA-BB92-4443-9196-2AF4D3F68D71-747x1536.png 747w, https://blog.xojo.com/wp-content/uploads/2023/10/51450EFA-BB92-4443-9196-2AF4D3F68D71-996x2048.png 996w, https://blog.xojo.com/wp-content/uploads/2023/10/51450EFA-BB92-4443-9196-2AF4D3F68D71.png 1080w" sizes="auto, (max-width: 498px) 100vw, 498px" /></figure>
</div>
</div>



<ol class="wp-block-list">
<li>Create a new Android project</li>



<li>Import the Android Design Extension<strong> </strong>folder into your project</li>



<li>Add a MobilePopupMenu<strong> </strong>(<em>PopupMenu1</em>) from the library to <em>Screen1</em></li>



<li>Add some entries to the <em>PopupMenu1 </em>in the Inspector in the InitialValue<strong> </strong>section (say &#8220;Apple&#8221;, &#8220;Banana&#8221;, &#8220;Peach&#8221;)</li>



<li>Set the Visible<strong> </strong>property of the <em>PopupMenu1 </em>to <code>False</code></li>



<li>Add a MobileButton<strong> </strong>(<em>Button1</em>) from the library to <em>Screen1 </em>and place it over the &#8220;invisible&#8221; <em>PopupMenu1</em></li>



<li>Add the Pressed-Event to <em>Button1</em> with the following code:</li>
</ol>



<pre id="Xojo" class="wp-block-code"><code>Call PopupMenu1.PerformClickXC</code></pre>



<p>8. Add the SelectionChanged-Event to the <em>PopupMenu1 </em>with the following code: </p>



<pre id="Xojo" class="wp-block-code"><code>Button1.Caption = Me.SelectedRowText</code></pre>



<p>9. Run your project by clicking Run.</p>



<p>You can use this technique with any control that you want to have a popup menu. For example, in a Canvas you would use the PointerDown-Event.</p>



<p>Feel free to take a look at the developer repository, create feature requests, and provide feedback on extending this extension library.</p>



<p>I’m happy to receive any voluntary financial support for the work I’ve done so far, which you are welcome to share <a href="https://paypal.me/MTrippensee" data-type="link" data-id="https://paypal.me/MTrippensee">here</a>. You can download the project with many examples <a href="https://github.com/XojoGermany/AndroidDesignExtensions" data-type="link" data-id="https://github.com/XojoGermany/AndroidDesignExtensions">here</a>. </p>



<p>Happy Coding.</p>



<p><em>Martin T. is a Xojo MVP and has been very involved in testing Android support.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Creating an Android Library with Kotlin for use with Xojo</title>
		<link>https://blog.xojo.com/2023/08/15/creating-an-android-library-with-kotlin-for-use-with-xojo/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 15 Aug 2023 20:11:14 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11913</guid>

					<description><![CDATA[In this first beta release of Android, there is some simple support for creating Android libraries and calling their methods from Xojo code. The Android libraries have to be written in Kotlin and compiled as AAR library files. Xojo code can call into the library using Declares.]]></description>
										<content:encoded><![CDATA[
<p>In this first beta release of Android, there is some simple support for creating Android libraries and calling their methods from Xojo code. The Android libraries have to be written in Kotlin and compiled as AAR library files. Xojo code can call into the library using Declares.</p>



<p>To create an Android library you will need to use Android Studio, which you should already have installed as its compiler toolchain and SDK are required by Xojo.</p>



<p>Create a New Android project (File-&gt;New-&gt;New Project), choosing “No Activity” from the Phone and Tablet section.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-1024x800.png" alt="" class="wp-image-11914" style="width:623px;height:487px" width="623" height="487" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-1024x800.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-300x234.png 300w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-768x600.png 768w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-1536x1201.png 1536w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic.png 2024w" sizes="auto, (max-width: 623px) 100vw, 623px" /></figure>



<p>You should be sure to choose Kotlin as the language and the Minimum SDK should be 26 to match what Xojo uses. For this example, I’ve named the project “LibraryTest”.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-1-1024x800.png" alt="" class="wp-image-11916" style="width:634px;height:495px" width="634" height="495" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-1-1024x800.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-1-300x234.png 300w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-1-768x600.png 768w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-1-1536x1201.png 1536w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-1.png 2024w" sizes="auto, (max-width: 634px) 100vw, 634px" /></figure>



<p>In this project, add a module (File-&gt;New-&gt;New Module), choosing the “Android Library” template. Here you can name your library, choose the language, etc. Again, stick with Kotlin.</p>



<p>I’m naming the library “utility” so that it can contain a random collection of things.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-3-1024x776.png" alt="" class="wp-image-11917" style="width:656px;height:497px" width="656" height="497" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-3-1024x776.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-3-300x227.png 300w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-3-768x582.png 768w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-3-1536x1163.png 1536w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-3.png 1682w" sizes="auto, (max-width: 656px) 100vw, 656px" /></figure>



<p>In the Android Studio navigator, expand the utility library and then the java folder. Yes, it is weird that Kotlin code is in a Java folder, but a lot about Android Studio is weird to me.</p>



<p>Right-click on “com.example.utility” and select New-&gt;Kotlin Class/File. In the selector, choose “Class” and type the name of the class as “regex” and press return. In this class will be a method to do some simple regex pattern matching.</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-4.png" alt="" class="wp-image-11918" style="width:276px;height:211px" width="276" height="211" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-4.png 678w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-4-300x229.png 300w" sizes="auto, (max-width: 276px) 100vw, 276px" /></figure>



<p>This creates an empty class:</p>



<pre id="xojo" class="wp-block-code"><code><code>package<strong> </strong>com.example.utility
class regex {

}</code></code></pre>



<p>Currently Xojo can only talk to methods in the companion class. These methods are similar to Shared methods in Xojo and work without creating a specific class instance.</p>



<p>In the class, add the companion object so that it looks like this:</p>



<pre id="Xojo" class="wp-block-code"><code><code>package com.example.utility

class regex {

    companion object {

    }

}</code></code></pre>



<p>Inside the companion object, add a method that will do simple regex pattern matching. Your code now looks like this:</p>



<pre id="Xojo" class="wp-block-code"><code><code>package com.example.utility

class regex {

    companion object {

        fun regexmatch(regex: String, text: String): Boolean {

            // Use the regex pattern
            val pattern = Regex(regex)

            // Returns true if it matches, false if it does not.
            return pattern.matches(text)
        }

    }

}</code></code></pre>



<p>The last step is to change the Kotlin version to match the version Xojo uses. In the Android Studio navigator, open Gradle Scripts and double-click “build.gradle (Project: LibraryTest)” to open it.</p>



<p>Change the last line with the kotlin.android version from whatever is there to “1.6.20”:</p>



<pre id="xojo" class="wp-block-code"><code><code>// Top-level build file where you can add configuration options common to all sub-projects/modules.

plugins {
    id 'com.android.application' version '8.0.2' apply false
    id 'com.android.library' version '8.0.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.20' apply false
}</code></code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Note</strong>: You may be prompted to do a Gradle sync after making this change. Go ahead and do the sync if prompted.</p>
</blockquote>



<p>The last thing to do in Android Studio is to build the library. From the Build menu, choose “Select Build Variant”. In the Build Variants panel that appears, click on the Active Build Variant value for the utility row and change it from debug to release.</p>



<p>Select Build-&gt;Rebuild Project to build the library file that Xojo will use.</p>



<p>In your file system, go to your project’s location and fine the aar file, which is located here: LibraryTest/utility/build/outputs/aar/utility-release.aar Make a note of this as we will be using it with Xojo in a moment.</p>



<p>Speaking of Xojo, create a new Xojo Android project and name it LibraryTest. Add a button and a table like so:</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-5-530x1024.png" alt="" class="wp-image-11919" style="width:295px;height:569px" width="295" height="569" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-5-530x1024.png 530w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-5-155x300.png 155w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-5-768x1484.png 768w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-5-795x1536.png 795w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-5.png 858w" sizes="auto, (max-width: 295px) 100vw, 295px" /></figure>



<p>In the button’s pressed event, <a href="https://blog.xojo.com/2023/08/09/android-declares/">write the Declare statements</a> to call the regexmatch method in the library, passing it a regex pattern and a string to test. Here is the code, which tests three strings and outputs the result to the table:</p>



<pre id="Xojo" class="wp-block-code"><code><code>Declare Function regexmatch Lib "com.example.utility.regex" (pattern As CString, value As CString) As Boolean

// Look for g, followed by any number of "ee" pairs and ending with ks
Var pattern As String = "g(&#91;ee]+)ks?"
Var result As Boolean
Var values() As String = Array("geeks", "geeeeeeeeeeks", "geeksforgeeks")

For Each v As String In values
  result = regexmatch(pattern, v)
  Table1.AddRow(v, result.ToString)
Next

// From: https://www.geeksforgeeks.org/kotlin-regular-expression/</code></code></pre>



<p>The important thing to note in this code is the use of CString in place of String, a requirement when working with a Declare even if it doesn’t directly apply to Android.</p>



<p>Also note that you need to provide the full path to the class. You have to use “com.example.utility.regex”, not just “regex”.</p>



<p>The next step is to add the Library to the Xojo project. Select Android in the Build Settings and add a Copy Files Build Step (Insert-&gt;Build Step-&gt;Copy Files).</p>



<p>Expand Android and click on CopyFiles1. Rename it to LibCopy and drag it so that it is before the Build entry. Change the Destination to “Framework Folder”.</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-7.png" alt="" class="wp-image-11920" style="width:271px;height:157px" width="271" height="157" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-7.png 442w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-7-300x174.png 300w" sizes="auto, (max-width: 271px) 100vw, 271px" /></figure>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-8.png" alt="" class="wp-image-11921" style="width:319px;height:211px" width="319" height="211" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-8.png 586w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-8-300x199.png 300w" sizes="auto, (max-width: 319px) 100vw, 319px" /></figure>



<p>Add the library that we built with Android Studio to this LibCopy step. Click “+” in the command bar and locate utility-release.aar.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Note</strong>: If you still have Android Studio open at this point, you should close it, otherwise it will lock debugger access and prevent the Xojo app from starting.</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Pro Tip</strong>: You can keep Android Studio open and run from Xojo by choosing this preference setting: Build, Execution, Deployment -&gt; Debugger -&gt; Use existing manually managed server. You’ll want to set it back to “Automatically start and manage the server” if you use Android Studio for anything else. Constantly flipping that setting is common when working with Android libraries.</p>
</blockquote>



<p>Run the project. If you did everything correctly, it should launch on your device or emulator. Click the button to see the output which should look like this:</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-6-930x1024.png" alt="" class="wp-image-11923" style="width:430px;height:473px" width="430" height="473" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-6-930x1024.png 930w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-6-272x300.png 272w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-6-768x846.png 768w, https://blog.xojo.com/wp-content/uploads/2023/08/Pasted-Graphic-6.png 964w" sizes="auto, (max-width: 430px) 100vw, 430px" /></figure>



<p>With libraries you can add your own extensions to Xojo’s Android support. You are limited to simple types at the moment, but that still opens up a lot of capabilities. This capability will continue to be expanded through the Android beta.</p>



<p>Feel free to share any Kotlin libraries you create in the Android topic of the forum.</p>



<p><a href="https://files.xojo.com/BlogExamples/UtilityLibrary.zip">Download this Example RegEx Library</a></p>



<p>Here is <a href="https://files.xojo.com/BlogExamples/LibTest.zip">another simple Library</a> you can download and examine.</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Android Declares</title>
		<link>https://blog.xojo.com/2023/08/09/android-declares/</link>
		
		<dc:creator><![CDATA[Travis Hill]]></dc:creator>
		<pubDate>Wed, 09 Aug 2023 13:30:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11870</guid>

					<description><![CDATA[Using and writing declares for Android is very similar to other platforms. The syntax is mostly the same, but we've made some additions to make Declares that change Controls easier. Let's walk through a couple of easy-to-understand Declares to show you how they're made.]]></description>
										<content:encoded><![CDATA[
<p>Using and writing declares for Android is very similar to other platforms. The syntax is mostly the same, but we&#8217;ve made some additions to make Declares that change Controls easier. Let&#8217;s walk through a couple of easy-to-understand Declares to show you how they&#8217;re made.</p>



<span id="more-11870"></span>



<p>First, let&#8217;s just get the Android version number, the kind a user might see if they were looking for what version of Android they were running on. As with any Declare, we first look up the call in the platform documentation. For Android, that is typically here: <a rel="noreferrer noopener" href="https://developer.android.com/reference/" target="_blank">https://developer.android.com/reference/</a></p>



<p>After searching the platform docs, we find out how to get the version here: <a href="https://developer.android.com/reference/kotlin/android/os/Build.VERSION" target="_blank" rel="noreferrer noopener">https://developer.android.com/reference/kotlin/android/os/Build.VERSION</a></p>



<p>The &#8220;Lib&#8221; section of the Declare will contain the &#8220;path&#8221; up to the function/property that we want to get the value. We get this from that page as:</p>



<p><code>android.os.Build.VERSION</code></p>



<p>The actual property we want is called &#8220;RELEASE&#8221; (&#8220;The user-visible version string.&#8221;) and since we want our Declare function to be called something different, we&#8217;ll set that as an alias.</p>



<p>In summary, the full Xojo Declare to get the Android version would be:</p>



<p><code>Declare Function AndroidVersion Lib "android.os.Build.VERSION" Alias "RELEASE" As CString</code></p>



<p>We use &#8220;CString&#8221; for any String coming from the Android platform for both ease of use and Declare compatibility &#8211; even though the String type from the platform may vary internally, you do not need to worry about that.</p>



<p>You can find this Declare in the Examples section of Xojo in the Platform>.Android>Declare>Declare project.</p>



<h3 class="wp-block-heading">Object Declares</h3>



<p>With Android, there is a special new Declare format that allows us to make calls directly against certain objects and controls. This comes in handy if we want to easily make a Declare that changes the property of a control. As an example, let&#8217;s set the background color of a MobileButton.</p>



<p>The typical way to use this new type of Object Declare is by adding an Extends method to a Module. Since we want to extend MobileButton with the ability to change its color, we&#8217;ll put a method on a Module called &#8220;SetBackColor&#8221; with the following parameters: &#8220;Extends ctrl As MobileButton, c As Color&#8221;</p>



<p>We look through the platform docs again, and learn that in Android, a Button is considered a View and thus has the following method: <a href="https://developer.android.com/reference/kotlin/android/view/View#setBackgroundColor(kotlin.Int)" target="_blank" rel="noreferrer noopener">https://developer.android.com/reference/kotlin/android/view/View#setBackgroundColor(kotlin.Int)</a></p>



<p>We don&#8217;t need an Alias this time since the extension method is what we&#8217;ll call in Xojo code. What we&#8217;ll do instead is make the Declare like this:</p>



<p><code>Declare Sub setBackgroundColor Lib "Object:ctrl:MobileButton" (myColor As Integer)</code></p>



<p>Breaking this down, we&#8217;re calling the setBackgroundColor function. The Lib denotes this new type of Object declare: an Object, separated by a colon, the Xojo name of the object (in this case, our &#8220;ctrl&#8221; parameter), followed by another colon, and the Xojo type of the object.</p>



<p>The next and final line of our extension method will actually call the declared function:</p>



<p><code>setBackgroundColor(c.ToInteger)</code></p>



<p>You can see this Declare and its helper method in action from the Examples section of Xojo in the Platforms>Android>Declare>ButtonBackgroundColor project.</p>



<p>We&#8217;ve already seen users using Declares to extend their Android projects during our pre-release phase, and some are planning to make Declare projects available to everyone in the future to make using them even easier!</p>



<p><em>Travis got started with computers as a kid with a TI-99/4A. He moved on to the original Macintosh when it was released and has been programming ever since. He&#8217;s been using Xojo in various ways since v3 back in 2001. When not programming he&#8217;s usually found playing around with VR, music, games, or watching a good show.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Android Design Extensions &#8211; Get more out of your projects</title>
		<link>https://blog.xojo.com/2023/08/09/android-design-extensions-get-more-out-of-your-projects/</link>
		
		<dc:creator><![CDATA[Martin T.]]></dc:creator>
		<pubDate>Wed, 09 Aug 2023 13:30:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Android Design Extensions]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11876</guid>

					<description><![CDATA[Many of us like using Xojo because it's intuitive and extensible. With the introduction of support for Android in 2023r2, Xojo now offers support for apps running on not just phones and tablets but other devices that also use Android as their operating system such as the Amazon Fire TV Stick.]]></description>
										<content:encoded><![CDATA[
<p>Many of us like using Xojo because it&#8217;s intuitive and extensible. With the introduction of support for Android in 2023r2, Xojo now offers support for apps running on not just phones and tablets but other devices that also use Android as their operating system such as the Amazon Fire TV Stick.</p>



<p>Developers, myself included, love maximizing the potential of their projects and often desire extended access to features that Xojo does not initially provides in their framework, or even features that are not available at all. This can be remedied by using Declares, which are available in Android, as well as in all other project types (Desktop, Console and iOS). The usage may differ slightly from other platforms, but once you grasp its nuances, it becomes just as intuitive.</p>



<p>To make it easier for Xojo developers who are taking their first steps with the Android platform and would like to get more extensions and accessibility, I have created the Android (Design) Extensions modeled after the <a rel="noreferrer noopener" href="https://github.com/jkleroy/iOSDesignExtensions" target="_blank">iOS Design Extensions</a> provide by Xojo MVP Jérémie Leroy. They are extension methods for all controls and classes supported in the Android project type. At the moment the project offers 440+ extensions and that should be good for a start.</p>



<p>Check out this short video of the demo application to see some of the uses of Android (Design) Extensions:</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Android (Design) Extensions" width="500" height="281" src="https://www.youtube.com/embed/7TpcF5y_Qd4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>For example, you can add currently missing functionalities for Android MobileHTMLViewer such as <em>GoBack </em>or <em>GoForward</em>, just to name a few.</p>



<p>The project has been customized to support both light and dark modes, offering you an optimized solution for Android projects right from the start, until Xojo implements automatic light/dark mode support for Android.</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="498" height="1024" src="https://blog.xojo.com/wp-content/uploads/2023/08/202079C2-5C79-41C6-BE46-5D6261082B39-498x1024.png" alt="" class="wp-image-11887" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/202079C2-5C79-41C6-BE46-5D6261082B39-498x1024.png 498w, https://blog.xojo.com/wp-content/uploads/2023/08/202079C2-5C79-41C6-BE46-5D6261082B39-146x300.png 146w, https://blog.xojo.com/wp-content/uploads/2023/08/202079C2-5C79-41C6-BE46-5D6261082B39-768x1579.png 768w, https://blog.xojo.com/wp-content/uploads/2023/08/202079C2-5C79-41C6-BE46-5D6261082B39-747x1536.png 747w, https://blog.xojo.com/wp-content/uploads/2023/08/202079C2-5C79-41C6-BE46-5D6261082B39-996x2048.png 996w, https://blog.xojo.com/wp-content/uploads/2023/08/202079C2-5C79-41C6-BE46-5D6261082B39.png 1080w" sizes="auto, (max-width: 498px) 100vw, 498px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="498" height="1024" src="https://blog.xojo.com/wp-content/uploads/2023/08/F920EDA3-5709-42F3-A1DA-2C7D5FC86009-498x1024.png" alt="" class="wp-image-11888" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/F920EDA3-5709-42F3-A1DA-2C7D5FC86009-498x1024.png 498w, https://blog.xojo.com/wp-content/uploads/2023/08/F920EDA3-5709-42F3-A1DA-2C7D5FC86009-146x300.png 146w, https://blog.xojo.com/wp-content/uploads/2023/08/F920EDA3-5709-42F3-A1DA-2C7D5FC86009-768x1579.png 768w, https://blog.xojo.com/wp-content/uploads/2023/08/F920EDA3-5709-42F3-A1DA-2C7D5FC86009-747x1536.png 747w, https://blog.xojo.com/wp-content/uploads/2023/08/F920EDA3-5709-42F3-A1DA-2C7D5FC86009-996x2048.png 996w, https://blog.xojo.com/wp-content/uploads/2023/08/F920EDA3-5709-42F3-A1DA-2C7D5FC86009.png 1080w" sizes="auto, (max-width: 498px) 100vw, 498px" /></figure>
</div>
</div>



<p>Feel free to take a look at the developer repository, create feature requests, and provide feedback on extending this extension library.</p>



<p>I&#8217;m happy to receive any voluntary financial support for the work I&#8217;ve done so far, which you are welcome to share <a rel="noreferrer noopener" href="https://paypal.me/MTrippensee" target="_blank">here</a>. You can download the project with many examples <a href="https://github.com/XojoGermany/AndroidDesignExtensions" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p>Happy Coding.</p>



<p><em>Martin T. is a Xojo MVP and has been very involved in testing Android support.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Moving Forward &#038; Giving Back: iOS and macOS Products from Greg O&#8217;Lone</title>
		<link>https://blog.xojo.com/2023/06/15/moving-forward-giving-back-ios-and-macos-products-from-greg-olone/</link>
		
		<dc:creator><![CDATA[Xojo]]></dc:creator>
		<pubDate>Thu, 15 Jun 2023 15:35:24 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11639</guid>

					<description><![CDATA[My new path has taken me deep into the world of iOS and macOS and I thought I would create some projects &#038; products which would benefit Xojo apps on those platforms by creating some products which expose some of the larger frameworks which are not already available but also cannot be accessed by declares alone...]]></description>
										<content:encoded><![CDATA[
<p>As many of you know, I was a Xojo engineer for eleven years until early 2022 when I decided to take my career in a new direction. My time at Xojo was exciting and innovative, it gave me a chance to exercise my creativity and love for creating new things and an opportunity to work with some of the most talented people I had ever known.</p>



<p>My new path has taken me deep into the world of iOS and macOS and I thought I would create some projects &amp; products which would benefit Xojo apps on those platforms by creating some products which expose some of the larger frameworks which are not already available but also cannot be accessed by declares alone&#8230;</p>



<h3 class="wp-block-heading" id="weatherkit">WeatherKit</h3>



<p>About the time that Apple ended support for the Dark Sky API, forcing users to transition to their WeatherKit Rest API, I was thinking about an iOS project which would benefit from having access to the phases of the moon and barometric pressure on a historical basis. After a bit of research, I found that Apple&#8217;s WeatherKit framework was well-suited for the purpose, but found that it was a Swift-only framework and accessing it from Xojo was going to be challenging. I proceeded to create an obj-c bridge framework and a set of Xojo classes to make it available to everyone.</p>



<p>What resulted is a framework which currently provides developers access to the WeatherKit framework as well as some helper tools for:</p>



<ul class="wp-block-list">
<li>Location Geocoding, because WeatherKit requires Latitude/Longitude and humans don&#8217;t remember locations that way.</li>



<li>Unit Conversion, for the units that are used in WeatherKit.</li>



<li>Multicolor Symbols, for a quick and easy way to access the multicolor SFSymbols which are provided by Apple for weather.</li>
</ul>



<p>You can read more information about this framework and download a demo from <a href="https://www.stretchedout.com/yaxew/products/weatherkit.html">here</a>, and it can be purchased from Xojo&#8217;s <a href="https://xojo.com/store/addons/weatherkit.php">Extras Store</a>.</p>



<h3 class="wp-block-heading" id="multipeer-connectivity">Multipeer Connectivity</h3>



<p>Another framework which caught my eye was MultipeerConnectivity. This framework allows you to make connections with up to 8 macOS and/or iOS devices simultaneously for use in games or business applications with multiple communicating workstations. It offers both automatic user-driven and manual programmatic device discovery as well as a few data transfer mechanisms. macOS devices use Wi-Fi and/or Ethernet and iOS devices use Wi-Fi and/or Bluetooth. Network selection is completely automatic so once the connection has been established, all your app needs to do is send data back and forth and disconnect when it&#8217;s done.</p>



<p>My port of the framework gives you access to nearly the whole framework, short of creating a direct socket connection between two devices, but text and file transfers are both implemented and working just fine. I was even able to transfer a 130MB file from a Mac to an iPhone in about 16 seconds.</p>



<p>You can read more information about this framework and download a demo from <a href="https://www.stretchedout.com/yaxew/products/multipeer.html">here</a>, and it can be purchased from Xojo&#8217;s <a href="https://xojo.com/store/addons/stretchedout.php">Extras Store</a>.</p>



<h3 class="wp-block-heading" id="free-stuff">Free Stuff</h3>



<p>I also have several Github repos and a number of free xojo-related items available, including my Profile Triage tool for helping developers figure out why they get errors when trying to sign or notarize their apps. You can see that list on my site <a href="https://www.stretchedout.com/yaxew/index.html#freestuff">here</a>.</p>



<h3 class="wp-block-heading" id="more-on-the-horizon">More on the horizon&#8230;</h3>



<p>There&#8217;s more to come. I have some other products which I think will benefit Xojo iOS and macOS projects in the future, so watch for posts on the Xojo forum!</p>



<p><em>Greg O&#8217;Lone spent eleven years as a member of the Xojo engineering team from 2011 through 2022. During his time at Xojo he worked on many of the parts of the product that make Xojo what it is today &#8211; from the IDE and iOS Framework to Xojo Cloud and both of the Web Frameworks.</em> You can learn more about Greg and what he&#8217;s creating now at <a href="https://www.stretchedout.com/yaxew/about.html">his website</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Use Quick Look to Retrieve FolderItem Icons</title>
		<link>https://blog.xojo.com/2022/01/24/use-quick-look-to-retrieve-folderitem-icons/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 24 Jan 2022 14:08:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=9711</guid>

					<description><![CDATA[In this tutorial we will see how to retrieve the file icon using macOS' Quick Look technology and the regular file type associated with the selected file, for example JPEG, MOV, PDF, RTF, etc. Continue reading to learn how to achieve this using Declares.]]></description>
										<content:encoded><![CDATA[
<p>In this tutorial we will see how to retrieve the file icon using macOS Quick Look technology and the regular file type associated with the selected file, for example JPEG, MOV, PDF, RTF, etc. Continue reading to learn how to achieve this using Declares.</p>



<span id="more-9711"></span>



<p><a href="https://developer.apple.com/design/human-interface-guidelines/macos/system-capabilities/quick-look/">Quick Look</a> is the Apple technology in charge of creating icons and thumbnails based on a file contents. With Quick Look, the user can get a more precise preview of the contents stored in the selected file without having to open it.</p>



<p>You can retrieve this kind of information in your macOS Xojo Desktop apps using the <a href="https://documentation.xojo.com/api/language/declare.html">Declare</a> feature of the Xojo language, as we already have seen in <a href="https://blog.xojo.com/tag/declare/">other blog posts</a>. As you probably already know, Declares give you the ability to, well, &#8220;declare&#8221; from Xojo any call to functions or methods provided by external APIs and libraries as it is the case with the Frameworks available in the macOS operating system itself.</p>



<div class="wp-block-image is-style-default"><figure class="aligncenter"><img loading="lazy" decoding="async" width="618" height="446" src="https://blog.xojo.com/wp-content/uploads/2021/11/FileIconsListBox.gif" alt="" class="wp-image-9713"/></figure></div>



<p>Once we have &#8220;declared&#8221; these kind of functions from Xojo code, they will be ready to be used when calling any of your own defined methods or any of the methods directly available from the Xojo classes.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>You can download the Xojo Project file <a href="https://www.dropbox.com/s/2vshzzpbxmz4r6k/macOS-IconForFile.xojo_binary_project.zip?dl=0">from this link</a>.</p></blockquote>



<p>We will start by adding a new method to a Module in a Xojo Desktop project using the following method signature:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> IconForFile</li><li><strong>Parameters:</strong> <code>Extends f As FolderItem, tSize As Size, Optional QuickLookIcon As Boolean = True</code></li><li><strong>Return Type:</strong> <code>Picture</code></li><li><strong>Scope:</strong> Global</li></ul>



<p>If you are new to coding in Xojo, then probably you&#8217;ll be wondering what &#8220;<a href="https://documentation.xojo.com/api/language/extends.html">Extends</a>&#8221; means in the signature method. In brief, that means that the method will be treated as a method for the data type (or class) included next to the defined parameter; in this case the <a href="https://documentation.xojo.com/api/files/folderitem.html">FolderItem</a>.</p>



<p>The main convenience of extended class methods is that your code will be more readable and you&#8217;ll be able to call the method on a data type instance using the dot notation. So, instead of using the following syntax:</p>



<pre class="wp-block-preformatted">Var f As FolderItem = FolderItem.ShowOpenFileDialog("")
Var tSize As New Size
tSize.Height = 128
tSize.Width = 128

var p As Picture = IconForFile(f, tSize) // IconForFile as a regular method definition</pre>



<p>We are able to call the method this way:</p>



<pre class="wp-block-preformatted">Var f As FolderItem = FolderItem.ShowOpenFileDialog("")
Var tSize As New Size
tSize.Height = 128
tSize.Width = 128

var p As Picture = f.IconForFile(tSize) // IconForFile as an extended method for the FolderItem class</pre>



<p>Notice as the second chunk of code is calling the method using the dot notation on the FolderItem instance referenced by the <code>f</code> variable and how, in that case, we don&#8217;t need to provide the FolderItem variable as one of the parameters in the method call.</p>



<p>The second thing you&#8217;ll probably find of interest in the method definition is the use of the <a href="https://documentation.xojo.com/api/language/optional.html">Optional</a> keyword. We include that keyword in the method signature to indicate that such parameter is… well…&nbsp;optional; that is, you can provide the parameter in the method call or not. In fact, in the previous code snippets you might have noticed the last parameter was omitted in the method call.</p>



<p>In addition, we can also provide a default value for our Optional parameter; that is the value that will receive the method if we don&#8217;t provide a value of our own. In our method definition we are setting the QuickLookIcon parameter to the default Boolean value True.</p>



<h3 class="wp-block-heading">Getting a Quick Look Icon…&nbsp;and a Regular one</h3>



<p>With our method just added, the next step is to type in the associated Code Editor the code that will be executed when we call it. As you can see, we are using a lot of Declares here from several macOS frameworks. I have added a brief commentary about their tasks on each one of these, plus a link to the associated documentation webpage on the Developers area from Apple web, so you can continue learning or digging into their functionality and, specially, the parameters and return types declared in their original signatures so you can compare how these are translated or matched from Objective-C when declared in Xojo code.</p>



<pre class="wp-block-preformatted">#If TargetMacOS Then

  #Pragma DisableBackgroundTasks
  #Pragma DisableBoundsChecking
  #Pragma NilObjectChecking False

  If f = Nil Or Not f.Exists Then Return Nil

  Var path As String = f.NativePath

  // Declare for allocating (reserving memory for) an Objective-C object
  // https://developer.apple.com/documentation/objectivec/nsobject/1571958-alloc/
  Declare Function Alloc Lib "Foundation" Selector "alloc" (classRef As ptr) As ptr

  // Declare for autoreleasing (freeing from memory) an Objective-C object
  // https://developer.apple.com/documentation/foundation/nsautoreleasepool/1807021-autorelease/
  Declare Sub AutoRelease Lib "Foundation" Selector "autorelease" (classInstance As ptr)

  // Declare for getting a reference to an Objective-C class based on the received String
  // https://developer.apple.com/documentation/foundation/1395135-nsclassfromstring?language=objc
  Declare Function NSClassFromString Lib "Foundation" (className As CFStringRef) As ptr

  // Declare for getting a reference to the shared Workspace of macOS process.
  // https://developer.apple.com/documentation/appkit/nsworkspace/1530344-sharedworkspace/
  Declare Function sharedWorkSpace Lib "AppKit" Selector "sharedWorkspace" (classObject As ptr) As ptr

  // Declare for getting the Icon object from the recived file path
  // https://developer.apple.com/documentation/appkit/nsworkspace/1528158-iconforfile/
  Declare Function iconForFile Lib "AppKit" Selector "iconForFile:" (instanceObject As ptr, path As CFStringRef) As ptr

  // Declare for setting the size of an NSImage
  Declare Function setSize Lib "AppKit" Selector "setSize:" (instanceObject As ptr, size As NSSize) As ptr

  // Declare for Lock and Unlock an NSImage in Objective-C
  // https://developer.apple.com/documentation/appkit/nsimage/1519891-lockfocus?language=objc
  // https://developer.apple.com/documentation/appkit/nsimage/1519853-unlockfocus?language=objc
  Declare Sub LockFocus Lib "AppKit" Selector "lockFocus" (imageObj As ptr)
  Declare Sub UnlockFocus Lib "AppKit" Selector "unlockFocus" (imageObj As ptr)

  // Declare for getting a new Bitmap Representation based on the Locked view
  Declare Function InitWithFocusedView Lib "AppKit" Selector "initWithFocusedViewRect:" (imageObj As ptr, rect As NSRect) As ptr

  // Declare for getting an NSData object with the specified image format from a Bitmap Representation
  // https://developer.apple.com/documentation/appkit/nsbitmapimagerep/1395458-representationusingtype/
  Declare Function RepresentationUsingType Lib "AppKit" Selector "representationUsingType:properties:" (imageRep As ptr, type As UInteger, properties As ptr) As ptr

  Var targetSize As NSSize
  targetSize.Width = tsize.Width
  targetSize.Height = tsize.Height

  Var tRect As NSRect
  tRect.Origin.x = 0
  tRect.Origin.y = 0
  tRect.RectSize = targetSize

  Var data As ptr

  If QuickLookIcon Then

    //=================
    // Let's try to retrieve the icon from Quick Look

    Var dictClass As ptr = NSClassFromString("NSDictionary")
    Var numberClass As ptr = NSClassFromString("NSNumber")

    // Declare for getting an NSNumber object from the received Boolean value
    // https://developer.apple.com/documentation/foundation/nsnumber/1551475-numberwithbool/

    Declare Function NSNumberWithBool Lib "Foundation" Selector "numberWithBool:" (numberClass As ptr, value As Boolean) As ptr
    Var numberWithBool As ptr = NSNumberWithBool(numberClass, True)

    // Declare for getting an NSDictionary object from the received Key and Value
    // https://developer.apple.com/documentation/foundation/nsdictionary/1414965-dictionarywithobject/

    Declare Function NSDictionaryWithObject Lib "Foundation" Selector "dictionaryWithObject:forKey:" (dictClass As ptr, value As ptr, key As CFStringRef) As ptr
    Var dictInstance As ptr = NSDictionaryWithObject(dictClass, numberWithBool,"IconMode")

    Var fileClass As ptr = NSClassFromString("NSURL")

    // Declare for getting an NSURL object from the received path as string
    // https://developer.apple.com/documentation/foundation/nsurl/1410828-fileurlwithpath/

    Declare Function NSFileURLWithPath Lib "Foundation" Selector "fileURLWithPath:" (fileClass As ptr, path As CFStringRef) As ptr
    Var fileInstance As ptr = NSFileURLWithPath(fileClass, f.NativePath)

    // Declare for getting the Quick Look based icon thumbnail for the received file and with the specified size
    // https://developer.apple.com/documentation/quicklook/1402623-qlthumbnailimagecreate?language=objc

    Declare Function QLThumbnailImageCreate Lib "QuickLook" (allocator As Integer, file As ptr, size As NSSize, dictRef As ptr) As ptr
    Var imageRef As ptr = QLThumbnailImageCreate(0, fileInstance, targetSize, dictInstance)

    If imageref &lt;> Nil Then

      Var BitmapImageRepClass As ptr = NSClassFromString("NSBitmapImageRep")
      Var BitmapImageRepInstance As ptr = Alloc(BitmapImageRepClass)

      // https://developer.apple.com/documentation/appkit/nsbitmapimagerep/1395423-initwithcgimage/

      Declare Function CGInitWithCGImage Lib "AppKit" Selector "initWithCGImage:" (bitmapInstance As ptr, CGImage As ptr) As ptr
      Var BitmapImageRep As ptr = CGInitWithCGImage(BitmapImageRepInstance, imageRef)

      data = RepresentationUsingType(bitmapImageRep, 4, Nil) // 4 = PNG

      AutoRelease(BitmapImageRep)
      AutoRelease(imageref)

      // Getting Xojo Picture instance from NSData object
      Var p As Picture = NSDataToPicture(data)

      data = Nil
      numberWithBool = Nil
      fileInstance = Nil
      dictInstance = Nil
      BitmapImageRepInstance = Nil
      Return p

    End If
  End If

  // If we reach this point is because there is no way to retrieve the
  // Quick Look icon for the file, it has returned a non valid object,
  // or we received the optional QuickLookIcon param set to False,
  // so we fallback to the regular one (FileType based).

  Var WorkSpace As ptr = NSClassFromString("NSWorkspace")
  Var sharedSpace As ptr = sharedWorkSpace(WorkSpace)
  Var icon As ptr = iconForFile(sharedSpace, path) // We get NSImage here

  Var resizedIcon As ptr = setSize(icon, targetSize)

  // Getting bitmap image representation in order to extract the data as PNG.

  LockFocus(resizedIcon)

  Var NSBitmapImageRepClass As ptr = NSClassFromString("NSBitmapImageRep")
  Var NSBitmapImageRepInstance As ptr = Alloc(NSBitmapImageRepClass)
  Var newRep As ptr = InitWithFocusedView(NSBitmapImageRepInstance, tRect)

  UnlockFocus(resizedIcon)

  data = RepresentationUsingType(newRep, 4, Nil) // 4 = PNG

  // Getting Xojo Picture instance from NSData object
  Var p As Picture = NSDataToPicture(data)

  data = Nil
  icon = Nil
  AutoRelease(newRep)

  Return p

#EndIf</pre>



<p>As you can see, all the code is wrapped into a compilation conditional <a href="https://documentation.xojo.com/api/compiler_directives/＃if...＃endif.html">#If… #EndIf</a> block. This means that the code will be compiled only if the condition is evaluated as true. In this case, it will compile only when we try to compile a desktop app for macOS as stated with the TargetMacOS keyword.</p>



<p>Next, we will use three #Pragma directives to speed things up a bit. In this case the pragma disable the tasks in the background, checking bound in collections like the Arrays and checking instances set to Nil, but only during the method execution, after which things return to their original settings.</p>



<p>The remaining code includes comments so you can see what happens at the more important points; for example whether to retrieve the Quick Look icon associated with the file or the regular one based on the file data type.</p>



<p>You&#8217;ll have probably noticed that we called a second method: NSDataToPicture. This method will be in charge of converting the data from an Objective-C NSDATA object to a Xojo Picture, using the technique used in previous blog posts (<a href="https://blog.xojo.com/2021/10/21/quicktip-using-sf-symbols-in-macos-revisited/">here</a> and <a href="https://blog.xojo.com/2021/08/31/how-to-create-thumbnails-from-pdfs-on-ios/">here</a>). In this case we included it as a method call to avoid the duplication of code.</p>



<p>Let&#8217;s add a second method to our Module using the following values:</p>



<ul class="wp-block-list"><li><strong>Method Name:</strong> <code>NSDataToPicture</code></li><li><strong>Parameters:</strong> <code>data As Ptr</code></li><li><strong>Return Type:</strong> <code>Picture</code></li><li><strong>Scope:</strong> Protected</li></ul>



<p>Type the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">Declare Function DataLength Lib "Foundation" Selector "length" (obj As ptr) As Integer
Declare Sub GetDataBytes Lib "Foundation" Selector "getBytes:length:" (obj As ptr, buff As ptr, len As Integer)

Var dlen As Integer
Var mb As MemoryBlock
Var mbptr As ptr

// Getting image data to generate the Picture object in the Xojo side
// We need to get the length of the raw data…
dlen = DataLength(data)

// …in order to create a memoryblock with the right size
mb = New MemoryBlock(dlen)
mbPtr = mb

// And now we can dump the PNG data from the NSDATA objecto to the memoryblock
GetDataBytes(data, mbPtr, dlen)

// In order to create a Xojo Picture from it
Return Picture.FromData(mb)</pre>



<h3 class="wp-block-heading">Adding Required Structures</h3>



<p>As in previous tutorials dealing with Declares, we need to add several structures to the Module; these are required when calling to some of the declared functions in the IconForFile method. The required structures are:</p>



<ul class="wp-block-list"><li><strong>Structure NSOrigin</strong><br>
X As CGFloat<br>
Y As CGFloat</li><li><strong>Structure NSSize</strong><br>
Height As CGFloat<br>
Width As CGFloat</li><li><strong>Structure NSRect</strong><br>
Origin As NSOrigin<br>
RectSize As NSSize</li></ul>



<h3 class="wp-block-heading">Creating the User Interface</h3>



<p>We have prepared for retrieving the file icons on macOS, let&#8217;s continue creating a user interface for the app so we can test how it works! The final user interface will look like this:</p>



<div class="wp-block-image is-style-default"><figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="907" src="https://blog.xojo.com/wp-content/uploads/2021/11/FinalUI-1024x907.jpg" alt="" class="wp-image-9715" srcset="https://blog.xojo.com/wp-content/uploads/2021/11/FinalUI-1024x907.jpg 1024w, https://blog.xojo.com/wp-content/uploads/2021/11/FinalUI-300x266.jpg 300w, https://blog.xojo.com/wp-content/uploads/2021/11/FinalUI-768x680.jpg 768w, https://blog.xojo.com/wp-content/uploads/2021/11/FinalUI.jpg 1270w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>Click on the Window1 window in the Navigator panel; that will display the window in the Layout Editor. With Window1 selected, go to the associated Inspector Panel and change the following properties:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> MainWindow</li><li><strong>Title:</strong> Icon File Viewer</li></ul>



<p>Next, with the MainWindow item still selected and displayed in the Layout Editor, drag a Button control from the Library and drop it in the top-left area of the window in the Layout Editor (you can rely on the displayed alignment guides to position the control).</p>



<p>With the button selected in the Layout Editor, change the following values in the associated Inspector Panel:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> SelectFileBt</li><li><strong>Locking:</strong> Top and Left closed (locked)</li><li><strong>Caption:</strong> Select File</li></ul>



<p>Return to the Library, drag a Label control and position it just under the button in the Layout Editor. Use the associated Inspector Panel to change the following values:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> IconSizeLB</li><li><strong>Locking:</strong> Top and Left closed (locked)</li><li><strong>Text:</strong> Icon Size:</li></ul>



<p>Drag a Slider control from the Library and position it just to the right of the label. Drag the right corner of the Label handler in the Layout Editor to change its width so it reaches the right margin of the window. Use the associated Inspector Panel to change the following values:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> IconSizeSL</li><li><strong>Locking:</strong> Top, Left and Right closed (locked)</li><li><strong>Line Step:</strong> 32</li><li><strong>Allow Live Scrolling:</strong> Enabled</li><li><strong>Page Step:</strong> 32</li><li><strong>Tick Mark Style:</strong> Bottom Right</li><li><strong>Value:</strong> 128</li><li><strong>Minimum Value:</strong> 32</li><li><strong>Maximum Value:</strong> 1024</li></ul>



<p>Once again, drag a CheckBox control from the Library and position it just below the Label in the Layout Editor. Use the associated Inspector Panel to change the following values for the CheckBox:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> QuickLookCB</li><li><strong>Locking:</strong> Top and Left closed (locked)</li><li><strong>Caption:</strong> Quick Look Preview</li><li><strong>Visual State:</strong> Checked</li></ul>



<p>The last control we need to add is an ImageViewer. Drag the control from the Library and position it just below the CheckBox. Use the ImageViewer resizing handlers in the Layout Editor so its width and height matches the right and bottom alignment guides in the window. Then, use the associated Inspector Panel to set the following values:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> IconPreviewIV</li><li><strong>Locking:</strong> Top, Left, Right and Bottom closed (locked)</li></ul>



<h3 class="wp-block-heading">Adding Functionality to the User Interface</h3>



<p>Let&#8217;s add the code to execute when the user interacts with certain controls. With the SelectFileBt button item selected in the Navigator or the Layout Editor, use the contextual menu to add the Pressed Event to it. Then, type the following code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">file = FolderItem.ShowOpenFileDialog("")
If file &lt;&gt; Nil Then
  FileNameLB.Text = file.Name
Else
  FileNameLB.Text = ""
End If
GetIconForFile</pre>



<p>With the IconSizeSL slider control selected, use the contextual menu to add the ValueChanged Event to it, and type the following code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">If Self.File &lt;> Nil Then
  GetIconForFile
End If</pre>



<p>With the QuickLookCB checkbox item selected, use the contextual menu to add the ValueChanged Event, and type the following line of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">GetIconForFile</pre>



<p>As you can see, all of these events will call the getIconForFile method, so we need to add it to the <code>MainWindow</code> window using the following signature:</p>



<ul class="wp-block-list"><li><strong>Name:</strong> GetIconForFile</li><li><strong>Scope:</strong> Public</li></ul>



<p>…and type the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted">If file &lt;&gt; Nil Then
  Var tSize As New Size
  tSize.Height = IconSizeSL.Value
  tSize.Width = IconSizeSL.Value

  IconPreviewIV.Image = file.IconForFile(tSize, QuickLookCB.Value)

End If</pre>



<p>In the final step, add the File property (as FolderItem type) to the window, because this will be the one responsible for storing the reference to the FolderItem selected by the user when they click the SelectFileBt button.</p>



<div class="wp-block-image is-style-default"><figure class="aligncenter"><img loading="lazy" decoding="async" width="618" height="534" src="https://blog.xojo.com/wp-content/uploads/2021/11/IconFilePreview.gif" alt="" class="wp-image-9712"/></figure></div>



<p>Once the File property has been added, run the app, click on the Select File button and change the slider value to retrieve the icon for the file using a different size. Try to click in the checkbox to change the retrieved icon from the Quick Look view (enabled by default) to the kind of icon associated with that particular file type.</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Things in 2021 Release 3 You May Have Missed Because You Might Not Have Wanted to Read All 220+ Items in the Release Notes</title>
		<link>https://blog.xojo.com/2021/11/18/things-in-2021-release-3-you-may-have-missed-because-you-might-not-have-wanted-to-read-all-220-items-in-the-release-notes/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Thu, 18 Nov 2021 14:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Auto-Complete]]></category>
		<category><![CDATA[Code Editor]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Unicode]]></category>
		<category><![CDATA[Windows ARM]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=9608</guid>

					<description><![CDATA[For those of you that don't consider reading through over 220 items as fun as I do, here are a few things I thought I would highlight, in no particular order...]]></description>
										<content:encoded><![CDATA[
<p>Because we make <a href="https://documentation.xojo.com/resources/release_notes/2021r3.html">so many fixes and changes</a> (and even add a few new things) in each Xojo release, it can be daunting to read through the entire <a href="https://documentation.xojo.com/resources/release_notes/2021r3.html">release notes</a>. I encourage you to do so, though, because it&#8217;s fun!</p>



<p>For those of you that don&#8217;t consider reading through over 220 items as fun as I do, here are a few things I thought I would highlight, in no particular order.</p>



<ul class="wp-block-list"><li><strong>Desktop projects now save icon resources as compressed PNGs.</strong> This can greatly reduce binary/xml project file size and also reduce the .xojoresources file size in text projects. In the case of the Eddie&#8217;s Electronics sample project, the binary project dropped from 11MB to 780K, the XML project from 22MB to 1.1MB and the .xojoresources file from 11MB to 388K.</li></ul>



<p></p>



<ul class="wp-block-list"><li>Need to iterate through a String&#8217;s characters in a completely unicode-friendly way (including emojis)? Rather than using the <a href="https://documentation.xojo.com/api/data_types/string.html#string-characters">String.Characters</a> iterator, <strong>use the new <a href="https://documentation.xojo.com/api/text/str.htmling.Codepoints">String.Codepoints</a> iterator which returns one value for each unicode scalar</strong>.</li></ul>



<p></p>



<ul class="wp-block-list"><li> <strong>You can now install Xojo on Windows ARM 64-bit.</strong> Xojo itself remains an Intel x86-64 binary, but Windows ARM has a translation system built-in that will allow Xojo to run. This should allow those of you using ARM Windows in a VM on an Apple Silicon Mac to use Xojo there. If you&#8217;re interested in native Xojo support for Windows ARM, subscribe to <a href="http://&lt;feedback://showreport?report_id=62672&gt;">Feedback Case 62672</a> so you&#8217;ll be notified of updates.</li></ul>



<p></p>



<ul class="wp-block-list"><li><strong>Auto-complete continues to get smarter and faster</strong>. It can&#8217;t quite write your code for you, but now it does a better job of substituting text and offering suggestions, among other things.</li></ul>



<p></p>



<ul class="wp-block-list"><li><strong>The Code Editor has more improvements</strong>, particularly in the area of code folding. Another improvement is that you can use Go To Location to jump to a specific line in the code using “#50” (for example) in addition to the previously allowed &#8220;50&#8221;.</li></ul>



<p></p>



<ul class="wp-block-list"><li>For use with Declares, there is <strong>now an OSHandle class</strong> that can handle either an Integer or a Ptr.</li></ul>



<p></p>



<ul class="wp-block-list"><li>And although we mentioned it in <a href="https://blog.xojo.com/2021/09/20/the-return-of-building-for-macos-from-windows-and-linux/">another blog post</a>, I&#8217;d still like to remind people that you can again <strong>build your Mac apps from Windows and Linux</strong>. Improvements in the open-source linker project used by Xojo allowed us to bring this feature back. Of course, please continue to test your Mac apps on an actual Mac before you ship them.</li></ul>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tip: Get Metadata for an Image on macOS</title>
		<link>https://blog.xojo.com/2021/09/03/tip-get-metadata-for-an-image-on-macos/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Fri, 03 Sep 2021 12:00:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Metadata]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=9067</guid>

					<description><![CDATA[Getting the metadata from an image file on macOS is quite easy using Declares. Learn How in this Xojo blog post.]]></description>
										<content:encoded><![CDATA[<p>Getting the metadata from an image file on macOS is quite easy using <code>Declares</code>. Continue reading and I&#8217;ll show you how!<span id="more-9067"></span></p>
<p>Create a new Desktop project in the <strong>Xojo IDE</strong> and add a new <code>Module</code> to it (for example, named <code>External</code>).</p>
<p>Next, add a new method to it using the following data in the associated Inspector Panel:</p>
<ul>
<li><strong>Method Name:</strong> MetadataForImageFile</li>
<li><strong>Parameters:</strong> source As FolderItem</li>
<li><strong>Return Type:</strong> String</li>
<li><strong>Scope:</strong> Global</li>
</ul>
<p>Now add the following snippet of code to the Code Editor for the just added method:</p>
<pre>Var desc As String

#If TargetMacOS
  
  // Declares against the "Foundation" framework
  Declare Function NSClassFromString Lib "Foundation" (clsName As CFStringRef) As Ptr
  Declare Function FileURLWithPath Lib "Foundation" Selector "fileURLWithPath:" (obj As Ptr, path As CFStringRef) As Ptr
  Declare Function Description Lib "Foundation" Selector "description" (dict As Ptr) As CFStringRef
  
  // Declares against the "ImageIO" framework
  Declare Function CGImageSourceCreateWithURL Lib "ImageIO" (path As Ptr, options As Ptr) As Ptr
  Declare Function CGImageSourceCopyPropertiesAtIndex Lib "ImageIO" (imageSource As Ptr, index As Integer, options As Ptr) As Ptr
  
  If source &lt;&gt; Nil Then
    
    // Getting a Reference to the NSURL class
    Var nsurl As Ptr = NSClassFromString("NSURL")
    
    // Getting a reference to a NSURL object created from the given Path
    // for the source file
    Var filePath As Ptr = FileURLWithPath(nsurl, source.NativePath)
    
    // Getting a reference to the image object created from the 
    // given NSURL object
    Var imageRef As Ptr = CGImageSourceCreateWithURL(filePath, Nil)
    
    // Getting an NSDictionary containing the Metadata for the image
    Var dict As Ptr = CGImageSourceCopyPropertiesAtIndex(imageRef, 0, Nil)
    
    // Getting the contents of the NSDictionary instance as a String
    // This will contain the metadata for the image file!
    desc = Description(dict)
    
  End If
  
#EndIf

Return desc</pre>
<p>Now you can call this method from your code in order to get a String containing the metadata information for the FolderItem passed to it as parameter.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-9068" src="https://blog.xojo.com/wp-content/uploads/2021/08/ImageMetadata-977x1024.png" alt="" width="977" height="1024" srcset="https://blog.xojo.com/wp-content/uploads/2021/08/ImageMetadata-977x1024.png 977w, https://blog.xojo.com/wp-content/uploads/2021/08/ImageMetadata-286x300.png 286w, https://blog.xojo.com/wp-content/uploads/2021/08/ImageMetadata-768x805.png 768w, https://blog.xojo.com/wp-content/uploads/2021/08/ImageMetadata-1466x1536.png 1466w, https://blog.xojo.com/wp-content/uploads/2021/08/ImageMetadata.png 1748w" sizes="auto, (max-width: 977px) 100vw, 977px" /></p>
<p>You can find more information from Apple about the <strong>ImageIO Framework</strong> <a href="https://developer.apple.com/documentation/imageio?language=objc">here</a>. Ask me questions on Twitter <a href="https://twitter.com/xojoes">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary">Xojo Forum</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>A Functional ForEach</title>
		<link>https://blog.xojo.com/2021/03/22/a-functional-foreach/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Mon, 22 Mar 2021 10:01:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Extension Methods]]></category>
		<category><![CDATA[Loops]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=8185</guid>

					<description><![CDATA[When looping through an array, I am a big fan of using For Each as I find it more readable than using a For loop with a counter and looking up the item in the array with the counter. Sometimes it’s fun to do stuff just because you can! Plus, it makes for a good excuse to learn about some more advanced Xojo features]]></description>
										<content:encoded><![CDATA[
<p>When looping through an array, I am a big fan of using <a href="https://documentation.xojo.com/api/code_execution/for_each...next.html">For Each</a> as I find it more readable than using a For loop with a counter and looking up the item in the array with the counter.</p>



<p>Such a loop might look like this:</p>



<pre class="wp-block-preformatted">Var xdcs() As String = Array("Orlando", "Austin", "Houston", _
"Las Vegas", "Denver", "Miami")

For Each city As String in xdcs
  Display(city)
Next</pre>



<p>The Xojo Developer Conference, aka XDC, is the biggest Xojo event of the year. We&#8217;re looking forward to <a href="https://www.xojo.com/xdc/">XDC London</a> in October 2021. </p>



<p>Here is the code for the Display method:</p>



<pre class="wp-block-preformatted">Public Sub Display(it As String)
  ListBox1.AddRow(it)
End Sub</pre>



<p>But what if you wanted to simplify things even further? Say you want to write code like this:</p>



<pre class="wp-block-preformatted">xdcs.ForEach(Display)</pre>



<p>Is that even possible in Xojo? Yes, it mostly is, with a couple things called <a href="https://documentation.xojo.com/api/language/extends.html">Extension Methods</a> and <a href="https://documentation.xojo.com/api/language/delegate.html">Delegates</a>.</p>



<p>To set this up, add a Module to your project and add a Delegate to the module. A Delegate is a type that is a method declaration. Here are its specifics:</p>



<ul class="wp-block-list"><li>Delegate Name: ForEachString</li><li>Parameters: it As String</li><li>Scope: Global</li></ul>



<p>Any actual method that matches this delegate signature is said to satisfy the delegate. If you look at the Display method above, you’ll see that it matches this delegate’s signature. So the Display method could be passed into a parameter of this delegate type.</p>



<p>In the same module, add a method. This will be an extension method on a string array. An extension method is a method that is called using dot notation on a specific data type (or class), even though it is not specifically part of the data type. This method also takes the delegate defined above as a parameter. Here are the method specifics:</p>



<ul class="wp-block-list"><li>Method Name: ForEach</li><li>Parameters: Extends stringArray() As String, action As ForEachString</li><li>Scope: Global</li></ul>



<p>Its code still uses For Each and calls the delegate like this:</p>



<pre class="wp-block-preformatted">For Each s As String In stringArray
  action.Invoke(s)
Next</pre>



<p>Note: The above method and delegate are designed to work with String arrays. To work with other array types you’d need to add equivalent delegates and ForEach method overloads.</p>



<p>With these pieces now in place, this code (which is almost exactly what we wanted above &#8212; <a href="https://documentation.xojo.com/api/language/addressof.html">AddressOf</a> is used to pass a reference of the Display method to the delegate) now works:</p>



<pre class="wp-block-preformatted">Var xdcs() As String = Array("Orlando", "Austin", "Houston", _
"Las Vegas", "Denver", "Miami")

xdcs.ForEach(AddressOf Display)</pre>



<p>The above code is slightly shorter since it doesn’t need to declare the variable, but was this really worth all this this effort just for that? Well, perhaps not, but <em>I</em> think it’s cool and sometimes it’s fun to do stuff just because you can! Plus, it makes for a good excuse to learn about some more advanced Xojo features. Either way, I hope you found this interesting.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>XDC 2019 Keynote Recap</title>
		<link>https://blog.xojo.com/2019/05/01/xdc-2019-keynote-recap/</link>
		
		<dc:creator><![CDATA[Alyssa Foley]]></dc:creator>
		<pubDate>Wed, 01 May 2019 13:48:02 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[XDC]]></category>
		<category><![CDATA[64-bit]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Interops]]></category>
		<category><![CDATA[Keynote]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5691</guid>

					<description><![CDATA[Geoff just wrapped up the keynote here in sunny Miami, Florida. We've made significant progress towards these many large, multiyear projects. ]]></description>
										<content:encoded><![CDATA[<p>Geoff just wrapped up the keynote here in sunny, windy Miami, Florida.</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-5733" src="https://blog.xojo.com/wp-content/uploads/2019/05/IMG_20190501_090424.jpg" alt="" width="631" height="473"></p>
<p>After a brief introduction welcoming attendees from 11 different countries, Geoff began the keynote by sharing some graphs showing how the Xojo community has been changing.</p>
<p><span id="more-5691"></span></p>
<p>Along with a growing interest in Xojo, account creation is up 200%, we&#8217;ve seen a change in the demographics of our users. In 2017 only 22% of Xojo users were women.&nbsp;This year, that number has nearly doubled to 41%!</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5701" src="https://blog.xojo.com/wp-content/uploads/2019/04/Gender-1.gif" alt="" width="480" height="360"></p>
<p>A few years ago, just under half of Xojo users were under 35.&nbsp;Now in 2019, 61% of our users are under 35.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5702" src="https://blog.xojo.com/wp-content/uploads/2019/04/Age.gif" alt="" width="480" height="360"></p>
<p>This broader change is partially the result of current Xojo community members who evangelize Xojo on social media, blogs or simply in speaking with friends and colleagues. We know that word of mouth recommendations always carry more weight than any advertisement. Geoff took some time to recognize a few members of the Xojo community that have gone the extra mile to build this community. Hal Gumbert and Tim Dietrich, both Xojo developers from the FileMaker community, regularly blog and share on social media their experiences with Xojo. Also thanks is due to Thomas Templemann whose rally cry on the forum encouraged users to review Xojo on slant.co. What may appear to be small single actions all add up to make a difference. The stronger our community is, the better Xojo will be.</p>
<p>Next Geoff announced the winners of the <a href="https://blog.xojo.com/2019/05/01/2019-xojo-design-award-winners/"><strong>Xojo </strong><strong>Design</strong><strong> Awards 2019</strong></a>, learn more&nbsp;more about these stellar examples of what has been done with Xojo!</p>
<p>Our team has been very busy over the last 12 months. Xojo has introduced 48 new features, made 75 changes and fixed 465 bugs. To name a few: we added Dark Mode for macOS, native labels in Windows, iOS Table pull to refresh and variable row heights, better text rendering on Windows, URLConnection in API 2.0, incremental compilation for 64-bit and ARM and significantly sped up the <a href="https://blog.xojo.com/2019/04/09/speeding-up-the-layout-editor/">layout editor</a>.</p>
<p>But we&#8217;ve also spent a lot of time working on some big, multiyear features so let&#8217;s take a look at where Xojo is going.</p>
<h3>Xojo Cloud</h3>
<p>Xojo Cloud is moving to 64-bit because the modern Linux distros are all 64-bit. Going forward, Named Hosts will allow you to point a domain at a specific app.&nbsp;We will be switching from CGIs to stand-alone apps to utilize modern web protocols and we are putting a load balancer in front of each app so you can easily handle more concurrent users.</p>
<h3>Interops</h3>
<p>If you don&#8217;t already know, Interops are basically a better way to make calls into OS APIs than declares. Interops require less code, remove the need to convert data between OS and Xojo types and are far easier to write. A quick example:</p>
<p>These four lines of declares connect to the EventStore database on your iOS device:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5698" src="https://blog.xojo.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-25-at-2.25.33-PM.png" alt="" width="1622" height="332"></p>
<p>Just to connect to the eventstore, you’re dealing with a lot of very unfriendly stuff.&nbsp;However, with Interops this is reduced to one simple line that is friendly Xojo code:</p>
<h3><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5699" src="https://blog.xojo.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-25-at-2.25.59-PM.png" alt="" width="1520" height="260"></h3>
<p>Interops are already a real thing.&nbsp;We are using them internally in the iOS XDC app for both for calendar events and local notifications as well.&nbsp;We are also using them to build the Android framework.</p>
<h3>IDE Update</h3>
<p>We’ve been doing a lot of work behind the scenes on IDE improvements. You’ve seen some of this in 2019r1 with the layout editor.</p>
<p>With that completed, we’ve now reached the point where the new Home screen and improved workflow are coming soon.</p>
<h3>API 2.0</h3>
<p>API 2.0, is a set of APIs that will replace many of the existing ones, they will provide better consistency in naming, offsets and error handling. In some cases, we are taking the opportunity to modernize the implementation as well. You already saw this with URLConnection&nbsp;introduced in 2018r4. URLConnection replaced the old HTTPSocket that used a library that had to be updated. URLConnnection uses the underlying OSs&#8217; library, so as those OSs get updated in order to provide better HTTP connections, your apps will automatically benefit. To name a couple more,&nbsp;API 2.0 supports Bezier Curves for all platforms, not just iOS. And the Date class has all the features we added to xojo.core.date, including: Locale support,&nbsp;DateInterval support&nbsp;and TimeZone support.</p>
<p>In most cases the APIs have not changed and not everything will be replaced. Those that are replaced will remain for many years so you don&#8217;t need to worry about rewriting your code right away.&nbsp;This change has gone faster than expected (yay, it does happen!) and we plan to be in beta&nbsp;after just a few more updates are made.</p>
<h3>Web Framework 2.0</h3>
<p>Last year we talked a lot about the design of Web 2.0, this year Geoff focused on implementation and the great progress made so far. As a way of testing out Web Framework 2.0, we decided to port something to the web using it. Since so many have asked for it over the years, we&#8217;re working on a&nbsp;web version of Feedback.&nbsp;It’s in the early stages and Greg will be demonstrating the web version in his XDC session.&nbsp;While there’s still more implementation to do, the fact that we are using it for internally tells you how far we have come. Once the implementation is complete, we will begin beta testing.</p>
<h3>Android</h3>
<p>As you may remember we showed you a Hello World on Android back in 2018. Since then we&#8217;ve got IDE integration, apps running on simulator and apps running on actual hardware. We&#8217;re also building Android apps internally. In fact, we have put together an&nbsp;Android version of the XDC app! You can go to the <a href="https://play.google.com/store/apps/details?id=com.xojo.xdc2019&amp;hl=en">Play Store</a> and download it right now. This is a simple app, basically the HTMLViewer. However, the app is native and was built the same way you will be building native apps in Xojo. Travis will show you more controls and have lots of details and demos in his XDC session.</p>
<p><img class=""><img class=""><img class=""><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5706" src="https://blog.xojo.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-25-at-3.16.24-PM.png" alt="" width="2252" height="1510"></p>
<p>So what&#8217;s left before Android is in your hands? In this as well, a lot of the &#8220;heavy lifting&#8221; has been done, we need to finish implementing the framework and port the debugger and then we will begin pre-release testing Xojo Android.</p>
<p>As you can see, Xojo has made significant progress towards these many large, multiyear projects. An additional note, currently work on Plugins in Xojo is paused to allow us to focus on Android. We&#8217;ll do our best to keep you updated via <a href="https://twitter.com/xojo">Twitter</a> and <a href="https://www.facebook.com/goxojo">Facebook</a> throughout the conference. Please use hashtag #XDC2019 online to search or share your own thoughts. Even if you aren&#8217;t here, we&#8217;ll do our best to reduce the Xojo FOMO! The XDC Video set is now <a href="https://www.xojo.com/store/#conference">available for sale</a>.</p>
<p>Speaking of great conferences, the <a href="https://www.monkeybreadsoftware.de/xojo/events/cologne-2019-event.shtml">MBS Software conference</a> will be in Cologne, Germany on October 24th and 25th of this year. There are already 40 people coming from 10 different countries, including Geoff Perlman!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Loading 3rd Party Frameworks in Xojo iOS</title>
		<link>https://blog.xojo.com/2019/01/17/loading-3rd-party-frameworks-in-xojo-ios/</link>
		
		<dc:creator><![CDATA[Greg O'Lone]]></dc:creator>
		<pubDate>Thu, 17 Jan 2019 10:00:57 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Third Party]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5319</guid>

					<description><![CDATA[If you're familiar with Declares in iOS, loading a 3rd Party framework requires just a couple of extra lines of code in Xojo and a CopyFilesStep. In this example build and run SimulatorStatusMagic in the Simulator in order to always show a default date and time values when you do a debug run. ]]></description>
										<content:encoded><![CDATA[<p>Did you know that it&#8217;s possible to load and use 3rd Party Frameworks in your Xojo iOS projects? There&#8217;s quite a number of good projects out there, many of which are on sites like <a href="https://github.com">GitHub</a> and freely available for use in your projects. If you&#8217;re familiar with Declares in iOS, loading a 3rd Party framework requires just a couple of extra lines of code and a CopyFilesStep.</p>
<p>Last year at XDC 2018, <a href="https://github.com/jkleroy">Jérémie Leroy</a> talked about making sure your screenshots mimicked the Apple method so that the date was always Jun 9th, the time was always 9:41 AM, the battery always shows as full and the WiFi strength always shows full. It got me thinking that it might be handy to be able to make the simulator <em>always</em> show those values when you do a debug run so that you don&#8217;t need to think about it when you are ready to start taking screenshots and movies of your app. One way to do that is to build &amp; run project like <a href="https://github.com/shinydevelopment/SimulatorStatusMagic">SimulatorStatusMagic</a> on the simulator before running your project, but it would be more useful if it was <em>automatic</em>.</p>
<p><span id="more-5319"></span></p>
<h3>Build the Framework</h3>
<p>First of all, go to the SimulatorStatusMagic Github page and clone or download the project. Just like Xojo iOS development, you&#8217;ll need <a href="https://developer.apple.com/xcode/">Xcode</a> for this step. After you&#8217;ve downloaded the project, double-click on the SimulatorStatusMagic.xcodeproj file to open it in Xcode. When the project opens, change the target to SimulatorStatusMagiciOS and build it by either pressing CMD-B or pressing the Play button. Once the build is complete, go to the project navigator, scroll down to the bottom and open the Products group to reveal the built parts of this project. The only item we&#8217;re concerned with here is the file named SimulatorStatusMagiciOS.framework. Right-click on it and select Show in Finder.</p>
<h3>Build the Project</h3>
<p>Let&#8217;s start off by making sure the framework will be available to your project at runtime.</p>
<ol>
<li>Create a folder on your drive named SimulatorStatusMagic and copy the framework file that you just built into it.</li>
<li>Launch Xojo and create a new iOS project. Save the project into that folder as well.</li>
<li>To make sure the framework will be available to your project when debugging, go to the iOS target in the Xojo navigator, right-click and select Build Step &gt; Copy Files. Make sure the step is between the Build step and the Sign step.</li>
<li>Drag the SimulatorStatusMagiciOS.framework file from the Finder into the Copy Files Step.</li>
<li>In the Xojo inspector, set Applies To to &#8220;Debug&#8221; and Destination to &#8220;App Parent Folder&#8221;.</li>
</ol>
<p>Now let&#8217;s make it so you can access the framework! We&#8217;re going to add this code in the App.Open event so that the status bar gets set up before you do anything else.</p>
<p>Getting the framework to load is fairly straightforward:</p>
<pre>#If DebugBuild
  Declare Function dlopen Lib "/usr/lib/libSystem.dylib" (name As CString, flags As Int32) As Ptr
  Call dlopen("@executable_path/SimulatorStatusMagiciOS.framework/SimulatorStatusMagiciOS", 1 Or 8)
#EndIf</pre>
<p>That magic string &#8220;@executable_path&#8221; gets translated into &#8220;wherever the current application currently is&#8221; at runtime. Now this just loads the framework. We still need to hook up the methods and properties. <em>Note: If you&#8217;re working with a framework that &#8220;activates itself&#8221; like the one that comes with <a href="https://revealapp.com">Reveal</a> (an excellent tool for tracking down iOS layout issues), this is as far as you would need to go.</em></p>
<p>To figure out what we need to do next, we need to look at the documentation and header files that come with SimulatorStatusMagic. Go back to Xcode and look at the navigator. What we&#8217;re looking for is a header file (with a .h extension) which has the definitions of each of the methods and properties which are available in this framework. The only file that meets this criteria (and the one that all the others seem to point to) is named SDStatusBarManager.h. There&#8217;s a bit of functionality available here, but the framework is set up to use the Apple recommended settings by default, so all we&#8217;re going to do here is call the enableOverrides method to activate it.</p>
<p>Go back to Xojo and update App.Open event:</p>
<pre>#If DebugBuild
  Declare Function dlopen Lib "/usr/lib/libSystem.dylib" (name As CString, flags As Int32) As Ptr
  Call dlopen("@executable_path/SimulatorStatusMagiciOS.framework/SimulatorStatusMagiciOS", 1 Or 8)

  // Start by creating a pointer to the SDStatusBarManager class itself
  Declare Function NSClassFromString Lib "Foundation" (clsName As CFStringRef) As Ptr
  Dim smclass As Ptr = NSClassFromString("SDStatusBarManager")

  // Next, we need a pointer to the shared instance of the SDStatusBarManager class
  Declare Function sharedInstance Lib "Foundation" Selector "sharedInstance" (clsref As Ptr) As Ptr
  Dim smclassShared as Ptr = sharedInstance(smclass)

  // Last, turn on the overrides
  // NOTE: We're specifically NOT using the actual lib name here. 
  // This is just to satisfy the Xojo linker. The correct framework will be used at runtime.
  Declare Sub enableOverrides Lib "Foundation" Selector "enableOverrides" (obj As Ptr)
  enableOverrides(smclassShared)
#EndIf</pre>
<p>Now if you run the project, when it opens the status bar automatically changes to the recommended defaults!</p>
<p>Please Note: These changes persist until the simulator device that you are running on is completely erased. If you need to disable it, you can do that with the disableOverrides method.</p>
<p>After posting this article, it was brought to my attention that I&#8217;d forgotten to show you how to sign the frameworks so you can build for the app store. To do that, you&#8217;ll need to add a script build step to your project, just after the Copy Files step you added above. The step can probably be set to Applies To: Release. The code should look like this:</p>
<pre>// Replace the text in the signingIdentity property with your own
Dim signingIdentity As String = "iPhone Distribution: Your Company (XXXXXXXXXX)"
Dim code As Integer
Dim cmd As String
Dim result As String
Dim builtApp As String

builtApp = CurrentBuildLocation + "/" + ReplaceAll(CurrentBuildAppName, " ", "\ ")

// Get a list of all frameworks, one per line
cmd = "ls -d1 " + builtApp + "/*.framework"
result = Trim(DoShellCommand(cmd, 30, code))

// If there was no error (like none being there), sign each one
If code = 0 Then
  Dim frameworks() As String = split(result, chr(13))
  For i As Integer = 0 To UBound(frameworks)
    frameworks(i) = ReplaceAll(frameworks(i), " ", "\ ")
    cmd = "/usr/bin/codesign -fs """ + signingIdentity + """ " + frameworks(i)

    Result = DoShellCommand(cmd, 30, code)

    // If the sign fails, print the error and stop the build
    If code &lt;&gt; 0 Then
      print Result
      cancelBuild
    End If
  Next i
End If</pre>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
