Le titre sera différent

Si vous développez un produit pour le marché de masse, les personnes très malvoyantes l'utilisent probablement. Si vous vous efforcez de créer des interfaces conviviales, vous devez le faire de manière pratique pour tous les clients, y compris les personnes malvoyantes. Je pense que nous l'oublions souvent. Et il est temps de le réparer.



J'ai saisi la requête «livraison de pizza» dans la recherche sur l'App Store, téléchargé les 24 premières applications et vérifié laquelle d'entre elles offrait une interface pour les personnes malvoyantes.



2 sur 24 . Et l'un des deux, semble-t-il, l'a fait par accident: à mesure que la taille de la police augmente, toute l'interface «flotte» et devient plus difficile à utiliser. C'est triste.

550 000 personnes utilisent l'application iOS Dodo Pizza chaque mois. Même si 1% de nos utilisateurs ont une police agrandie, ce sont 5500 personnes qui sont mal à l'aise avec notre application. Nous allons le corriger.

Ajouter un support de type dynamique


  1. Nous utilisons des styles de texte système dynamiques au lieu de styles statiques.
  2. Vous pouvez également activer la coche Ajuster automatiquement la police sur les étiquettes des story-boards. Ou, si l'étiquette dans le bouton ou est créée via le code, nous adjustsFontForContentSizeCategory sur son paramètre adjustsFontForContentSizeCategory .
  3. Nous apprenons à l'interface à s'étendre à différentes tailles de police:
    - Nous utilisons le calcul automatique de la taille des cellules lorsque nous le pouvons.
    - Là où nous ne pouvons pas - nous obtenons les paramètres de taille de police actuels et répondons aux modifications de la méthode traitCollectionDidChange .
  4. Nous obtenons une interface impossible à utiliser.




Nous changeons l'interface pour qu'elle puisse être utilisée


Nous reculons et commençons à penser comment bien faire tout.

Utilisez correctement la place dans le menu


Maintenant, il y a beaucoup d'espace vide sous l'image de la pizza. Essayons de mettre une image au-dessus du nom: de cette façon, elle deviendra plus grande et l'espace vide disparaîtra. Pour ce faire, nous enveloppons le conteneur d'image et de UIStackView avec tout le reste dans UIStackView , puis nous UIStackView la direction de la vue de la pile si nécessaire.



Nous n'avons pas de séparateurs entre les éléments du menu, c'est pourquoi lorsque la taille est grande, les cellules commencent à «coller ensemble» et le prix de la pizza est trop proche de l'image de la prochaine pizza. Essayons d'ajouter un séparateur.



Pas ça. Tout d'abord, ça a l'air moyen. Deuxièmement, il sera difficile à voir pour les personnes malvoyantes. Même repeint du gris au noir.

Nous le supprimons et essayons simplement d'augmenter Internet entre les cellules.



Maintenant.

Sous-total: utilisez plus d'espace, les yeux sautent moins d'une ligne à l'autre, la lecture est devenue plus facile.

Nous améliorons l'étirement et le retrait


Vous pouvez maintenant augmenter la largeur du bouton ajouter au panier, sinon il flottait vers la gauche et n'est pas sous votre doigt, bien qu'il y ait beaucoup d'espace vide à droite. Vous pouvez, bien sûr, simplement le déplacer vers la droite, mais cela sera gênant pour les gauchers et, en général, nous ferons un meilleur geste que non compressé. Et nous allons rendre le trait plus gras, et maintenant il n'est pas cohérent avec la police.



Je regarde tout cela et je comprends que la photo de pizza, bien sûr, est très énorme. Essayons de le cacher, peut-être sans images tu peux vivre.



En général, un menu sans photos n'a pas perdu beaucoup d'informations, mais maintenant un élément de menu interfère presque toujours avec l'écran d'un iPhone 6S. Mais il est devenu moins attrayant, Drool ne coule pas lors du défilement. Tels. Pour l'instant, laissons cela comme ça, réfléchissons bien et peut-être reviendrons plus tard sur la photo.

N'oubliez pas de cocher "live"


Maintenant catégories. En général, même avec la première approche, cela s'est avéré tolérable. Allumez-en un nouveau.



J'ai essayé de parcourir le menu et de basculer entre les catégories. Néanmoins, cela s'est mal passé: tout s'effondre dans l'action. Lorsque vous faites défiler le menu, les catégories changent automatiquement et, sur de si grandes broches, elles attirent trop l'attention.

UICollectionView par un bouton qui appellera UIActionSheet .



Voooot. Maintenant, vous pouvez prendre sur le panneau supérieur, où la ville, les stocks, l'adresse et le code promotionnel.

N'oubliez pas les très longues files d'attente


