O iOS 8 removeu a propriedade da janela de visualização "minimal-ui"; existem outras soluções de "tela cheia suave"?

191

(Esta é uma pergunta com várias partes, farei o possível para resumir o cenário.)

No momento, estamos construindo um aplicativo Web responsivo (leitor de notícias) que permite que os usuários deslizem entre o conteúdo com guias, bem como rolar verticalmente dentro de cada conteúdo com guias.

Uma abordagem comum para o problema é ter um wrapper divque preencha a janela de exibição do navegador, definido overflowcomo hiddenou auto, em seguida, role horizontalmente e / ou verticalmente dentro dele.

Essa abordagem é ótima, mas tem uma desvantagem principal: como a altura do documento é exatamente a mesma da janela de exibição do navegador, o navegador móvel não oculta a barra de endereços / menu de navegação .

Existem inúmeras propriedades de hacks e viewport que nos permitem obter mais propriedades da tela, mas nenhuma é tão eficaz quanto minimal-ui(introduzida no iOS 7.1).

Chegou a notícia de que o iOS 8 beta4 havia sido removido minimal-uido Mobile Safari (consulte a seção Webkit nas Notas de versão do iOS 8 ), o que nos deixou pensando:

Q1 Ainda é possível ocultar a barra de endereço no Mobile Safari?

Tanto quanto sabemos, o iOS 7 não responde mais ao window.scrollTohack, o que sugere que precisamos viver com um espaço menor na tela, a menos que adotemos um layout ou uso vertical mobile-web-app-capable.

Q2 Ainda é possível ter uma experiência semelhante em tela cheia?

Por tela cheia suave, eu realmente quero dizer sem usar a mobile-web-app-capablemeta tag.

Nosso aplicativo da web foi desenvolvido para ser acessível, qualquer página pode ser marcada ou compartilhada usando o menu nativo do navegador. Ao adicionar mobile-web-app-capable, impedimos que os usuários invoquem esse menu (quando ele é salvo na tela inicial), o que confunde e antagoniza os usuários.

minimal-uicostumava ser o meio termo, ocultando o menu por padrão, mas mantendo-o acessível com um toque - embora a Apple possa removê-lo devido a outras preocupações de acessibilidade (como usuários que não sabem onde tocar para ativar o menu).

Q3 Uma experiência em tela cheia vale a pena?

Parece que uma API de tela cheia não chegará ao iOS tão cedo, mas mesmo assim, não vejo como o menu será mantido acessível (o mesmo vale para o Chrome no Android).

Nesse caso, talvez devêssemos deixar o safari móvel como está e considerar a altura da janela de visualização (para iPhone 5+, é 460 = 568 - 108, em que 108 inclui a barra do SO, a barra de endereços e o menu de navegação; para o iPhone 4 ou mais velho, é 372).

Adoraria ouvir algumas alternativas (além de criar um aplicativo nativo).

bitinn
fonte
consulte stackoverflow.com/questions/18793072/… para obter mais detalhes sobre por que a interface do usuário mínima pode ser crucial para algum aplicativo.
bitinn
1
Eu encontrei o mesmo problema no iOS 7, pois estamos tentando criar um aplicativo Web com eventos de deslize / rolagem, mas testei em eventos de rolagem no iOS8 Beta 4 e .. eles funcionam. ios8-scroll-events.heroku.com Não tenho certeza se isso ajuda, mas .. você tem isso para você.
Devin McInnis
Corri para o mesmo problema. No momento, apenas o javascript "corrige", pois a função calc () abaixo é a única resposta. Mantenha este tópico atualizado, se você souber uma decisão melhor. Cumprimentos.
A1exandr

Respostas:

86

A propriedade minimal-ui viewport não é mais suportada no iOS 8. No entanto, a minimal-ui em si não se foi. O usuário pode inserir a interface do usuário mínima com um gesto de "arrastar o toque para baixo".

Existem várias pré-condições e obstáculos para gerenciar o estado da visualização, por exemplo, para que o mínimo de interface do usuário funcione, é necessário que haja conteúdo suficiente para permitir que o usuário role; para que o mínimo de interface do usuário persista, a rolagem da janela deve ser deslocada no carregamento da página e após a alteração da orientação. No entanto, não há como calcular as dimensões da interface do screenusuário mínima usando a variável e, portanto, não há como saber quando o usuário está na interface do usuário com antecedência.

