Jak za jeden týden připravit kompletní aplikaci pro Windows 8 s použitím technologií HTML5, CSS3 a JavaScript – den 2

MyWindows.cz

home archív foto video win8dev kontakt

Jak za jeden týden připravit kompletní aplikaci pro Windows 8 s použitím technologií HTML5, CSS3 a JavaScript – den 2

Na jídelníčku šéfkuchaře jsou dnes následující chody:

  • Podpora mezinárodního prostředí
  • Správa aktivace režimu offline
  • Přidání ovládacího prvku flipView na stránky karet
  • Podpora přichyceného zobrazení
  • Podpora různých rozlišení
  • Podpora různých velikostí karet

Jako obvykle je kompletní řešení k dispozici zde: http://www.catuhe.com/msdn/urza/day2.zip

Celý projekt byl následně aktualizován pro Release Preview verzi Windows 8 (z Customer Preview), pro kompletní seriál (dny 0 - 4, bude popsáno v dalších článcích), je k dispozici zde: http://mywindows.cz/media/urza/UrzaGatherer.zip

Můžete si také přečíst články z předchozích dnů:

Podpora mezinárodního prostředí

Aplikace UrzaGatherer bude nabízena na všech trzích, které podporuje web Windows 8 Store. Proto je nutné, aby podporovala mezinárodní prostředí. Za tím účelem stačí přidat soubory resources.resjon do složky s názvem odpovídajícím jazyku, jehož podporu chcete přidat (například en pro angličtinu nebo fr pro francouzštinu):

Tento soubor obsahuje popis párů klíč/hodnota v notaci JSON používaných lokalizačním systémem knihovny WinJS (základního kódu JavaScript pro styl Windows 8 Metro):

{
    "Settings"              : "Settings",
    "CardsZoomLevel"        : "Cards zoom level",
    "OfflineFiles"          : "Offline files",
    "OfflineFilesRestart"   : "(You must restart to apply this settings)",
    "On"                    : "On",
    "Off"                   : "Off",
    "DownloadInProgress"    : " download(s) in progress",
    "LoadingData"           : "Loading data...please wait",
    "ErrorConnection"       : "Error during connection to server. Please check you connectivity.",
    "All"                   : "All ",
    "Colors"                : "colors",
    "Authors"               : "authors",
    "Rarities"              : "rarities",
    "Types"                 : "types",
    "Cards"                 : " cards",
    "Number"                : "Number:",

    "Type"                  : "Type:",
    "Color"                 : "Color:",
    "Power"                 : "Power:",
    "Rarity"                : "Rarity:",    
    "Text"                  : "Text:",
    "Flavor"                : "Flavor:",
    "Author"                : "Author:",
    "AveragePrice"          : "Average price:",
    "ByNumber"              : "By number",
    "ByName"                : "By name",
    "OnlyMissing"           : "Only missing",
    "AllExceptMissing"      : "All except missing"
}

Takový soubor můžete vytvořit pro všechny jazyky, které chcete podporovat. Knihovna WinJS pak za vás vyberete ten správný soubor podle jazyka aktivního uživatele.

Abyste soubor prostředku mohli používat ve své stránce HTML, je nutné přidat atribut data-win-res:

<span data-win-res="{innerText: 'OfflineFilesRestart'}"></span>

Volání následující funkce zajistí zpracování přidaného atributu a přiřadí řetězec prostředku k příslušné vlastnosti:

WinJS.Resources.processAll();

Nesmíte zapomenout tuto funkci zavolat. V aplikaci UrzaGatherer ji volám ve funkci ready pro jednotlivé stránky:

ui.Pages.define("/pages/card/card.html", {
     ready: function (element, options) {
         WinJS.Resources.processAll();

Pomocí volání systému prostředků můžete ve svém kódu také získat hodnotu přidruženou k danému klíči:

var resourceLoader = new Windows.ApplicationModel.Resources.ResourceLoader();
var getString = function (name) {
    if (!name)
        return "";

    return resourceLoader.getString(name);
};

Správa aktivace režimu offline

Někteří uživatelé nemusejí chtít používat offline režim souborů (například proto, aby aplikace UrzaGatherer nepoužívala příliš místa na disku). To můžete vyřešit tak, že do nastavení přidáte novou vlastnost:

Stačí přidat následující kód HTML do stránky default.html:

<div id="settingsDiv" data-win-control="WinJS.UI.SettingsFlyout" data-win-options="{width:'narrow'}">
    <div class="win-header">
        <button type="button" onclick="WinJS.UI.SettingsFlyout.show()" class="win-backbutton">
        </button>
        <div class="win-label" data-win-res="{innerText: 'Settings'}"></div>
    </div>
    <div class="win-content">
        <h4 data-win-res="{innerText: 'CardsZoomLevel'}"></h4>
        <input type="range" id="zoomRange" min="20" max="80" value="50" />
        <fieldset class="controlGroup">
            <legend class="controlGroupName"><span data-win-res="{innerText: 'OfflineFiles'}"></span>
                <br />
                <i><span data-win-res="{innerText: 'OfflineFilesRestart'}"></span></i>
            </legend>
            <label class="radioLabel horizontalLabelLayout">
                <input type="radio" name="offlineMode" checked id="offlineModeOn"/>
                <span data-win-res="{innerText: 'On'}"></span>
            </label>
            <label class="radioLabel horizontalLabelLayout">
                <input type="radio" name="offlineMode" id="offlineModeOff"/>
                <span data-win-res="{innerText: 'Off'}"></span>
            </label>
        </fieldset>
    </div>
</div>

Přepínače řídí stav nastavení offlineMode v rámci roamingu:

// Offline mode
var on = document.getElementById("offlineModeOn");
var off = document.getElementById("offlineModeOff");
var offlineMode = Windows.Storage.ApplicationData.current.roamingSettings.values["offlineMode"];

if (offlineMode)
    on.checked = true;
else
    off.checked = true;

on.addEventListener("change", function () {
    Windows.Storage.ApplicationData.current.roamingSettings.values["offlineMode"] = true;
});

off.addEventListener("change", function () {
    Windows.Storage.ApplicationData.current.roamingSettings.values["offlineMode"] = false;
});

Kód pro načítání obrázku je pak upraven tak, aby podporoval přepínání mezi místním (ms-appdata) a vzdáleným režimem (http):

var offlineMode = Windows.Storage.ApplicationData.current.roamingSettings.values["offlineMode"];
 if (offlineMode) {
     block.logo = "ms-appdata:///local/blocks/" + block.name.replace(":", "_") + ".png";
     block.banner = "ms-appdata:///local/blocks/" + block.name.replace(":", "_") + "_banner.png";
 }
 else {
     block.logo = root + "/blocks/" + block.name.replace(":", "_") + ".png";
     block.banner = root + "/blocks/" + block.name.replace(":", "_") + "_banner.png";
 }

A je to!

Přidání ovládacího prvku flipView na stránky karet

Dalším chodem je stránka karet, kterou je možné snadno vylepšit přidáním ovládacího prvku flipView pro přecházení mezi kartami bez nutnosti návratu na stránku rozšíření.

flipView je ovládací prvek s podporou dotykového ovládání, který umožňuje přecházet mezi položkami posunutím prstem nebo s použitím navigačních tlačítek na levé a pravé straně ovládacího prvku:

Mimochodem, data musí mít být navázána ihned a nemohou být přímo nastavena v kódu:

<body>
    <!--Template-->
    <div class="itemTemplate" data-win-control="WinJS.Binding.Template">
        <div class="item-root">
            <header aria-label="Header content" role="banner">
                <button class="win-backbutton" aria-label="Back"></button>
                <h1 class="titlearea win-type-ellipsis"><span class="pagetitle" 
                    data-win-bind="innerText: name">
                </span></h1>
            </header>
            <section aria-label="Main content" role="main">
                <h3 class="item-number-label" data-win-res="{innerText: 'Number'}"></h3>
                <div class="item-number" data-win-bind="innerText: number"></div>
                <h3 class="item-type-label" data-win-res="{innerText: 'Type'}"></h3>
                <div class="item-type" data-win-bind="innerText: type"></div>
                <h3 class="item-color-label" data-win-res="{innerText: 'Color'}"></h3>
                <div class="item-color" data-win-bind="innerText: color"></div>
                <h3 class="item-power-label" data-win-res="{innerText: 'Power'}"></h3>
                <div class="item-power" data-win-bind="innerText: power"></div>
                <h3 class="item-rarity-label" data-win-res="{innerText: 'Rarity'}"></h3>
                <div class="item-rarity" data-win-bind="innerText: rarity"></div>
                <h3 class="item-text-label" data-win-res="{innerText: 'Text'}"></h3>
                <div class="item-text" data-win-bind="innerText: text"></div>
                <h3 class="item-flavor-label" data-win-res="{innerText: 'Flavor'}"></h3>
                <div class="item-flavor" data-win-bind="innerText: flavor"></div>
                <h3 class="item-author-label" data-win-res="{innerText: 'Author'}"></h3>
                <div class="item-author" data-win-bind="innerText: author"></div>
                <h3 class="item-price-label" data-win-res="{innerText: 'AveragePrice'}"></h3>
                <div class="item-price" data-win-bind="innerText: price UrzaGatherer.Tools.PriceConverter">
                </div>
                <div class="item-image-container" data-win-control="UrzaGatherer.Tools.DelayImageLoader"
                    data-win-options="{root: 'cards'}">
                    <img class="item-image-container" data-win-bind="src: logo" />
                </div>
                <div class="expansion-image-container" data-win-control="UrzaGatherer.Tools.DelayImageLoader">
                    <img class="expansion-picture" src="#" data-win-bind="src: expansion.banner" />
                </div>
            </section>
        </div>
    </div>
    <!--Content-->
    <div class="card fragment">
        <div id="flipView" data-win-control="WinJS.UI.FlipView" 
            data-win-options="{ itemTemplate : select('.itemTemplate') }">
        </div>
    </div>
</body>

Všimněte si přítomnosti atributu data-win-res pro lokalizaci a atributu data-win-bind pro navázání dat.

Propojení mezi ovládacím prvkem flipView a daty nastavíte s použitím stejného kódu jako v případě ovládacího prvku listView:

var flipView = document.getElementById("flipView").winControl;
ui.setOptions(flipView, {
    itemDataSource: options.cards.dataSource,
    currentPage: options.cardIndex
});

Podpora přichyceného zobrazení

Aby aplikace dosáhla certifikace pro web Store, musí podporovat přichycené zobrazení. Tento režim se aktivuje, když je aplikace zobrazena vedle další aplikace. Plocha povolená pro přichycenou aplikaci má šířku 320 pixelů.

Je nutné definovat nový návrh pro přichycené zobrazení pro všechny obrazovky v aplikaci.

V případě aplikace UrzaGatherer jsem se rozhodl zachovat v přichyceném zobrazení kompletní možnosti práce s aplikací. Můžete se samozřejmě rozhodnout vypustit nepodstatné funkce, ale v případě aplikace UrzaGatherer jsou v přichyceném zobrazení k dispozici všechny funkce.

Hlavní obrazovka se změní následovně:

Obrazovka rozšíření v přichyceném zobrazení vypadá takto:

A toto je obrazovky karty:

Kouzelné na tom je, že k provedení všech těchto úprav stačí pouze jedna funkce: media queries (http://msdn.microsoft.com/en-us/library/windows/apps/hh453556.aspx). Tato funkce umožňuje vybrat nová pravidla šablon stylů CSS na základě konkrétních dotazů (například, zda je aplikace v režimu přichycení).

Toto je příklad pro stránku rozšíření:

@media screen and (-ms-view-state: snapped) {
    #cardsCount {
        display: none;
    }
    #cardsPrice {
        display: none;
    }
    .expansion section[role=main] {
        -ms-grid-rows: 0px 1fr;
    }
}

Tato pravidla nahradí (nebo doplní) původní pravidla. Například základní pravidla pro .expansion section[role=main] jsou následující:

.expansion section[role=main] {
    -ms-grid-columns: 1fr;
    -ms-grid-rows: 50px 1fr;
    display: -ms-grid;
}

V režimu přichycení se z nich na základě našeho dotazu stane:

.expansion section[role=main] {
    -ms-grid-columns: 1fr;
    -ms-grid-rows: 0px 1fr;
    display: -ms-grid;
}

Vaším úkolem tedy je přesunout elementy HTML s použitím dotazů na médium z horizontálního rozložení na velké ploše do malého vertikálního rozložení (pomocí mřížek specifikace CSS3).

Podpora různých rozlišení

Pomocí dotazů na médium je možné také aplikaci přizpůsobit různým rozlišením. Stránka karty může například pomocí dotazu na médium přizpůsobit své zobrazení nízkému rozlišení:

@media screen and (min-height: 1024px) {
    .card section[role=main] {
        -ms-grid-columns: auto 1fr 960px;
    }

    .card .item-image-container {
        margin-top: 0px;
    }
}

Při velkém rozlišení zobrazení vypadá takto:

A při nižším rozlišení:

Jak vidíte, sloupce jsou menší a obrázek se posunul nahoru, aby bylo dostatek místa na jeho zobrazení.

Podpora různých velikostí karet

Poslední věcí, o které dnes chci mluvit, je práce s vícenásobnými šablonami pro ovládací prvek listView. Některé karty v mé sbírce jsou dvakrát širší než standardní karty (zejména ty v rozšíření Planechase):

Můžete to vyřešit tak, že namísto statické šablony poskytnete funkci JavaScript, která šablonu vytváří dynamicky:

var listView = element.querySelector(".cardsList").winControl;

ui.setOptions(listView, {
    itemTemplate: this.itemRenderer,
    oniteminvoked: this.itemInvoked.bind(this)
});

Funkce itemRenderer zodpovídá za vykreslování jednotlivých položek. Máte tedy úplnou kontrolu nad vytvářením všech elementů. V tomto případě můžete zkontrolovat, zda se jedná o velkou kartu, a podle toho upravit styly:

itemRenderer: function (itemPromise) {
    return itemPromise.then(function (currentItem, recycled) {
        var template = document.querySelector(".itemTemplate").winControl.renderItem(itemPromise, recycled);
        template.renderComplete = template.renderComplete.then(function (elem) {

            if (currentItem.data.isLarge) {
                var zoomLevel = Windows.Storage.ApplicationData.current.roamingSettings.values["zoomLevel"];

                if (!zoomLevel)
                    return;

                var level = zoomLevel / 100.0;
                elem.querySelector(".item-container").style.width = (480 * level * 2) + "px";
            }
        });
        return template.element;
    })
},

Všimněte si, že kód při výpočtu správné velikosti bere do úvahy místní úroveň přiblížení.

Ale to nestačí. Aby ovládací prvek podporoval různé velikosti položek, musí být ve „vícevelikostním“ režimu. Proto je nutné přidat parametr groupInfo:

ui.setOptions(listView, {
    itemDataSource: filtered.dataSource,
    layout: new ui.GridLayout({
        groupHeaderPosition: "top",
        groupInfo: function () {
            var zoomLevel = Windows.Storage.ApplicationData.current.roamingSettings.values["zoomLevel"];

            if (!zoomLevel)
                zoomLevel = 50;

            var level = zoomLevel / 100.0;

            return {
                multiSize: true,
                slotWidth: Math.round(480 * level),
                slotHeight: Math.round(680 * level)
            };
        }
    })
});

Evidentně je důležité poskytnout správnou velikost buňky (slotWidth a slotHeight), protože velikost všech položek v ovládacím prvku listView musí odpovídat velikosti buňky!


Anglický originál tohoto článku od David Catuhe je dostupný na MSDN.


win8 soutěž win8 vývoj

Nový komentář

Pro přidání komentáře se musíte  registrovat Facebookem. Je to snadné a bezpečné.