Tout d'abord, faisons un choix de la ville. Il n'y a rien de compliqué avec la police du bouton, mais il est intéressant d'apprendre aux "triangles" à grandir avec la police. Dans notre cas, le triangle a été transformé en icône dans le bouton, qui est déplacé vers la droite via CGAffineTransform . Une autre option consiste à collecter NSAttributedString partir du texte et de l'icône en triangle, puis de tout alimenter vers le bouton. Pour normaliser l'icône, vous pouvez utiliser une image vectorielle, qui doit nécessairement être dans les actifs avec la coche Préserver les données vectorielles.


L'icône du triangle est noire et est peinte en blanc à travers le code. Et pour une raison quelconque, avec la taille de texte standard, des artefacts sous forme de bordures noires sortent dessus. C'est marrant Pas vraiment. Il a été guéri en mettant une icône qui était à l'origine blanche dans les actifs.

Maintenant on étire les dodo-roubles, tout est simple:



Et maintenant, la question est: que se passera-t-il si le nom de la ville s'avère long et que nous avons de nombreux dodo-roubles? En théorie, vous devez raccourcir le nom de la ville. Rappelez-vous ce que j'ai dit à propos de la deuxième option pour ajouter une telle icône à un bouton, via NSAttributedString ? J'ai essayé et maintenant il y a un problème quand on réduit le titre, l'icône triangle disparaît, car maintenant elle fait partie du titre. Stosh. Nous devrons retourner la logique de déplacer l'icône à travers les transformations.
Si vous connaissez un moyen pratique de déplacer l'icône du bouton vers la droite et de la mettre à l'échelle avec la police dans l'en-tête - jetez-la dans les commentaires, s'il vous plaît.

Cram dans


Enfin des stocks. Ici, vous devez vous asseoir et réfléchir. Le titre peut être long et même maintenant, il ne tient parfois pas sur une seule ligne. Sur une grande taille, il ne rentrera pas du tout bien. Si vous faites le caoutchouc du panneau orange supérieur et laissez le titre de l'action dans une grande taille occuper plusieurs lignes, le bloc supérieur mangera la moitié de l'écran même sur les grands iPhones, et vous n'aurez pas à vous souvenir de 4S. Ce n'est pas le cas. Vous pouvez jouer avec une mise en page à l'intérieur de la zone d'action: faire le carré de l'image et prendre la place vacante comme titre. Mais les images des stocks sont personnalisées dans un format spécifique et ne s'afficheront pas correctement dans un autre. C'est impossible.

Compliqué

Donc, mais vous pouvez à nouveau supprimer complètement les images et occuper toute la place avec un titre.



Ouais, ça l'est. Les mains démangent pour coloriser l'arrière-plan sous le titre de l'action, mais cela affectera négativement la lisibilité. Et nous, comme, essayons de l'améliorer. Nous ne peignons donc rien et passons aux deux boutons restants concernant l'adresse et les codes promotionnels.

Nous travaillons avec des restrictions strictes


Les titres de ces boutons sont irréductibles. Mais s'ils ne sont pas réduits, les boutons se glisseront les uns sur les autres. Et oui, vous ne pouvez pas masquer ces boutons.

Quand j'ai refait le stock, je ne voulais pas augmenter la hauteur du panneau orange supérieur. Cela semble devoir. C'est bien qu'ils ne l'aient pas augmenté à ce moment-là, sinon maintenant il y aurait aduha. En général, je vais sélectionner une ligne pour chaque bouton.



Ufff, c'est tout. En ce qui concerne les photos désactivées dans le menu, je ne suis toujours pas sûr. Alternativement, vous ne pouvez afficher que la moitié des images de pizza au lieu d'un cercle entier, mais nous avons des demi-pizzas droites dans le menu, donc cela ne fonctionnera pas, nous pouvons confondre les utilisateurs.

Comparons la première approche avec le résultat final:



Comparez maintenant «avant» et «après» avec une simulation de mauvaise vision:



N'ayez pas peur de changer l'interface et les commandes. Il n'y a rien de mal à ce que quelqu'un voit un autre bouton ou, par exemple, un curseur. Et ce n'est pas fatal si quelqu'un ne voit pas quelque chose ou si le titre est différent.
Et nous n'avons pas touché le UITabBarController , car avec une grande taille de texte, il peut afficher l'icône et le titre de l'onglet de la même manière que iOS montre le changement de volume.

Nous montrons comment tout cela fonctionne à l'intérieur


Chaque composant d'interface utilisateur logique de l'application iOS Dodo Pizza est alloué à un UIViewController distinct. Chacun de ces contrôleurs a une UIView allouée à un fichier distinct. Vous pouvez en savoir plus à ce sujet dans nos articles:

Contrôleur, allez-y doucement! Nous sortons le code dans UIView
Contrôleur d'oignon. Nous cassons les écrans en plusieurs parties

