Skip to content

Themes, styles and other conventions

Florian edited this page Sep 11, 2021 · 5 revisions

This page is WIP (work in progress)

As of June 2021 a major overhaul of the c:geo UI is ongoing. This page tries to document some "best practice" approaches and conventions to use when working with styles, themes and components. Be warned, though: Most of c:geo is not yet following those conventions, there's still much work to do. And: This is WIP, some not so manifested "conventions" may still change over the next couple of months...

Some basics

  • We are migrating to using the material components library, see https://material.io/components. Before inventing your own mega cool UI element, have a look at the component library if there's something already existing which fits your needs.
  • All activities should be based on AppCompatActivity (our only exception are our settings, which need to be migrated to PreferenceFragment first, see #10579)
  • All of our themes are based on material themes, no "AppCompat" theme, no "Holo" etc.
  • Basically: You need a very good reason to not base your activity on cgeo theme

(to be continued)

For now, let's start with what got changed with our base PR #10643 in contrast to older versions of c:geo:

New base theme, and theme hierarchy reduced

  • Based c:geo main theme on MaterialComponents.DayNight.DarkActionBar, which, besides other things, means that there will be only one theme for both dark (night) and light (day) mode, and we even have the option to set changing themes to "automatically by system". That also means, that theme checks inside the java code (e.g.: Settings.isLightSkin() ? R.style.light : R.style.dark) shouldn't be implemented! See next section for more details...
  • Themes and theme hierarchy drastically reduced to a bare five themes:
    • cgeo - is the basic theme for all of c:geo, except the following
    • cgeo.popup - used for cache and waypoint popups from map (based on cgeo, but added transparency around the popup)
    • settings and settings.light are only temporarily needed, as our current implementation for settings is not yet based on AppCompatActivity and PreferenceFragment - both themes can be removed when migration of settings is done
    • SplashScreenTheme is a stripped-down theme for splash screen, based on MaterialComponents.DayNight.NoActionBar

Color and drawable definitions / new folder structure

  • Divided our color definitions into a common part (still in res/values/colors.xml), a file for the day theme colors (res/values/colors_light.xml) and a file for the night theme colors (located in res/values-night/colors_dark.xml). Be aware that the file name does not matter, it's only for easier handling in the editor. It's the folder location that matters. Files in values-night override the color values in the values folder when in night (dark) mode.
  • The same is true for drawables, so instead of naming a drawable res/drawable/test_dark.png and res/drawable/test_light.png (and chosing the right one by defining an attribute, which gets prefilled in the theme), handling is way easier now: You place the day theme drawable in res/drawable, and the night theme drawable in res/drawable-night. Or even better, use a dynamic color reference in the SVG that depends on the current theme, so that two identical icon definitions are not necessary at all. Access is simply done by using the drawable id, R.drawable.test in this case. (Same applies for the other drawable folders - res/drawable-mdpi becomes res/drawable-night-mdpi etc.)
  • Besides that, colors for the material components follow the color scheme described in https://material.io/blog/android-material-theme-color. Currently, we've set colorPrimary, colorSecondary and its variants to our orange colorAccent (as it has been called earlier), but that's not really fixed by now.
  • (Nearly) all other explicit color definitions in the separate components have been removed to be based on material theme's set of colors.

Text sizes

  • Instead of explicitly mentioning a certain textSize - and we have been very creative in doing so - all text sizes are now based on a defined set of text sizes, which you will find in values/dimens.xml
  • In all xml definitions where you need a text size, you refer to one of those attributes, e. g. textSize="@dimen/textSize_detailsPrimary"
  • So far I have defined the following text sizes:
    • detailsPrimary will be the most commonly used text size for regular text, edit text etc.
    • detailsSecondary can be used for the same places, but for less important text
    • listsPrimary and listsSecondary are similar, but for use in lists
    • headingPrimary is for headings (not toolbar!), and sometimes you might have use for a subheading, which would be headingSecondary
    • for the toolbar you can use toolbarSingle if there is a single line of text, and toolbarPrimary / toolbarSecondary if you have a two-liner
    • There are a few more for some special cases (e. g. wizard), but that's it so far - every text size is based on one of those, which gives a way more consistent look throughout the app

UI conventions

some of the following conventions are inspirited by this article

show feedback

  • always give visual touch feedback if the view is clickable. If the view does not do this automatically, apply an selectableItemBackground to the view, e.g.:
android:background="?android:attr/selectableItemBackground"           // inside the whole view
android:background="?android:attr/selectableItemBackgroundBorderless" // beyond the view borders
  • UI should provide feedback about their current status. Users should never wonder what state the system is in.

no data loss

  • Dangerous actions should either support undo or display a "do you really want to do this?" dialog
  • But we should try to speed up user workflows as well (see 'efficiency') - Providing undo instead of asking for confirmation is often the preferable solution.

efficiency

  • default actions should be reachable in as fewer clicks as possible. Every additional click is somewhat annoying.

avoid interruptions

  • popup dialogs should only be shown if there was a user action before.
  • toasts are allowed to show up at any time, but always check users will really benefit or rather be confused by it.

consistency

  • similar actions should use the same views / viewgroups. Try to make components reusable!

minimalism

  • Layouts / Activities should be as simple as possible. We never really managed this in c:geo. Somehow our screens always get too complicated ;-)
  • Furthermore, don't use any form of implementation level terminology inside the UI. Software should be understandable for average users.

software should work

  • Only release features when they are complete. It is better to not have a feature instead of having one that works poorly.

don't make everything configurable

  • For sure, there are many different user cases and sometimes a setting is simply necessary.
  • However, when people ask for a setting, try to find out the root of the problem and fix that instead.
Clone this wiki locally