Desenvolvimento

10 jan, 2013

“Puxar para baixo para atualizar” com Dojo Mobile

Publicidade

Puxar para baixo para atualizar é um padrão de UI muito usado em aplicativos nativos para smartphones iPhone, Android e BlackBerry. Ele faz exatamente o que seu nome indica: se o usuário navegar para a parte superior de uma lista, puxar para baixo e soltar, o conteúdo da lista é atualizado. Esse recurso popular, mostrado em ação na Figura 1, é uma maneira rápida para os usuários atualizarem a visualização:

pull-refresh-ios

Este artigo mostra como implementar o recurso “puxar para baixo para atualizar” em aplicativos com Dojo Mobile 1.8. Comece criando um pequeno widget que permite aos usuários puxar a visualização para baixo para revelar uma caixa de mensagens na parte superior. Em seguida, use esse widget para desenvolver dois aplicativos de amostra: um aplicativo com “puxar para baixo para atualizar” e outro com “puxar para baixo para voltar”. Obtenha o código fonte completo na seção Download no final deste artigo.

Criar o widget PullView

Como é possível ver na Figura 1 e nos aplicativos nativos para smartphone que você usa, uma caixa de mensagens (uma área que exibe mensagens como Puxe para baixo para atualizar… ) e um componente de lista movem-se juntos quando o usuário puxa a lista para baixo, enquanto um cabeçalho na parte superior tem posição fixa. Lista 1 mostra uma maneira de implementar esse comportamento usando Dojo Mobile:

<h1 data-dojo-type="dojox.mobile.Heading"
data-dojo-props='fixed:"top"'>Technical Topics</h1>
<div id="view1" data-dojo-type="dojox.mobile.ScrollableView">
<div id="pull">
<img id="icon" src="images/refresh-arrow.png">
<div id="msg1">Pull down to refresh...</div>
<div id="msg2">Check for new items</div>
</div>
<ul data-dojo-type="dojox.mobile.EdgeToEdgeDataList">
....
</ul>
</div>

A Lista 1 usa um widget Heading para colocar o cabeçalho na parte superior. A caixa de mensagens e a lista estão em um widget ScrollableView. Dessa forma, a caixa de mensagens e a lista rolam juntas, enquanto o cabeçalho é corrigido. A caixa de mensagens, no entanto, pode ser vista desde o início, como mostra a Figura 2:

message-box

A caixa de mensagens não deve aparecer até que o usuário puxe a lista para baixo, portanto, é necessário ocultá-la inicialmente.

Ocultando a caixa de mensagens

Para ocultar a caixa de mensagens, é possível aplicar CSS que mude sua posição, como mostra a Lista 2:

#pull {
position: absolute;
height: 65px;
top: -65px;
}

A Lista 2 dá a caixa de mensagens uma posição absoluta acima da lista, para ocultá-la. Quando o usuário puxa a lista para baixo, a caixa de mensagens aparece.

Mantendo a caixa de mensagens visível

Agora a caixa de mensagens é exibida apenas quando a lista é puxada para baixo. Tudo certo até aqui. O problema, no entanto, é que ScrollableView volta à sua posição inicial assim que o usuário solta a lista. Em vez disso, queremos manter a caixa de mensagens visível enquanto a lista é atualizada. Para isso, é necessário implementar uma subclasse em ScrollableView e implementar a lógica necessária. O método adjustDestination() é um bom lugar para isso. É possível obter a altura da caixa de mensagens e deslizar até a posição na qual toda a caixa seja exibida na parte superior. Se adjustDestination() retornar o valor false, o comportamento de rolagem padrão é cancelado. Lista 3 mostra o código de exemplo para a subclasse:

define([
"dojo/_base/declare",
"dojo/dom",
"./ScrollableView"
], function(declare, dom, ScrollableView){
return declare("dojox.mobile.PullView", ScrollableView, {
adjustDestination: function(to, pos, dim){
var h = dom.byId("pull").offsetHeight;
if(this.getPos().y >= h){ // if completely revealed
this.slideTo({y:h}, 0.3, "ease-out");
return false;
}
return true;
}
});
});

Publicando eventos

Por fim, é necessário publicar eventos para que o aplicativo de usuário possa receber ou conectar a eles, como mostra a Lista 4:

return declare("dojox.mobile.PullView", ScrollableView, {
adjustDestination: function(to, pos, dim){
var h = dom.byId("pull").offsetHeight;
if(this.getPos().y >= h){
this.slideTo({y:h}, 0.3, "ease-out");
connect.publish("/dojox/mobile/onPulled", [this]);
this.onPulled(this);
return false;
}
return true;
},

scrollTo: function(/*Object*/to, /*Boolean?*/doNotMoveScrollBar, /*DomNode?*/node){
this.inherited(arguments); // scrollable#scrollTo() will be called
var h = dom.byId("pull").offsetHeight;
connect.publish("/dojox/mobile/onPull", [this, to.y, h]);
this.onPull(this, to.y, h);
},

onPull: function(/*Widget*/view, /*Number*/y, /*Number*/h){
},

onPulled: function(/*Widget*/view){
}
});

Na Lista 4, onPull() é chamado enquanto a caixa de mensagens está sendo puxada. onPulled() é chamado quando toda a caixa de mensagens tiver sido puxada e solta.

Desenvolver um aplicativo com “puxar para baixo para atualizar”

Agora que você tem o widget PullView, está pronto para desenvolver um aplicativo de amostra com “puxar para baixo para atualizar”. A primeira etapa é reescrever Lista 1 comoLista 5:

