Category Archives: code

UI design for questions in your app

IMG_20160721_103356When asking a question in an app, it is important to make it easy for the user to find the right answer to the question. Simply because a question is phrased for a yes/no answer doesn’t mean that presenting yes or no as answers is a good idea. Instead it is a good idea to present the answers such that the right option can be selected even if the user doesn’t even bother to read the question.

The Brexit ballot from earlier this month is an example of good design. The question on the ballet asked if the UK should leave the EU, but the answers to pick from are ‘remain’ and ‘leave’ rather than ‘yes’ and ‘no’. This makes for a better user experience.

The image to the right is from the Stuff I Need app and shows the example of the same design. ‘Delete All’ and ‘Cancel’ do not explicitly answer the question, but give the user the opportunity to pick the right choice, even if they don’t read the question.

Showing the full file path in the finder

By default the finder on Mac OSX does not show the full file path of the current folder. This can make it hard to remember where a folder is, and can cause confusion when working with multiple folders with the same name.

Fortunately, there is a simple fix that will show the full file path in the finder’s title bar.

In the terminal type

defaults write com.apple.finder _FXShowPosixPathInTitle -bool true

And then to restart the finder

killall Finder

After that the folders full path will be displayed in the title of the finder.

Preventing Windows 10 updates from rebooting your computer

By default Windows will download and install updates on your computer without any required interaction. This is great, but the problem is that it will also reboot on its own, closing anything you may have been in the middle of working on. No idea why Microsoft approved of this terrible user experience, but fortunately there is a (very hidden) way of preventing it from happening.

First from the start menu, search and open “gpedit.msc”. Then in the application go to Computer Configuration -> Administrative Templates -> Windows Components -> Windows Update. Then select the option “No auto-restart with logged on users for scheduled automatic updates installations”, then click “Enable”, and then “Apply”.

This will ensure that your Windows 10 machine will only restart when you want it to.

Synchronous AlertDialogs in Android

In general Android does not want developers creating alert dialogs that block the flow of code, but for those situations where it is needed, there is a way to force a dialog to wait. The approach essentially uses a handler to create a slightly more elegant version of a busy loop.

private boolean resultValue;
public boolean getDialogValueBack(Context context)
{
    final Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message mesg)
        {
            throw new RuntimeException();
        } 
    };

    AlertDialog.Builder alert = new AlertDialog.Builder(context);
    alert.setTitle("Title");
    alert.setMessage("Message");
    alert.setPositiveButton("Return True", new DialogInterface.OnClickListener()
    {
        public void onClick(DialogInterface dialog, int id)
        {
            resultValue = true;
            handler.sendMessage(handler.obtainMessage());
        }
    });
    alert.setNegativeButton("Return False", new DialogInterface.OnClickListener()
    {
        public void onClick(DialogInterface dialog, int id)
        {
            resultValue = false;
            handler.sendMessage(handler.obtainMessage());
        }
    });
    alert.show();

    try{ Looper.loop(); }
    catch(RuntimeException e){}

    return resultValue;
}

Setting up Windows to use ls like dir

After spending a lot of time with the unix command line you can get used to simply using the ls command to list the files in the current directory, it can be annoying when the option is suddenly not there on the Windows. Using the cd command to traverse through directories is the same, so it is a bit jarring when suddenly ls does not work.

Fortunately I was able to find a simple way to fix this from Stack Overflow. This approach maps the ls command to the dir, and is so simple that the file to do so can be created with a single statement on the command line.

echo dir %1 > %systemroot%\system32\ls.bat

This statement will create a new bat file that is always visible and will replace ls with dir behind the scenes. Now you can just use the ls command without having to think about what operating system you are running.

Writing to a file in a Windows 10 Cordova app

While writing to a file is easy in C# applications, for apps written in JavaScript things are a bit more complicated. Especially if you want to write to a file outside of the app’s sandbox. Fortunately this can be solved using Microsoft’s WinJS libraries.

var exportData = "String of data";
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.documentsLibrary;
savePicker.fileTypeChoices.insert("CSV", [".csv"]);
savePicker.suggestedFileName = "Export.csv";