Essas observações são resultado de pesquisas como parte do desenvolvimento do Brim - view manager para iOS 8 . A implementação final funciona da seguinte maneira:

Quando a página é carregada, o Brim cria um elemento na esteira. O elemento da esteira é usado para dar espaço ao usuário para rolar. A presença do elemento da esteira garante que o usuário possa acessar a visualização da interface do usuário mínima e que continue a persistir se o usuário recarregar a página ou alterar a orientação do dispositivo. É invisível para o usuário o tempo todo. Este elemento tem um ID brim-treadmill.

Ao carregar a página ou depois de alterar a orientação, o Brim está usando o Scream para detectar se a página está na visualização mínima-interface do usuário (a página que estava anteriormente na interface mínima e foi recarregada permanecerá na interface mínima se a altura do conteúdo for maior que a altura da janela de visualização).

Quando a página está na minimal-ui, o Brim desativará a rolagem do documento (isso é feito de uma maneira segura que não afeta o conteúdo do elemento principal). Desativar a rolagem de documentos evita acidentalmente deixar o mínimo de interface do usuário ao rolar para cima. De acordo com a especificação original do iOS 7.1, tocar na barra superior traz de volta o restante do chrome.

O resultado final é assim:

Brim no simulador iOS.

Para fins de documentação, e caso você prefira escrever sua própria implementação, vale a pena notar que não é possível usar o Scream para detectar se o dispositivo está na interface do usuário mínima logo após o evento de mudança de orientação porque as windowdimensões não refletem a nova orientação até o a animação de rotação terminou. Você deve anexar um ouvinte ao evento directionchangeend .

Grito e mudança de orientação foram desenvolvidos como parte deste projeto.

