Ionic-framework: Sem preenchimento para barra de status (no iOS) ao navegar por push dentro de um modal

Criado em 21 set. 2016  ·  45Comentários  ·  Fonte: ionic-team/ionic-framework

Breve descrição do problema:

A barra de navegação pode se sobrepor à barra de status no iOS, quando uma nova página é enviada usando NavController#push de dentro de um modal. Veja a imagem.

img_2079

Que comportamento você está esperando?

Como todas as outras barras de navegação, esta deve deixar espaço suficiente para a barra de status.

Passos para reproduzir:

  1. Abra um modal.
  2. Dentro do modal, chame NavController#push com qualquer página.

Qual versão do Ionic? 2

Repo que mostra um exemplo do seu problema

https://github.com/zmbc/statusbar

Vá para a lista, abra um item e clique em "Empurrar algo".

Execute ionic info no prompt do terminal / cmd: (cole a saída abaixo)
Versão Gulp: CLI versão 3.9.1
Gulp local: versão local 3.9.1
Versão do Ionic Framework: 2.0.0-beta.11
Versão Ionic CLI: 2.0.0-beta.32
Versão Ionic App Lib: 2.0.0-beta.18
versão ios-deploy: 1.8.6
versão ios-sim: 3.1.1
SO: Mac OS X El Capitan
Versão do nó: v6.3.0
Versão do Xcode: Xcode 7.3.1 Versão de compilação 7D1014

Comentários muito úteis

Ainda presente no iônico-angular 3.3.0. Alguma maneira de consertar isso?

Todos 45 comentários

mesmo problema aqui. Resolvi não empurrando a nova página, mas apresentando-a como um segundo modal.

Olá a todos! Obrigado por usar o Ionic !. Tenho o prazer de informar que não consigo mais reproduzir este problema com o RC0. Obrigado!

Este bug ainda existe. Esse problema só pode ser reproduzido em um dispositivo / emulador real. Ele não aparecerá em navegadores de desktop a menos que você passe {statusbarPadding: true} para a variável de configuração de IonicModule.forRoot(MyApp, config) . Criei um repositório rápido para demonstrar esse problema com RC0 https://github.com/msalcala11/modal-padding-bug.

O mesmo problema aqui.

Também pode confirmar este problema

sim, esse problema ainda existe. por favor reabra

Temos que documentar melhor os modais, temos pessoas trabalhando nisso agora.
@comfortme @royipressburger @CyrisXD @ msalcala11 @zmbc Você tem que criar um novo ion-nav para ter navegação dentro de um modal, assim como você faz para ter navegação em seu aplicativo.

@Component({
  template: '<ion-nav [root]="root"></ion-nav>'
})
export class NavigationModal {
  root = ModalFirstPage;
}

// YOUR CONTENT MODAL
@Component({})
export class ModalFirstPage {
}

(...)

  presentModalChildNav() {
    this.modalCtrl.create(NavigationModal).present();
  }

isso ainda não faz sentido para mim.

Tenho uma página para a qual navegarei de outra página OU de um modal, dependendo de onde o usuário está no aplicativo.

Quando eu faço um nav.push dentro do modal, ele vai para a página, tudo transita bem e funciona exatamente como eu quero. EXCETO que o preenchimento da barra de status não é aplicado quando navego para a página de um modal.

Eu realmente não vejo como o trecho de código acima me ajuda com isso? Parece que deveria ser algo realmente simples, já que funcionalmente tudo está funcionando E em um dos betas anteriores o preenchimento da barra de status também foi aplicado corretamente, mas isso foi quebrado novamente em uma versão posterior.

Observe que o Android não tem nenhum problema com o mesmo código, a navegação de outra página ou de um modal está formatado corretamente e funciona bem, eu esperaria que o ios fosse o mesmo.

Ainda existe. Quaisquer hacks simples para evitar isso?

Aplique o seguinte CSS a ion-navbar e ion-title para corrigir isso. Eu uso um ngIf * para aplicá-lo apenas se o platform.is (iOS) como o Android não precisar disso. Isso é simplesmente substituído pelo css padrão ao abrir a partir de outra página no iOS, portanto, também não há problemas.

Observe também que qualquer alerta / planilha de ações / pop-up aberto na página recém-enviada será aberto atrás da página. Você precisará hackear o valor do Z-index para que esses componentes sejam maiores do que o Z-index modal para que estejam sempre no topo. Dado que essas coisas devem estar sempre no topo de qualquer maneira, isso não é realmente um problema.