La suppression de composants d'interface utilisateur logiques dans un UIViewController distinct UIViewController considérablement simplifié la tâche de modification des interfaces vers différents états. Nous vous recommandons d'essayer cette approche, même si vous ne prévoyez pas d'ajouter la prise en charge de Dynamic Type - il est plus facile de contrôler l'état des écrans: répondez aux changements d'autorisation, de droits, de rôles, etc.

Alors voilà. Nous ajoutons une couche supplémentaire entre un tel composant d'interface utilisateur et son conteneur parent. Nous l'avons appelé StateViewController .


Le contrôleur avec le menu intègre le contrôleur d'état, et il intègre déjà la collection - ou le contrôleur de button .

Ce StateViewController affiche tel ou tel composant d'interface utilisateur en fonction d'une situation.

Pour ce faire, StateViewController doit connaître ses états et les changer si nécessaire.

Dans cet exemple, StateViewController basculera la sélection des catégories dans le menu de la collection au bouton et vice versa. Et dans le cas d'un affichage «normal», et dans le cas d'un affichage pour les malvoyants, le sélecteur doit pouvoir faire les mêmes choses:

  • Afficher la liste des catégories.
  • Mettez en surbrillance la catégorie sélectionnée.
  • Mettre à jour la liste des catégories.
  • Signaler que la catégorie "est sorti".

Sentez-vous cette merveilleuse odeur de petites bûches fraîches? Et, non, c'est une équipe de pizza livrée par api mobile. Pause de 5 minutes.

2 tranches plus tard
"... Eh bien, nous emballons nos composants comme ça pour sélectionner des catégories dans les protocoles, ET ILS SONT IMMÉDIATEMENT!"
Astuce: lancez l'inspecteur d'accessibilité pour vérifier facilement la façon dont l'interface réagit aux modifications des paramètres de mosaïque dynamique. Pour ce faire, dans le Xcode ouvert, cliquez sur Xcode → Ouvrir l'outil de développement → Inspecteur d'accessibilité, sélectionnez le simulateur dans l'appareil et accédez au dernier onglet

Autre astuce: retirez le contrôle dynamo taip sur l'iPhone (pas sur le simulateur) au Control Center pour changer facilement et rapidement la taille du texte. Pour ce faire, sur un iPhone, accédez à Paramètres → Centre de contrôle → Personnaliser les contrôles et ajoutez la taille du texte.

Nous avons appelé le sélecteur de catégorie habituel CategoriesCollectionViewController , et pour les malvoyants - CategoriesButtonViewController . Leur protocole commun est appelé CategoriesPickerProtocol . Le contrôleur d'état général est CategoriesStateViewController .

Nous décrivons les états possibles dans notre CategoriesStateViewController :

 private enum State { case collection, button } 

Nous lui apprenons à montrer le contrôleur souhaité pour chaque état:

 private var state: State = .collection { didSet { if state != oldValue { updateViewController(for: state) } } } private func updateViewController(for state: State) { let viewController = self.viewController(for: state) self.updateController(with: viewController) } private func viewController(for state: State) { switch state { case .collection: return CategoriesCollectionViewController.instantiateFromStoryboard() case .button: return CategoriesButtonViewController.instantiateFromStoryboard() } } 

instantiateFromStoryboard() - une méthode d'une extension auto-écrite à un contrôleur de vue, crée une instance de contrôleur à partir de storyboards s'ils ont le même nom. Le code se trouve dans le code source à la fin de l'article.

 override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) self.updateStateToCurrentContentSize() } private func updateStateToCurrentContentSize() { let contentSize = self.traitCollection.preferredContentSizeCategory self.updateState(to: contentSize) } private func updateState(to contentSize: UIContentSizeCategory) { self.state = contentSize.isAccessibilityCategory ? .button : .collection } 

Nous décrivons le protocole CategoriesPickerProtocol , en ajoutant simultanément deux protocoles supplémentaires: pour le délégué et pour la donnée.

 protocol CategoriesPickerProtocol where Self: UIViewController { var datasource: CategoriesDatasource? { get set } var delegate: CategoriesDelegate? { get set } func select(_ category: ProductCategoryModule.ProductCategoryViewModel) func updateCategories() var selectedCategory: ProductCategoryModule.ProductCategoryViewModel? { get } } protocol CategoriesDatasource: class { var categories: [ProductCategoryModule.ProductCategoryViewModel] { get } func index(of category: Product.ProductCategory) -> Int } protocol CategoriesDelegate: class { func productCategoriesView(_ categoriesPicker: CategoriesPickerProtocol, didSelect category: ProductCategoryModule.ProductCategoryViewModel) } 

Cela n'a aucun sens de montrer l'implémentation, c'est juste que chaque piker affiche les catégories et signale les changements à la hausse.

Un exemple détaillé de l'utilisation de contrôleurs d'état pour le taype dynamique peut être trouvé dans mon dépôt sur GitHub .

Au fait, nous nous développons

Source: https://habr.com/ru/post/fr452226/


All Articles