Gajus
fonte
3
Esta é a maneira mais expansiva do que a minha resposta original, marcada como nova resposta até mesmo melhor solução chega :)
bitinn
4
Parece legal! Posso forçar o mínimo de interface do usuário sem a rolagem inicial?
INT
50
Esta realmente nunca termina história. Sou desenvolvedor de jogos em HTML e o mínimo de interface do usuário no iOS 7.1 funcionou bem - era a única maneira de ter um aplicativo rodando em tela cheia E ao mesmo tempo tocando na parte inferior da tela. As soluções com passagem de página são boas, mas não são boas o suficiente :( Apple, precisamos da implementação adequada da API de tela cheia para jogos, por favor.
Petr Urban
4
@ Pet: Eu não poderia concordar mais. Quando Esta correção foi anunciada na versão 7.1, lançamos rapidamente um novo fluxo de compra do checkout, que fixou o CTA principal na parte inferior da tela. Isso funcionou e converteu muito bem! Parecia muito "nativo" e sem costura. Qual eu acho que é o problema exato. Se você pensar bem, não é do interesse da Apple que os aplicativos da Web pareçam nativos. Na verdade, é um conflito de interesse direto com o monopólio da App Store. Esta é a IMO, a única razão válida pela qual um recurso que faz tanto sentido foi corrigido e removido intencionalmente. # My2Cents :)
Jose Browne
2
@PetrUrban Estou convencido de que a Apple prefere que você publique seu jogo como um aplicativo de captura de chamadas do que permitir que você sirva pela web. Sua recente decisão de permitir bloqueadores de anúncios para safari cimenta essa idéia.
Patrick Gunderson
20

Como não há uma maneira programática de imitar minimal-ui, criamos uma solução alternativa diferente, usando uma calc()altura conhecida da barra de endereço iOS para nossa vantagem:

A página de demonstração a seguir ( também disponível em gist, mais detalhes técnicos ) solicitará que o usuário role, o que aciona uma tela cheia suave (ocultar barra de menus / menu), onde o cabeçalho e o conteúdo preenchem a nova janela de exibição.

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Scroll Test</title>

    <style>
        html, body {
            height: 100%;
        }

        html {
            background-color: red;
        }

        body {
            background-color: blue;
            margin: 0;
        }

        div.header {
            width: 100%;
            height: 40px;
            background-color: green;
            overflow: hidden;
        }

        div.content {
            height: 100%;
            height: calc(100% - 40px);
            width: 100%;
            background-color: purple;
            overflow: hidden;
        }

        div.cover {
            position: absolute;
            top: 0;
            left: 0;
            z-index: 100;
            width: 100%;
            height: 100%;
            overflow: hidden;
            background-color: rgba(0, 0, 0, 0.5);
            color: #fff;
            display: none;
        }

        @media screen and (width: 320px) {
            html {
                height: calc(100% + 72px);
            }

            div.cover {
                display: block;
            }
        }
    </style>
    <script>
        var timeout;

        window.addEventListener('scroll', function(ev) {

            if (timeout) {
                clearTimeout(timeout);
            }

            timeout = setTimeout(function() {

                if (window.scrollY > 0) {
                    var cover = document.querySelector('div.cover');
                    cover.style.display = 'none';
                }

            }, 200);

        });
    </script>
</head>
<body>

    <div class="header">
        <p>header</p>
    </div>
    <div class="content">
        <p>content</p>
    </div>
    <div class="cover">
        <p>scroll to soft fullscreen</p>
    </div>

</body>
</html>
bitinn
fonte
10

Apenas diga adeus ao minimal-ui (por enquanto)

É verdade, minimal-uipode ser útil e prejudicial, e suponho que o compromisso agora tenha outro equilíbrio, a favor de iPhones novos e maiores.

Estive lidando com o problema enquanto trabalhava com minha estrutura js para aplicativos HTML5. Depois de muitas tentativas de soluções, cada uma com suas desvantagens, desisti de considerar que o espaço perdido nos iPhones era anterior a 6. Dada a situação, acho que o único comportamento sólido e previsível é um predeterminado.

Em resumo, acabei impedindo qualquer forma de interface do usuário mínima , pelo menos a altura da minha tela é sempre a mesma e você sempre sabe qual o espaço real que você tem para o seu aplicativo.

Com a ajuda do tempo, usuários suficientes terão mais espaço.


EDITAR

Como eu faço isso

Isso é um pouco simplificado, para fins de demonstração, mas deve funcionar para você. Supondo que você tenha um contêiner principal

html, body, #main {
  height: 100%;
  width: 100%;
  overflow: hidden;
}
.view {
  width: 100%;
  height: 100%;
  overflow: scroll;
}

Então:

  1. depois, com js, defino #maina altura da janela para a altura disponível da janela. Isso também ajuda a lidar com outros erros de rolagem encontrados no iOS e no Android. Isso também significa que você precisa lidar com como atualizá-lo, observe isso;

  2. Eu bloqueio a rolagem excessiva ao atingir os limites da rolagem. Este é um pouco mais profundo no meu código, mas acho que você também pode seguir o princípio desta resposta para obter funcionalidades básicas. Eu acho que poderia flickr um pouco, mas vai fazer o trabalho.


Veja a demonstração (em um iPhone)

Como nota de rodapé: esse aplicativo também pode ser marcado como favorito, pois usa um roteamento interno para endereços com hash, mas também adicionei um prompt de usuários do iOS para adicionar em casa. Eu sinto que dessa maneira ajuda a fidelizar e retornar visitantes (e assim o espaço perdido está de volta).

Francesco Frapporti
fonte
Desabilitar o mínimo de interface do usuário parece muito razoável para mim. Por favor, inclua uma breve descrição de como fazer isso!
István Pálinkás
Você está certo, acrescentei um pouco de como fazer. Muitas outras maneiras irão funcionar.
Francesco Frapporti
1
Sua demonstração não funciona em iOS8, de acordo com o meu iPhone 5.
dmr07
Obrigado por me informar, deve ser uma atualização porque costumava funcionar. Você está no safari? O que você quer dizer exatamente com isso não funciona?
Francesco Frapporti
7

A maneira mais fácil de corrigir isso foi definir a altura dos elementos body e html para 100,1% para qualquer solicitação em que o agente do usuário fosse um iphone. Isso só funciona no modo paisagem, mas é tudo o que eu precisava.

html.iphone, 
html.iphone body { height: 100.1%; }