<ion-navbar *ngIf="globals.isIos" style="height:calc(44px + 20px); min-height:calc(44px + 20px); padding-top:20px;">
    <button ion-button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title style="padding-top:14px !important;">{{selectedItem.name}}</ion-title>
  </ion-navbar>

Ainda com esse problema. Isso será corrigido em breve?

@mrhirsch Há um problema semelhante aqui . Confira. Não foi corrigido, mas @manucorporat pediu um exemplo de repo que eu forneci lá, então espero que eles estejam trabalhando nisso.

@ ghenry22

A maneira como você está fazendo esse preenchimento não é uma boa maneira. Não use *ngIf para ocultar barras de navegação com base nos tipos de plataforma. O cálculo de ion-content subsequentemente não levará em conta a barra de navegação e fará com que ion-content inteiros se desloquem para cima.

Em vez disso, no app.scss , adicione o seguinte CSS.

.platform-ios .ios-header {
  height:calc(56px + 20px);
  min-height:calc(56px + 20px);
  padding-top:20px;
}

Então, simplesmente no cabeçalho de que você precisa (para mim, são todas as páginas que empurro para a página da guia), basta adicionar class="ios-header" .

<ion-header>
  <ion-navbar class="ios-header">
  </ion-navbar>
</ion-header>

Muito mais SECO, e sem o problema de ion-content . Claro, se a equipe Ionic investigasse isso sozinha, não teríamos que passar por essa dor.

Para quem está tropeçando nisso com um popover, esse é o mesmo problema.

Em relação à solução: não é uma boa ideia seguir a abordagem de correção de CSS porque você está apenas mascarando algo que não está fazendo conforme o planejado (mesmo que seja um design um pouco estranho, tbh).

Outra solução diferente da apontada pelo manucorporat é trabalhar com eventos. Fiz assim e é muito simples e limpo. Basta disparar um evento em sua página modal ou popover e ouvi-lo em sua página "principal". Mais sobre eventos pode ser encontrado aqui: https://ionicframework.com/docs/api/util/Events/

@timvandijck Você pode dar um exemplo?

@ kabus202 este é um exemplo com um popover:

A página em que você está iniciando o popover:

@Component({
    selector: 'page-my-page',
    templateUrl: 'my-page.html'
})
export class MyPage {
    popover = null;

    constructor(public navCtrl:NavController, public popoverCtrl: PopoverController, public events: Events) {
        this.events.subscribe('nav:my-other-page', () => {
            this.navCtrl.setRoot(MyOtherPage);

            if (this.popover) {
                this.popover.dismiss();
            }
        })
    }

    toggleActionsMenu(event) {
        this.popover = this.popoverCtrl.create(PopoverContentPage);
        this.popover.present({
            ev: event
        });
    }
}

A página que contém o conteúdo do popover:

@Component({
    selector: 'page-popover-content',
    templateUrl: 'popover-content.html'
})
export class PopoverContentPage {

    constructor(public events: Events) {
    }

    registerAppliance() {
        this.events.publish('nav:my-other-page');
    }
}

Sim, isso ainda é um problema. Além disso, quando você tenta deslizar para voltar, às vezes ele pode agir e abrir a visualização sob o modal. @ jgw96

Ainda presente no iônico-angular 3.3.0. Alguma maneira de consertar isso?

@manucorporat Você poderia, por favor, reabrir este problema? Abrir modal na página aberta por navController.push () causa a mesma situação da primeira postagem.

Sim, por favor reabra

@vosecek O problema existe, mas você pode usar minha correção de css que postei acima. Funciona com 3.3.

Olá, pessoal, vejam a API NavController , especificamente a seção intitulada Navegando de um componente de sobreposição (colado abaixo)

Observe o uso de this.appCtrl.getRootNav() . Isso funcionou muito bem para mim, então estou curioso para saber se o uso de App corrige esse problema para outras pessoas. De qualquer forma, apenas pensei que vocês deveriam saber sobre isso.

Navegando a partir de um componente de sobreposição

import { Component } from '@angular/core';
import { App, ViewController } from 'ionic-angular';

@Component({
    template: `
    <ion-content>
      <h1>My PopoverPage</h1>
      <button ion-button (click)="pushPage()">Call pushPage</button>
     </ion-content>
    `
  })
  class PopoverPage {
    constructor(
      public viewCtrl: ViewController
      public appCtrl: App
    ) {}

    pushPage() {
      this.viewCtrl.dismiss();
      this.appCtrl.getRootNav().push(SecondPage);
    }
  }

