Language: ENCN

Maintain both iOS and Material Themes in single app

We already know that there is no too much difference between these themes layouts. And of course, if you want to deliver the best experience for both platforms it is better to keep them in separate apps, but for simple case we can maintain both of them into single app.

App Layout

Let's take iOS theme layout for the base app layout:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <title>My App</title>
    <!-- We will include related CSS styles using JavaScript -->
  </head>
  <body>
    <div class="statusbar-overlay"></div>
    <div class="views">
      <!-- 
      We use Through-type Navbar layout for dynamic navbar.
      So we keep Navbar as the child of View, and have "navbar-through" class on View 
      -->
      <div class="view view-main navbar-through">
        <div class="navbar">
          <div class="navbar-inner">
            <div class="center sliding">Awesome App</div>
          </div>
        </div>
        <div class="pages">
          <div data-page="index" class="page">
            <div class="page-content">
              <p>Page content goes here</p>
              <a href="about.html">About app</a>
            </div>
          </div>
        </div>
      </div>
    </div>
    <script src="path/to/framework7.min.js"></script>
    <!--
    We need the following script to include styles depending on device's OS
    It is important to keep it as inline script or in separate JS file with this code only!
    -->
    <script>
      (function () {
        if (Framework7.prototype.device.android) {
              Dom7('head').append(
                  '<link rel="stylesheet" href="path/to/framework7.material.min.css">' +
                  '<link rel="stylesheet" href="path/to/framework7.material.colors.min.css">' +
                  '<link rel="stylesheet" href="path/to/my-app.material.css">'
              );
          }
          else {
              Dom7('head').append(
                  '<link rel="stylesheet" href="path/to/framework7.ios.min.css">' +
                  '<link rel="stylesheet" href="path/to/framework7.ios.colors.min.css">' +
                  '<link rel="stylesheet" href="path/to/my-app.ios.css">'
              );
          }
      })();
    </script>
    <script src="path/to/my-app.js"></script>
  </body>
</html> 

Java Script

Let's look at my-app.js.

But first of all, as we need to use conditions for iOS or Material theme, we need to determine our device. So the very first lines in our JS will be:

 
var isAndroid = Framework7.prototype.device.android === true;
var isIos = Framework7.prototype.device.ios === true;

We also need to use this conditions in our Template7 templates, so we may assigin it to Template7 global context:

Template7.global = {
    android: isAndroid,
    ios: isIos
};

In further code we need to use Dom7, let's assign it to $$:

var $$ = Dom7;

And the final part before App initialization, we need to change "Through" type navbar layout to "Fixed" in Material theme (for Android):

if (isAndroid) {
    // Change class
    $$('.view.navbar-through').removeClass('navbar-through').addClass('navbar-fixed');
    // And move Navbar into Page
    $$('.view .navbar').prependTo('.view .page');
}

Now we may initialize our App and View

// Init App
var myApp = new Framework7({
    // Enable Material theme for Android device only
    material: isAndroid ? true : false,
    // Enable Template7 pages
    template7Pages: true
});
 
// Init View
var mainView = myApp.addView('.view-main', {
    // Material doesn't support it but don't worry about it
    // F7 will ignore it for Material theme
    dynamicNavbar: true
});

These are all basics we need in our JS file. Here it is again, all in one:

// Determine theme depending on device
var isAndroid = Framework7.prototype.device.android === true;
var isIos = Framework7.prototype.device.ios === true;
 
// Set Template7 global devices flags
Template7.global = {
    android: isAndroid,
    ios: isIos
};
 
// Define Dom7
var $$ = Dom7;
 
// Change Through navbar layout to Fixed
if (isAndroid) {
    // Change class
    $$('.view.navbar-through').removeClass('navbar-through').addClass('navbar-fixed');
    // And move Navbar into Page
    $$('.view .navbar').prependTo('.view .page');
}
 
// Init App
var myApp = new Framework7({
    // Enable Material theme for Android device only
    material: isAndroid ? true : false,
    // Enable Template7 pages
    template7Pages: true
});
 
// Init View
var mainView = myApp.addView('.view-main', {
    // Don't worry about that Material doesn't support it
    // F7 will just ignore it for Material theme
    dynamicNavbar: true
});

Internal Pages

We have enabled Template7 to preprocess our internal pages. Now let's look at such internal page layout:

<!-- Dynamic navbar for iOS theme -->
{{#if @global.ios}}
<div class="navbar">
    <div class="navbar-inner">
        <div class="left sliding">
            <a href="#" class="back">
                <i class="icon icon-back"></i>
                <span>Back</span>
            </a>
        </div>
        <div class="center sliding">About</div>
    </div>
</div>
{{/if}}
 
<div class="page" data-page="about">
    <!-- Fixed navbar for Material theme -->
    {{#if @global.android}}
    <div class="navbar">
        <div class="navbar-inner">
            <div class="left">
                <a href="#" class="back icon-only">
                    <i class="icon icon-back"></i>
                </a>
            </div>
            <div class="center">About</div>
        </div>
    </div>
    {{/if}}
    
    <div class="page-content">
        <!-- Page content goes here -->
    </div>
</div>      

Conclusion

As we may see, it is pretty easy to configure basic app to maintain both iOS and Material themes. To summarize we just need to:

However, don't forget that if you want to deliver the best experience for both platforms it is better to keep them in separate apps!