Confira em https://www.360jungle.com/virtual-tour/25

Stephen Garside
fonte
Obrigado @Stephen. height: 100,1% me ajudaram. No entanto, quando abri o 360jungle.com/virtual-tour/25 no iPhone (iOS 11.1.1) Safari e cliquei nos botões na parte inferior, o endereço e a barra de ferramentas apareceram. Isso ocorre porque os botões estão muito perto do final da exibição. Eu acho que seria melhor movê-los para outro lugar no modo móvel.
Téwa 21/12/19
2

O problema raiz aqui parece que o safari iOS8 não oculta a barra de endereço ao rolar para baixo se o conteúdo for igual ou menor que o visor.

Como você já descobriu, adicionar um pouco de preenchimento na parte inferior contorna esse problema:

html {
    /* enough space to scroll up to get fullscreen on iOS8 */
    padding-bottom: 80px;
}
// sort of emulate safari's "bounce back to top" scroll
window.addEventListener('scroll', function(ev) {
    // avoids scrolling when the focused element is e.g. an input
    if (
        !document.activeElement
        || document.activeElement === document.body
    ) {
        document.body.scrollIntoViewIfNeeded(true);
    }
});

O css acima deve ser aplicado condicionalmente, por exemplo, com o sniffing do UA adicionando uma gt-ios8classe a <html>.

Navalha
fonte
1
O que esse JS faz exatamente?
Ben Sinclair
Se você estiver se referindo scrollIntoViewIfNeeded, é uma derivação não padrão de scrollIntoView( developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView ). Como o nome indica, o método rola o elemento para a exibição. trueO parâmetro diz para alinhar a vista com a parte superior do elemento. Isso, na verdade, deve impedir você de rolar. A implementação é falha, no entanto.
Gajus 4/11
1

Quero comentar / responder parcialmente / compartilhar meus pensamentos. Estou usando a técnica overflow-y: scroll para um grande projeto próximo. Usá-lo tem duas vantagens principais.

a) Você pode usar uma gaveta com botões de ação na parte inferior da tela; se o documento rolar e a barra inferior desaparecer, tocar em um botão localizado na parte inferior da tela fará com que a barra inferior apareça e depois clique. Além disso, o modo como isso funciona causa problemas com os modais que possuem botões na parte inferior.

b) Ao usar um elemento excedido, as únicas coisas que são repintadas em caso de grandes alterações de css são aquelas na tela visível. Isso me deu um enorme aumento de desempenho ao usar o javascript para alterar o CSS de vários elementos em tempo real. Por exemplo, se você tiver uma lista de 20 elementos, precisará repintar e apenas dois deles aparecerão na tela no elemento excedido, apenas esses serão repintados enquanto o restante será repintado ao rolar. Sem ele, todos os 20 elementos são repintados.

... é claro que depende do projeto e se você precisar de alguma das funcionalidades que eu mencionei. O Google usa elementos em excesso no Gmail para usar a funcionalidade descrita em a). Imo, vale a pena, mesmo considerando a pequena altura em iphones mais antigos (372px, como você disse).

patinete
fonte
1