Eu acho que a questão é por que você adicionaria tanto overhead quando você pode apenas nav.push e tudo funciona perfeitamente bem, exceto um pouco de CSS que ninguém parece interessado em consertar?

Isso meio que me lembra a resposta do Apples "apenas segurar de forma diferente" aos problemas da antena.

Por que este problema foi encerrado se ainda está lá?

@edwinchoate isso funciona, mas não quando você ainda precisa que o popover esteja ativo ao voltar da página. Não acho que seja possível navegar para longe e voltar para um popover como uma página normal com o design atual, o popover está posicionado em uma camada mais alta do que todas as páginas normais, portanto, dispensar é necessário. A menos que eles mudem completamente o comportamento do popover.

Como esse bug não foi corrigido, adicionei este código SCSS como solução alternativa e funcionou para mim. Espero que seja útil para você:

.toolbar-ios {
  height: 44px + $cordova-ios-statusbar-padding;
  padding-top: $cordova-ios-statusbar-padding;
}

.toolbar-title-ios {
  padding-top: $cordova-ios-statusbar-padding;
}

Para todas as pessoas que ainda estão tropeçando nisso. @manucorporat já apresentou a ideia certa. O código contém apenas um erro e está um tanto incompleto. Eu testei isso com Ionic 3.6.0 .

Na página de conteúdo que você apresenta como modal, simplesmente inclua outra classe de página de wrapper com um elemento nav como este:

@Component({
    template: '<ion-nav [root]="this.rootPage" [rootParams]="this.rootParams"></ion-nav>'
})
export class MyModalWrapper {
    private rootPage = MyModalContentPage;
    private rootParams;
    constructor(navParams: NavParams, private viewCtrl: ViewController) {
        this.rootParams = navParams;
        this.rootParams["data"]["closeModal"] = this.onCloseModal
    }
    onCloseModal = () => {
        this.viewCtrl.dismiss();
    }
}

E, em seguida, modifique sua classe de página de conteúdo como este:

@Component({ /* ... */ })
export class MyModalContentPage {
    /* ... */
    private closeModal;
    constructor(navParams: NavParams, /* ... */) {
        this.closeModal = navParams.get("closeModal");
    }
    /* ... */
}

Agora você pode chamar closeModal como uma função normal em sua classe ou modelo.

Agora tudo o que resta a fazer é substituir MyModalContentPage por MyModalWrapper onde quer que você crie e apresente o modal. Então, em vez de:

this.modalCtrl.create(MyModalContentPage, { /* ... */ }).present();

fazem isto:

this.modalCtrl.create(MyModalWrapper, { /* ... */ }).present();

Espero que isto ajude.

@codemusings Eu fiz assim:

@Component({
  template: '<ion-nav [root]="root" [rootParams]="params"></ion-nav>'
})
export class MyModalWrapper {
  root = MyModalContentPage;
  params: any;

  constructor(
    public navParams: NavParams,
    viewCtrl: ViewController,
  ) {
    this.params = Object.assign({}, navParams.data, {viewCtrl: viewCtrl});
  }
}

@Component({ /* ... */ })
export class MyModalContentPage {
    /* ... */
    private viewCtrl: ViewController;
    constructor(navParams: NavParams, /* ... */) {
        this.viewCtrl = navParams.get('viewCtrl');
    }
    /* ... */
    someFunc() {
      this.viewCtrl.dismiss();
    }
}

Ao passar o ViewController inteiro, você pode usar o mesmo this.viewCtrl.dismiss() que usaria normalmente; nenhuma mudança na página de conteúdo é necessária, exceto no construtor.

Estou no Ionic 3.3.0 mas acho que também funcionaria no último.

Mas o fato é que funcionalmente funciona perfeitamente bem como está e não há necessidade de todo aquele código extra, apenas uma correção CSS de uma linha apenas para iOS e isso nem é um problema.

@ ghenry22 Isso não é totalmente correto para telas grandes, por exemplo, iPad, onde a página enviada é tela cheia, embora o modal seja pequeno.

Desejo nav.push dentro de um modal Acabado de Trabalhar. Mas eu prefiro fazer dessa maneira mais complexa do que depender de correções CSS mais invasivas.

@ ghenry22 @zmbc A nav-view implica em uma pilha nav separada, que você cria ao abrir um modal. Este é o caminho".

Quando você chama navCtrl.pop, isso pode criar problemas inadvertidos com o nav raiz, uma vez que o Ionic não entende quando você está em um modal e quando não está.