<h1 data-dojo-type="dojox.mobile.Heading"
data-dojo-props='fixed:"top"'>Technical Topics</h1>
<div id="view1" data-dojo-type="dojox.mobile.PullView"
data-dojo-props='onPull:onPull, onPulled:onPulled'>
<div id="pull">
<div id="prog"></div>
<img id="icon" src="images/refresh-arrow.png">
<div id="msg1"></div>
<div id="msg2">Check for new items</div>
</div>
<ul data-dojo-type="dojox.mobile.EdgeToEdgeDataList">
....
</ul>
</div>

Em seguida, é necessário fazer mais algumas coisas no lado do aplicativo.

Girando um ícone de seta

Pode ser útil girar o ícone de seta enquanto a lista é puxada para baixo, como mostra a Figura 3:

rotating

Como a Lista 6 mostra, é possível girar as setas no manipulador onPull(). Também é possível atualizar a mensagem em onPull() para pedir ao usuário que solte a lista.

onPull = function(view, y, h){
dom.byId("msg1").innerHTML = percent < 100 ?
"Pull down to refresh..." : "Release to refresh...";
y = y > h ? h : y;
var percent = y / h * 100;
var deg = -1.8 * percent + 360;
dom.byId("icon").style.webkitTransform = "rotate(" + deg + "deg)";
}

Realizando uma ação

O manipulador onPulled() é chamado quando a caixa de mensagens é puxada para baixo inteiramente e solta. É possível colocar uma ação de atualização nesse manipulador. A ação pode variar, dependendo do aplicativo em particular. Na Lista 7, para atualizar seu conteúdo, o widget chama setStore():

onPulled = function(view){
if(prog1.timer){ return; }

// hide the arrow icon
dom.byId("icon").style.visibility = "hidden";

// update the message
dom.byId("msg1").innerHTML = "Loading...";

// add a ProgressIndicator and start it
dom.byId("prog").appendChild(prog1.domNode);
prog1.start();

// reload the datastore
store.close();
registry.byId("list").setStore(store);
}

A Lista 7 também oculta o ícone de seta, atualiza a mensagem para Loading… e inclui um ProgressIndicator. Figura 4 mostra o conteúdo sendo atualizado:

loading

Fechando a caixa de mensagens

Quando a ação de atualização estiver concluída, você fecha a caixa de mensagens como mostra a Lista 8:

connect.connect(registry.byId("list"), "onComplete", function(){
registry.byId("view1").slideTo({y:0}, 0.3, "ease-out");
prog1.stop();
dom.byId("icon").style.visibility = "visible";
});

Figura 5 mostra a lista com a caixa de mensagens fechada e o conteúdo atualizado:

list

Desenvolver um aplicativo com “puxar para baixo para voltar”

Agora crie uma variação do aplicativo de amostra — dessa vez, um aplicativo com “puxar para baixo para voltar”. Se o usuário puxar o conteúdo para baixo, um botão giratório verde aparece dentro de um slot horizontal e move-se da direita para a esquerda, como mostra a Figura 6:

pull-back-ios

Se o usuário liberar o conteúdo após o botão giratório verde chegar à extremidade esquerda do slot, como mostra a Figura 7, o aplicativo volta à visualização original:

go-back

Deslizando um botão giratório verde

Assim como você implementou a rotação do ícone de seta no primeiro aplicativo de amostra com o manipulador onPull(), é possível deslizar o nó do botão giratório em onPull(), como mostra a Lista 9:

onPull = function(view, y, h){
dom.byId("msg1").innerHTML = y < h ? "Pull down to go back" : "Go back";
y = y > h ? h : y;
var percent = Math.round(y / h * 100);
dom.byId("knob").style.left = (100 - percent) + "px";
}

Realizando uma ação

Dessa vez, a ação realizada no manipulador onPulled() é retornar à visualização anterior usando o método performTransition() da visualização atual, como mostra a Lista 10:

onPulled = function(view){
  registry.byId("view2").performTransition("view1", -1, "slide");
}

Conclusão

Neste artigo, você aprendeu a implementar duas variantes do padrão de UI “puxar para baixo para atualizar” com Dojo Mobile 1.8. Agora você pode implementar outros aplicativos com o recurso “puxar para baixo para X, em que X é a ação escolhida.

Observe que a implementação de fato do widget PullView no código de amostra é um pouco mais complexa do que eu descrevi neste artigo. É possível até colocar a caixa de mensagens na parte inferior da visualização, caso a opção pullDir="up" seja especificada. Essa opção permite criar um aplicativo com puxar para baixo para carregar mais, por exemplo.

Download

Descrição Nome Tamanho Método de download
PullView widget and sample apps pullview.zip 16KB HTTP

Informações sobre métodos de download

Recursos

Aprender

Obter produtos e tecnologias

Dojo 1.8.x: Faça download da versão mais recente do Dojo Toolkit.

***

Sobre o autor: Yoshiroh Kamiyama é Advisory Software Engineer no Yamato Software Lab (YSL), IBM Japão. Ele trabalha no WebSphere Feature Pack para Web 2.0 e Dispositivos Móveis, e anteriormente trabalhou em vários projetos de desenvolvimento, incluindo Mobile Mashup, Lotus iNotes e Rational Portfolio Manager, muitos dos quais usam o Dojo Toolkit. É contribuidor original de dojox.mobile e committer de Dojo Toolkit.

***

Artigo original disponível em: http://www.ibm.com/developerworks/br/library/mo-dojo-mobile-pullview/index.html