savePicker.pickSaveFileAsync().then(function (file) {
    if (file) {
        Windows.Storage.CachedFileManager.deferUpdates(file);
        Windows.Storage.FileIO.writeTextAsync(file, exportData).done(function () {
            Windows.Storage.CachedFileManager.completeUpdatesAsync(file).done(function (updateStatus) {
                if (updateStatus === Windows.Storage.Provider.FileUpdateStatus.complete) {
                    //file saved
                } else {
                   //file not saved, failed for some reason
                }
            });
        });
    } else {
        //file not saved, canceled by user
    }
});

This will allow Cordova apps to write out to a part of the operating system where users can easily access the files.

UI frameworks for Angular.js

I recently had the opportunity to review a number of angular.js compatible UI frameworks. All of these frameworks are fairly new, and therefore they all give some thought to how they appear on phones and tablets.

Angular Material

angularmaterialAngular Material has been created by Google to follow the guidelines for Android’s Material UI. In my opinion this is the best UI for angular. Given its ties to Android it works great on mobile, but it also is designed to scale up to also look good on larger screens. Additionally, the flex box based layout system for Angular Material is more complete and more reliable than what is offered by the other frameworks.

Ionic

ionicThe Ionic framework by Drifty is a mobile focused UI that I have used before. Ionic has good looking controls, and mostly follows the design found in iOS 7. Compared to the other frameworks, the touch targets for Ionic are larger and better optimized for phones. By design, Ionic is meant to be used for creating Cordova apps, but can also be used for websites if you copy two files from their github.

UI Bootstrap

Unlike the other frameworks, Bootstrap does not include any JavaScript and is implemented strictly through css. While this lightweight approach is great, UI Bootstrap is also the least optimized for mobile and is the least integrated with angular.

LumX

lumxCreated by LumApps, Lumx is another framework that follows Android’s Material design guidelines. Unfortunately, when compared to Angular Material, it is not quite as good. Also LumX has the far more third party dependencies than the other frameworks, making it more difficult for set up. On the plus side, it has the best selection of built in colors for theming your app.

Using multiple frameworks

Additionally there is the option to use a number of these frameworks together at the same time. This is not always an option as the css for Bootstrap and Ionic conflict with one another. But sometimes it can work. In particular the components of Ionic make a good compliment to the layout and navigation of Material.

Coloring a ProgressBar on Android

On newer versions of Android (such as Lollipop and Marshmallow) the activity indicator now has a distinct color instead of just being a shade of gray. While this is neat, it brings up the potential for the color of the activity indicator to clash with your design.

Fortunately it is possible to change the color of these controls. Starting with the xml in the layout, your progress bar will look as follows…

<ProgressBar
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:id="@+id/activityIndicator"
    android:progressDrawable="@drawable/colorProgress"
    android:indeterminateOnly="true"/>

The relevant part of this code is the setting of progressDrawable to a custom drawable object. While this custom object must exist, it doesn’t actually have to do anything. The full source of colorProgress.xml is below and is essentially blank.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
</selector>

Finally we will get to the Java code that actually sets the color of the progress bar. This is done as the program starts up and consists of three steps. First, you filter out the older Android OS versions to avoid crashing the app on Android 4.x phones. Next you get a reference to the ProgressBar object, and then finally you set the object to the color you want.

protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
ProgressBar progressbar = (ProgressBar) findViewById(R.id.activityIndicator);
int color = 0xFF2980b9;
progressbar.getIndeterminateDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);
progressbar.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
}

Forcing a dark theme on Windows Phone Universal Apps

While the introduction of Windows 8.1 and Windows 10 has done a lot to clean up the look of apps, Windows Phone still allows you to give your phone a light theme which can make your app look weird. This requires you to do additional testing for your apps and optionally hard code colors for some elements on the screen.

In 2013, I described how to force a dark theme on Windows Phone silverlight apps, but things have changed when it comes to the newer universal apps.

The ApplicationBar has been replaced by the CommandBar, and is fortunately rather easy to theme in XAML. The following code will force your CommandBar into a dark theme.

<CommandBar Background="#1F1F1F" Foreground="White">
</CommandBar>

Theming ListPreference Dialogs on Android Lollipop

ListPreferenceSetting a custom theme color for your Android app is as simple as setting a colorAccent color in the app’s styles.xml file. Yet while this will theme most of the app, oddly ListPreference pop-ups and other dialogs do not naturally inherit the theme used by the rest of the app.