Eu também não tenho problemas com páginas enviadas no iOS? Quero dizer, vou testá-lo novamente, agora que você mencionou, para ter certeza, mas eles permanecem dentro dos limites do modal para mim.

Basicamente, se eu empurro ou pop uma página de dentro de um modal, espero que ela carregue e seja vinculada ao modal.

Se eu empurrar ou abrir uma página normal, espero que ela carregue com a página em tela inteira normal.

Tenho páginas que posso usar em qualquer cenário, portanto, adicionar código para lidar com um cenário pode causar problemas no outro.

Se você quiser que a página enviada por push dentro de um modal abra em tela inteira no ipad, então acho que você teria que ter uma função que fecha o modal e então envia por push a página, o que pode ficar um pouco confuso, com certeza.

@wbhob este pode ser o resultado desejado, mas tudo que você precisa fazer é olhar para este tíquete e os fóruns iônicos e estouro de pilha para ver a mesma pergunta sendo feita repetidamente.

Obviamente, é um problema do ponto de vista da usabilidade pura para as pessoas. Seria ótimo se a ionic pudesse implementar algo sob o capô para que "simplesmente funcionasse", então todos os comentários e solicitações sobre este problema encerrado parariam :)

Fez um PR para os docs @ ghenry22

Meu pr foi mesclado! Verifique os documentos modais

@ jgw96 Espero que isso seja resolvido com o Ionic4. Tem sido excelente desde ionic2 RC0 sem nenhuma ação, o que é um pouco chocante, considerando que é uma correção simples de CSS e, em seguida, usar a navegação funciona como esperado, esteja você em uma página modal ou normal. Como deveria.

Funciona como esperado, não é um problema. Há detalhes sobre como fazer isso nos documentos Ionic (eu escrevi essa parte dos documentos)

@wbhob exceto que não funciona como esperado. Conforme mostrado pelos inúmeros tópicos no fórum. Problemas aqui e no estouro da pilha.

A navegação funciona exatamente como você espera, exceto que a página enviada perde seu status no preenchimento. Esta é uma correção de CSS simples e não requer nada mais complicado.

Sua solução recomendada e outras envolvem o fechamento da sobreposição antes de abrir a nova página. Esta não é uma abordagem viável para meu aplicativo, pois desejo que o usuário possa visualizar algumas informações de um modal OU de outras páginas regulares e, se estiver visualizando de um modal, desejo que eles possam voltar ao modal.

De qualquer forma, postei uma correção de apenas css para isso em um dos outros problemas registrados para este outro dia, que resolveu completamente para mim simplesmente aplicando os estilos de página iônicos padrão como seriam em uma configuração não modal.

A maneira correta de fazer isso é criar uma instância de navegação autocontida dentro do modal. Sua intenção é navegar para páginas adicionais, mas quando você chama navCtrl.push, como você esperaria, executa-o contra a pilha de navegação raiz, uma vez que não conhece nada melhor. Quando você faz isso corretamente e torna uma pilha de navegação exclusiva para o modal, ela funciona corretamente.

Sim, essa é uma maneira de fazer isso para um cenário específico. Supondo que, no seu caso de uso, você queira descartar a sobreposição que está aberta (modal / pop over etc) e ENTÃO abrir a página. Neste cenário, sim, o que você disse e o que é mostrado nos documentos do componente Ionic para o controlador de navegação funcionam bem.

Não quero descartar o modal que está aberto, quero poder navegar para uma página que mostre algumas informações adicionais e, quando terminar, clique em VOLTAR para voltar ao modal de onde a página foi aberta. Este cenário não é coberto pelos documentos aos quais você se refere.

Para o segundo cenário, tudo funciona perfeitamente em termos de funcionalidade. Tudo funciona sem problemas no Android. O único problema é que no IOS apenas a classe css correta não é aplicada à página enviada quando ela é enviada de uma sobreposição. Existe uma correção CSS simples para isso.

Basta inserir o seguinte em seu app.scss e você estará pronto para prosseguir, pois a classe correta agora será aplicada às páginas, sejam elas enviadas de um modal ou de outra página regular.

Agora, os dois cenários funcionam bem.
1) quando quiser descartar a sobreposição e carregar uma nova página, use o método nos documentos do navcontroller.
2) quando você não quiser descartar a sobreposição e carregar uma nova página que pode voltar e ainda ter a sobreposição de origem disponível, basta incluir o css abaixo e isso resolverá o problema de layout.