É possível, usando algo como o exemplo abaixo que eu juntei com a ajuda do trabalho de ( https://gist.github.com/bitinn/1700068a276fb29740a7 ) que não funcionou bem no iOS 11:

Aqui está o código modificado que funciona no iOS 11.03. Comente se ele funcionou para você.

A chave está adicionando algum tamanho ao BODY para que o navegador possa rolar, ex: height: calc (100% + 40px);

Exemplo completo abaixo e link para visualização em seu navegador (teste!)

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CodeHots iOS WebApp Minimal UI via Scroll Test</title>

    <style>
        html, body {
            height: 100%;
        }
        html {
            background-color: red;
        }
        body {
            background-color: blue;
            /* important to allow page to scroll */
            height: calc(100% + 40px);
            margin: 0;
        }
        div.header {
            width: 100%;
            height: 40px;
            background-color: green;
            overflow: hidden;
        }
        div.content {
            height: 100%;
            height: calc(100% - 40px);
            width: 100%;
            background-color: purple;
            overflow: hidden;
        }
        div.cover {
            position: absolute;
            top: 0;
            left: 0;
            z-index: 100;
            width: 100%;
            height: 100%;
            overflow: hidden;
            background-color: rgba(0, 0, 0, 0.5);
            color: #fff;
            display: none;
        }
        @media screen and (width: 320px) {
            html {
                height: calc(100% + 72px);
            }
            div.cover {
                display: block;
            }
        }
    </style>
    <script>
        var timeout;

        function interceptTouchMove(){
            // and disable the touchmove features 
            window.addEventListener("touchmove", (event)=>{
                if (!event.target.classList.contains('scrollable')) {
                    // no more scrolling
                    event.preventDefault();
                }
            }, false); 
        }

        function scrollDetect(event){
            // wait for the result to settle
            if( timeout ) clearTimeout(timeout);

            timeout = setTimeout(function() {
                console.log( 'scrolled up detected..' );
                if (window.scrollY > 35) {
                    console.log( ' .. moved up enough to go into minimal UI mode. cover off and locking touchmove!');
                    // hide the fixed scroll-cover
                    var cover = document.querySelector('div.cover');
                    cover.style.display = 'none';

                    // push back down to designated start-point. (as it sometimes overscrolls (this is jQuery implementation I used))
                    window.scrollY = 40;

                    // and disable the touchmove features 
                    interceptTouchMove();

                    // turn off scroll checker
                    window.removeEventListener('scroll', scrollDetect );                
                }
            }, 200);            
        }

        // listen to scroll to know when in minimal-ui mode.
        window.addEventListener('scroll', scrollDetect, false );
    </script>
</head>
<body>

    <div class="header">
        <p>header zone</p>
    </div>
    <div class="content">
        <p>content</p>
    </div>
    <div class="cover">
        <p>scroll to soft fullscreen</p>
    </div>

</body>

Exemplo de link completo aqui: https://repos.codehot.tech/misc/ios-webapp-example2.html

Code Freeze
fonte
1

É possível fazer com que um aplicativo Web seja executado em tela cheia no iOS e no Android, ele é chamado de PWA e, depois de muito trabalho, foi a única maneira de contornar esse problema.

Os PWAs abrem várias opções interessantes de desenvolvimento que não devem ser perdidas. Já fiz algumas, confira este Manual de licitação pública e privada para designers (espanhol). E aqui está uma explicação em inglês do site CosmicJS

ganar
fonte
-2

Eu não fiz web design para iOS, mas pelo que me lembro de ter visto nas sessões da WWDC e na documentação, a barra de pesquisa no Mobile Safari e as barras de navegação em todo o sistema operacional agora serão automaticamente redimensionadas e encolhidas para mostrar mais do seu conteúdo.

Você pode testar isso no Safari em um iPhone e perceber que, quando você rola para baixo para ver mais conteúdos em uma página, a barra de navegação / pesquisa é ocultada automaticamente.

Talvez deixar a barra de endereço / barra de navegação como está e não criar uma experiência em tela cheia seja o melhor. Não vejo a Apple fazendo isso tão cedo. E, no máximo, eles não estão controlando automaticamente quando a barra de endereço é exibida / oculta.

Claro, você está perdendo espaço na tela, especialmente em um iPhone 4 ou 4S, mas não parece haver uma alternativa no Beta 4.

iFeli
fonte
1
Eu conhecia esse recurso do iOS7 +, mas veja minha explicação acima: como a altura do documento é exatamente a mesma da janela de exibição do navegador, o navegador móvel não oculta a barra de endereços / menu de navegação , pois nenhuma rolagem ocorre no nível do documento.
bitinn
1
Isso pode ser uma limitação agora que o Beta 4 removeu esse recurso. É possível e provável que a Apple esteja controlando a barra de endereços automaticamente e impedindo os desenvolvedores de acessá-la.
IFeli
8
I haven't done web design for iOS- se você está criando web design, faz para todas as plataformas. Porque a web está em todas as plataformas.
problema é o seguinte
4
@ Sei que sei que trabalhar na web é universal, mas cada navegador e suas estruturas subjacentes têm atributos CSS específicos. Portanto, o Chrome pode ter alguns atributos indisponíveis no Safari, FireFox e vice-versa.
iFeli