In order to fix this both a dialogTheme and an alertDialogTheme need to be explicitly added to the app’s styles.xml file. The result should look similar to this…

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme" parent="android:Theme.Material.Light">
        <item name="android:colorPrimary">@color/primary
        <item name="android:colorPrimaryDark">@color/accent
        <item name="android:colorAccent">@color/accent
        <item name="android:dialogTheme">@style/DialogStyle
        <item name="android:alertDialogTheme">@style/DialogStyle
    </style>
    <style name="DialogStyle" parent="android:Theme.Material.Light.Dialog">
        <item name="android:colorAccent">@color/accent
    </style>
</resources>

How to treat Android’s up button like a back button

When opening up a child screen on most android apps an arrow will appear on the upper left corner of the screen indicating that you can go back to the previous screen. Android’s documentation refers to this as an “up” button (despite the fact that it clearly points left). While at first glance it appears to similar to the back button it is subtly different.

More complex apps may have a use for the difference in this button’s behavior, but for simple apps the up button acts like a back button that additionally blows away minor state information (such as scroll position) on the parent screen. Fortunately there is a simple way to force the up button to act the same as your standard back button.

In the child activity find the onOptionsItemSelected() method…

public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == android.R.id.home) {
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

and replace NavUtils.navigateUpFromSameTask(this); with finish(); so that your new code now looks like...

public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == android.R.id.home) {
        finish();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Now the back button on your action bar will work just as well as the back button at the bottom of the screen.

Amazon now allowing for fine grained control of BlackBerry app Support

With the Amazon app store coming pre-installed on new BlackBerry 10 phones, Amazon is continuing to improve the support given to developers. Last month Amazon began explicitly adding BlackBerry phones to their testing procedures, and now they are giving developers the option to individually select support for various BlackBerry phones.

amazon

Previously all BlackBerry phones were just included under the generic “all other Android devices” category while a specific per device breakdown like what is now offered was only available for the Amazon Fire line of products.

How to invoke the Classic Camera app

The Classic Camera app can be invoked using the following code…


InvokeManager mInvokeManager = new InvokeManager(this);
connect(mInvokeManager,
      SIGNAL(childCardDone(const
      bb::system::CardDoneMessage&)), this,
      SLOT(childCardDone(const
      bb::system::CardDoneMessage&)));
InvokeRequest request;
request.setAction("bb.action.CAPTURE");
request.setTarget("com.ebscer.classiccamera.card");
request.setMimeType("image/jpeg");
mInvokeManager->invoke(request);

The response data contains the file name of the captured image.

Thoughts on BlackBerry Cascades from 2011

Flipping through an old notebook, I came across my notes on BlackBerry Cascades from BlackBerry DevCon 2011. This was half a year before the framework was released, and a good year and a half before the launch of BlackBerry 10. Since then I have become an expert at Cascades, but it is interesting to see some of my earlier thoughts.IMG_20150311_233508_crop

  • 2D and 3D
  • 90% of UI could be lists
  • QML declarative UI from Qt
  • Asynchronous to help rendering rate
  • Signals to handle events
  • List Types – (SQL,XML,JSON)
  • Uses BBX IDE
  • QML looks nicer than C++
  • Beta in fall (November)
  • Everything in BBX is Qt

Somethings I got right, and with some others I look a little silly. For example Cascades has no support for 3D. In fact Cascades is actively bad at working in three dimensions and doesn’t even support giving z-values to elements. Also the beta wasn’t launched in November (at the time only a month away), but instead the next May. The emphasis on lists was a bit overblown. Creating 90% of an app out of lists can be true for pretty much any framework, and somewhat ironically I don’t actually use a ListView for creating the lists in most of my apps anyhow. The one thing that was apparent to me from the very beginning is that QML is far nicer than C/C++ ever was…

How to get a Slider to stop at discreet points on a Windows Phone app

By default the Slider control that Microsoft provides for Windows Phone Silverlight applications is missing some key properties such as the IsSnapToTickEnabled property. However this can be recreated in code to give Windows Phone apps the same functionality.

First the XAML…

<Slider x:Name="slider" Width="450" ValueChanged="Slider_ValueChanged" Minimum="0" Maximum="10" SmallChange="1"/>

Then in C#…

public void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
        try
        {
            int newValue = (int)e.NewValue;
            slider.Value = newValue;

            //code goes here, using newValue
            //as the slider's value...
        }
        catch (Exception) { }
}