// handle top padding disappearing in modals
<strong i="12">@media</strong> only screen and (max-width: 767px){
    .ios > .ion-page > ion-header > .toolbar.statusbar-padding:first-child {
        padding-top: calc(20px + 4px);
        padding-top: calc(constant(safe-area-inset-top) + 4px);
        padding-top: calc(env(safe-area-inset-top) + 4px);
        min-height: calc(44px + 20px);
        min-height: calc(44px + constant(safe-area-inset-top));
        min-height: calc(44px + env(safe-area-inset-top));
        }
}

@ ghenry22 Acho que você está enganado. Estou usando a solução recomendada em uma aplicação Ionic, e o modal não é dispensado. Ele coloca uma nova página na pilha modal e, quando o usuário toca em "Voltar", ele retorna ao modal.

Acho que seu aplicativo provavelmente tem algum tipo de bug se você não está vendo esse comportamento com a solução recomendada. Se eu fosse você, abriria uma pergunta StackOverflow para tentar depurá-lo. Alguém aí pode ajudá-lo a descobrir.

Esse problema não é o lugar certo, porque essa funcionalidade já está no Ionic e foi adequadamente documentada para uso geral.

@zmbc https://ionicframework.com/docs/api/navigation/NavController/
Os documentos aqui para navegar a partir de uma sobreposição mostram dispensar () sendo chamado antes de navegar para a próxima página. É a isso que me referia.

Examinando os registros antigos de PR, parece que as atualizações adicionadas por @wbhob não são refletidas nas páginas de documentação dos componentes iônicos. Vou tentar a solução dos commits antigos, mas se funcionar como você disse, seria bom incluir essa informação nos documentos ou exemplos da API do componente do controlador de navegação para que possa ser encontrada facilmente.

Ainda assim, se as classes CSS corretas forem aplicadas (como no Android), não há necessidade de qualquer solução alternativa ou código adicional do usuário, certamente este seria um resultado desejável?

@ ghenry22 Não tenho mais certeza de onde dizer que as alterações de ModalController , não no NavController ).

Como expliquei antes , simplesmente não é verdade que a correção de CSS é tão boa quanto a solução recomendada. É equivalente apenas em telas pequenas onde os modais são em tela cheia, e quem sabe se funcionará na próxima versão do Ionic? A solução recomendada cria uma verdadeira pilha de navegação, que é o que você deseja nesta situação, funciona em todos os tamanhos de tela e usa uma API pública documentada. Também não é uma grande diferença na complexidade do código: eu preferiria muito mais algumas linhas de texto clichê do que algum SCSS obscuro que não serei capaz de entender no futuro.

Recomendo que você use essa abordagem para fazer exatamente o que deseja: enviar uma página em um modal e ter a capacidade de voltar ao modal. Se você não quiser fazer isso, depende de você. Mas isso claramente não é um problema com o Ionic.

@zmbc a documentação estaria no navController, pois é ele que é usado para navegação. O ModalControl apenas cria e apresenta o modal.

Eu discordo que o CSS é obscuro, é o CSS iônico padrão que é aplicado a uma página quando empurrado normalmente, eu concordo que ele pode parar de funcionar ou causar problemas se houver uma grande mudança para iônico (como com V4 chegando ), é por isso que isso deve ser corrigido como um bug que afeta a plataforma iOS para Ionic para que as pessoas NÃO PRECISAM aplicar nenhuma correção.

Esse problema não existe no Android, que funciona perfeitamente sem nenhuma alteração. Portanto, este parece ser um bug específico da plataforma com a aplicação iônica de classes CSS.

Eu admito que não testei em um dispositivo de tela maior ainda e pode haver algo mais necessário lá, vou dar uma olhada nisso.

Posso ver que existe uma solução que foi perdida nos documentos e agora existe apenas como um comentário no cabeçalho de um arquivo de origem. Se esta solução puder ser restaurada para os documentos oficiais do controlador de navegação, na seção sobre como navegar a partir de um Modal, então pelo menos há uma solução que está documentada e a documentação é facilmente acessível para quem lê o Ionic Docs.

Obviamente, não vamos concordar sobre qual abordagem é certa ou errada, então, deixando isso de lado, contanto que haja uma maneira oficialmente recomendada de fazer isso (seja lá o que for) devidamente adicionada aos documentos, isso é bom o suficiente para mim.

Obrigado pelo problema! Este problema está sendo bloqueado para evitar comentários que não são relevantes ao problema original. Se isso ainda for um problema com a versão mais recente do Ionic, crie um novo problema e certifique-se de que o modelo esteja totalmente preenchido.

Esta página foi útil?
0 / 5 - 0 avaliações