Guides pratiques

Découvrez Cahier : un nouvel exemple GitHub Android pour la productivité et la créativité sur grand écran

Temps de lecture : 11 min
Chris Assigbe
Ingénieur chargé des relations avec les développeurs

L'API Ink est désormais en bêta et peut être intégrée à votre application. Cette étape a été rendue possible grâce aux précieux commentaires des développeurs, qui ont permis d'améliorer en continu les performances, la stabilité et la qualité visuelle de l'API.

Les applications Google, telles que Google Docs, Pixel Studio, Google Photos, Chrome PDF, Youtube Effect Maker et les fonctionnalités uniques sur Android, comme Entourer pour chercher, utilisent toutes les dernières API. 

Pour marquer cette étape importante, nous sommes heureux d'annoncer le lancement de Cahier, un exemple d'application de prise de notes complet optimisé pour les appareils Android de toutes tailles, en particulier les tablettes et les téléphones pliables.

Qu'est-ce que Cahier ?

Cahier est une application exemple conçue pour vous montrer comment créer une application qui permet aux utilisateurs de capturer et d'organiser leurs pensées en combinant du texte, des dessins et des images. 

L'exemple peut servir de référence pour améliorer la productivité et la créativité des utilisateurs sur les grands écrans. Il présente les bonnes pratiques pour créer de telles expériences, en aidant les développeurs à mieux comprendre et à adopter les puissantes API et techniques associées. Cet article vous présente les principales fonctionnalités de Cahier, les API clés et les décisions architecturales qui font de cet exemple une excellente référence pour vos propres applications.

Voici quelques-unes des principales fonctionnalités présentées dans l'exemple :

  • Création de notes polyvalente : montre comment implémenter un système de création de contenu flexible qui prend en charge plusieurs formats dans une même note, y compris du texte, des dessins à main levée et des pièces jointes d'images.
  • Outils d'encrage créatifs : implémente une expérience de dessin hautes performances et à faible latence à l'aide de l'API Ink. L'exemple fournit un exemple pratique d'intégration de différents pinceaux, d'un sélecteur de couleurs, d'une fonctionnalité d'annulation/rétablissement et d'un outil d'effacement.
  • Intégration de contenu fluide avec le glisser-déposer : montre comment gérer le contenu entrant et sortant à l'aide du glisser-déposer. Cela inclut l'acceptation des images déposées depuis d'autres applications et la possibilité pour les utilisateurs de faire glisser du contenu hors de votre application pour le partager facilement.
  • Organiser vos notes : marquez vos notes comme favorites pour y accéder rapidement. Filtrez la vue pour rester organisé.
  • Architecture "hors connexion d'abord" : l'application est conçue avec une architecture "hors connexion d'abord" à l'aide de Room, ce qui garantit que toutes les données sont enregistrées localement et que l'application reste entièrement fonctionnelle sans connexion Internet.
  • Prise en charge puissante du multifenêtre et des instances multiples : montre comment prendre en charge les instances multiples, ce qui permet à votre application d'être lancée dans plusieurs fenêtres afin que les utilisateurs puissent travailler sur différentes notes côte à côte, ce qui améliore la productivité et la créativité sur les grands écrans.
  • Interface utilisateur adaptative pour tous les écrans : l'interface utilisateur s'adapte de manière fluide aux différentes tailles et orientations d'écran à l'aide de ListDetailPaneScaffold et NavigationSuiteScaffold pour offrir une expérience utilisateur optimisée sur les téléphones, les tablettes et les appareils pliables.
  • Intégration système approfondie : fournit un guide sur la façon de faire de votre application l'application de prise de notes par défaut sur Android 14 et versions ultérieures en répondant aux intents Notes à l'échelle du système, ce qui permet de capturer rapidement du contenu à partir de différents points d'entrée du système.

Conçue pour la productivité et la créativité sur les grands écrans

Pour le lancement initial, nous avons axé l'annonce sur quelques fonctionnalités clés qui font de Cahier une ressource d'apprentissage essentielle pour les cas d'utilisation liés à la productivité et à la créativité.

Une base d'adaptabilité

Cahier a été conçu pour être adaptatif dès le départ. L'exemple utilise la bibliothèque material3-adaptive, plus précisément ListDetailPaneScaffold et NavigationSuiteScaffold, pour adapter de manière fluide la mise en page de l'application à différentes tailles et orientations d'écran. Il s'agit d'un élément essentiel pour une application Android moderne, et Cahier fournit un exemple clair de la façon de l'implémenter efficacement.

Cahier adaptive UI built with Material 3 Adaptive library..gif

Cahier UI adaptatif créé avec la bibliothèque adaptative Material 3

Présentation des principales API et intégrations

L'exemple est axé sur la présentation d'API de productivité puissantes que vous pouvez exploiter dans vos propres applications, y compris :

Examen plus approfondi des API clés

Examinons plus en détail deux des API fondamentales que Cahier intègre pour offrir une expérience de prise de notes de première classe.

Créer des expériences d'encrage naturel avec l'API Ink

La saisie au stylet transforme les appareils à grand écran en blocs-notes et sketchbooks numériques. Pour vous aider à créer des expériences d'encrage fluides et naturelles, nous avons fait de l'API Ink un élément clé de l'exemple. L'API Ink permet de créer, d'afficher et de manipuler facilement de magnifiques traits d'encre avec une faible latence de premier ordre.

L'API Ink offre une architecture modulaire, ce qui vous permet de l'adapter à la pile et aux besoins spécifiques de votre application. Les modules d'API incluent les éléments suivants :

  • Modules de création (Compose –vues) : gérez les entrées d'écriture en temps réel pour créer des traits fluides avec la latence la plus faible possible sur un appareil.
    • Dans DrawingSurface, Cahier utilise le composable InProgressStrokes récemment introduit pour gérer les saisies au stylet ou tactiles en temps réel. Ce module est chargé de capturer les événements de pointeur et d'afficher les traits d'encre humide avec la latence la plus faible possible.
  • Module Traits : représente l'entrée d'encre et sa représentation visuelle. Lorsqu'un utilisateur termine de dessiner une ligne, le rappel onStrokesFinished fournit un objet Stroke finalisé/sec à l'application. Cet objet immuable, qui représente le tracé d'encre terminé, est ensuite géré dans DrawingCanvasViewModel.
  • Module de rendu : affiche efficacement les traits d'encre, ce qui permet de les combiner avec Jetpack Compose ou les vues Android.
  • Modules de pinceau (Compose – vues) : fournissent un moyen déclaratif de définir le style visuel des traits. Les dernières mises à jour (depuis la version alpha03) incluent un nouveau pinceau à ligne pointillée, particulièrement utile pour des fonctionnalités telles que la sélection au lasso. DrawingCanvasViewModel contient l'état de currentBrush. Une boîte à outils dans DrawingCanvas permet aux utilisateurs de sélectionner différentes familles de pinceaux (comme StockBrushes.pressurePen() ou StockBrushes.highlighter()) et de changer de couleur. Le ViewModel met à jour l'objet Brush, qui est ensuite utilisé par le composable InProgressStrokes pour les nouveaux traits.
  • Modules de géométrie (Compose – vues) : permettent de manipuler et d'analyser les traits pour des fonctionnalités telles que l'effacement et la sélection.
    • L'outil Gomme de la boîte à outils et la fonctionnalité de DrawingCanvasViewModel reposent sur le module de géométrie. Lorsque la gomme est active, elle crée un MutableParallelogram autour du tracé du geste de l'utilisateur. La gomme vérifie ensuite les intersections entre la forme et les cadres de délimitation des traits existants pour déterminer quels traits effacer, ce qui la rend intuitive et précise.
  • Module Storage : fournit des fonctionnalités de sérialisation et de désérialisation efficaces pour les données d'encre, ce qui permet de réduire considérablement la taille du disque et du réseau. Pour enregistrer les dessins, Cahier conserve les objets Stroke dans sa base de données Room. Dans Converters, l'exemple utilise la fonction encode du module de stockage pour sérialiser StrokeInputBatch (les données brutes des points) en ByteArray. Le tableau d'octets, ainsi que les propriétés du pinceau, sont enregistrés sous forme de chaîne JSON. La fonction decode permet de reconstruire les traits lorsqu'une note est chargée.
orion.png

Au-delà de ces modules de base, les mises à jour récentes ont étendu les capacités de l'API Ink :

  • De nouvelles API expérimentales pour les objets BrushFamily personnalisés permettent aux développeurs de créer des types de pinceaux créatifs et uniques, offrant ainsi la possibilité de créer des outils tels que les pinceaux Crayon et Pointeur laser.

Cahier utilise des pinceaux personnalisés, y compris le pinceau musical unique présenté ci-dessous, pour illustrer les possibilités créatives avancées.

Rainbow laser created with Ink API's custom brushes..gif

Laser arc-en-ciel créé avec les pinceaux personnalisés de l'API Ink

notes.png

Pinceau musical créé avec les pinceaux personnalisés de l'API Ink

  • Les modules d'interopérabilité Jetpack Compose natifs simplifient l'intégration des fonctionnalités d'encrage directement dans vos UI Compose pour une expérience de développement plus idiomatique et efficace.

L'API Ink offre plusieurs avantages qui en font le choix idéal pour les applications de productivité et de créativité par rapport à une implémentation personnalisée :

  • Facilité d'utilisation : l'API Ink élimine la complexité des graphiques et de la géométrie, ce qui vous permet de vous concentrer sur les fonctionnalités de base de Cahier.
  • Performances : la prise en charge intégrée de la faible latence et le rendu optimisé garantissent une expérience d'encrage fluide et réactive.
  • Flexibilité : la conception modulaire vous permet de choisir les composants nécessaires, ce qui permet d'intégrer facilement l'API Ink à l'architecture de Cahier.

L'API Ink a déjà été adoptée dans de nombreuses applications Google, y compris pour l'annotation dans Docs et pour Entourer pour chercher, ainsi que dans des applications partenaires comme Orion Notes et PDF Scanner.

"L'API Ink était notre premier choix pour Entourer pour chercher. Grâce à leur documentation complète, l'intégration de l'API Ink a été un jeu d'enfant, ce qui nous a permis de créer notre premier prototype fonctionnel en une semaine seulement. La prise en charge des textures et des animations de pinceaux personnalisées d'Ink nous a permis d'itérer rapidement sur la conception des traits." - Jordan Komoda, ingénieur logiciel chez Google

Devenir l'application de notes par défaut avec le rôle "Notes"

La prise de notes est une fonctionnalité essentielle qui améliore la productivité des utilisateurs sur les appareils à grand écran. Grâce à la fonctionnalité de rôle Notes, les utilisateurs peuvent accéder à vos applications compatibles depuis l'écran de verrouillage ou pendant l'exécution d'autres applications. Cette fonctionnalité identifie et définit les applications de prise de notes par défaut à l'échelle du système, et leur accorde l'autorisation d'être lancées pour capturer du contenu. 

Implémentation dans Cahier

L'implémentation du rôle "Notes" implique quelques étapes clés, toutes illustrées dans l'exemple :

  1. Déclaration dans le fichier manifeste : l'application doit d'abord déclarer sa capacité à gérer les intents de prise de notes. Dans AndroidManifest.xml, Cahier inclut un <intent-filter> pour l'action android.intent.action.CREATE_NOTE. Cela indique au système que l'application est un candidat potentiel pour le rôle de notes.
  2. Vérification de l'état du rôle : SettingsViewModel utilise RoleManager d'Android pour déterminer l'état actuel. SettingsViewModel vérifie si le rôle Notes est disponible sur l'appareil (isRoleAvailable) et si Cahier détient actuellement ce rôle (isRoleHeld). Cet état est exposé à l'UI à l'aide de flux Kotlin.
  3. Demander le rôle : dans le fichier Settings.kt, un Button s'affiche pour l'utilisateur si le rôle est disponible, mais qu'il ne le détient pas. Lorsque l'utilisateur clique dessus, le bouton appelle la fonction requestNotesRole dans le ViewModel. La fonction crée un intent pour ouvrir l'écran des paramètres par défaut de l'application, où l'utilisateur peut sélectionner Cahier. Le processus est géré à l'aide de l'API rememberLauncherForActivityResult, qui gère le lancement de l'intent et la réception du résultat.
  4. Mise à jour de l'UI : une fois que l'utilisateur revient de l'écran des paramètres, le rappel ActivityResultLauncher déclenche une fonction dans ViewModel pour mettre à jour l'état du rôle, ce qui permet de s'assurer que l'UI reflète correctement si l'application est désormais celle par défaut.

Découvrez comment intégrer le rôle "Notes" dans votre application en consultant notre guide de création d'une application de prise de notes.

helloworld.png

Cahier lancé dans une fenêtre flottante comme application de prise de notes par défaut sur une tablette Lenovo

Une avancée majeure : Lenovo active le rôle "Notes"

Nous sommes ravis d'annoncer une avancée majeure pour la productivité sur les grands écrans Android : Lenovo a activé la prise en charge du rôle Notes sur les tablettes équipées d'Android 15 ou version ultérieure. Grâce à cette mise à jour, vous pouvez désormais mettre à jour vos applications de prise de notes pour permettre aux utilisateurs disposant d'appareils Lenovo compatibles de les définir comme applications par défaut. Ils pourront ainsi y accéder facilement depuis l'écran de verrouillage et débloquer les fonctionnalités de capture de contenu au niveau du système.

Cet engagement d'un OEM de premier plan démontre l'importance croissante du rôle des notes pour offrir une expérience utilisateur véritablement intégrée et productive sur Android. 

Multi-instance, multifenêtrage et fenêtrage du bureau

Pour être productif sur un grand écran, il faut gérer efficacement les informations et les workflows. C'est pourquoi Cahier est conçu pour exploiter pleinement les fonctionnalités avancées de fenêtrage d'Android, offrant ainsi un espace de travail flexible qui s'adapte aux besoins des utilisateurs. L'application est compatible avec :

  • Multifenêtrage : capacité fondamentale à s'exécuter aux côtés d'une autre application en mode Écran partagé ou en mode libre. C'est essentiel pour des tâches telles que la référence à une page Web lors de la prise de notes dans Cahier.
  • Multi-instance : c'est là que le véritable multitâche brille. Cahier permet aux utilisateurs d'ouvrir plusieurs fenêtres indépendantes de l'application simultanément. Imaginez comparer deux notes différentes côte à côte ou faire référence à une note de texte dans une fenêtre tout en travaillant sur un dessin dans une autre. Cahier montre comment gérer ces instances distinctes, chacune avec son propre état, transformant votre application en un outil puissant et multifacette.
  • Fenêtrage du bureau : lorsqu'une tablette ou un appareil pliable est connecté à un écran externe, le mode Bureau Android le transforme en poste de travail. Cahier étant conçu avec une UI adaptative et prenant en charge les instances multiples, l'application fonctionne parfaitement dans cet environnement. Les utilisateurs peuvent ouvrir, redimensionner et positionner plusieurs fenêtres Cahier comme sur un ordinateur de bureau traditionnel, ce qui permet d'effectuer des workflows complexes qui étaient auparavant hors de portée sur les appareils mobiles.
cahier-desktop-windowing.webp

Cahier fonctionnant en mode fenêtre sur la Pixel Tablet

Voici comment nous avons implémenté ces fonctionnalités dans Cahier :

Pour activer le multi-instance, nous devions d'abord indiquer au système que l'application pouvait être lancée plusieurs fois en ajoutant la propriété PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI à la déclaration de MainActivity dans AndroidManifest :

  <activity

    android:name="com.example.cahier.MainActivity"

    android:exported="true"

    android:label="@string/app_name"

    android:theme="@style/Theme.MyApplication"

    android:showWhenLocked="true"

    android:turnScreenOn="true"

    android:resizeableActivity="true"

    android:launchMode="singleInstancePerTask">


    <property

        android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"

        android:value="true"/>

    ...

</activity>

Ensuite, nous avons implémenté la logique pour lancer une nouvelle instance de l'application. Dans CahierHomeScreen.kt, lorsqu'un utilisateur choisit d'ouvrir une note dans une nouvelle fenêtre, nous créons un Intent avec des indicateurs spécifiques qui indiquent au système comment gérer le lancement de la nouvelle activité. La combinaison de touches FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_MULTIPLE_TASK et FLAG_ACTIVITY_LAUNCH_ADJACENT permet de s'assurer que la note s'ouvre dans une nouvelle fenêtre distincte de celle existante.

  fun openNewWindow(activity: Activity?, note: Note) {

    val intent = Intent(activity, MainActivity::class.java)

    intent.putExtra(AppArgs.NOTE_TYPE_KEY, note.type)

    intent.putExtra(AppArgs.NOTE_ID_KEY, note.id)

    intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or

        Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT


    activity?.startActivity(intent)

}

Pour prendre en charge le mode multifenêtre, nous devions indiquer au système que l'application était redimensionnable en définissant l'élément <activity> ou <application> du fichier manifeste.

  <activity

    android:name="com.example.cahier.MainActivity"

    android:resizeableActivity="true"

    ...>

</activity>

L'interface utilisateur étant elle-même conçue avec la bibliothèque adaptative Material 3, elle peut s'adapter de manière fluide aux scénarios multifenêtres, comme le mode écran partagé d'Android. 

Pour améliorer l'expérience utilisateur, nous avons ajouté la prise en charge du glisser-déposer. Découvrez ci-dessous comment nous avons implémenté cette fonctionnalité dans Cahier.

Glisser-déposer

Une application réellement productive ou créative ne fonctionne pas de manière isolée. Elle interagit de manière fluide avec le reste de l'écosystème de l'appareil. Le glisser-déposer est un élément clé de cette interaction, en particulier sur les grands écrans où les utilisateurs travaillent souvent sur plusieurs fenêtres d'application. Cahier adopte pleinement cette approche en implémentant une fonctionnalité intuitive de glisser-déposer pour ajouter et partager du contenu.

  • Importation facile : les utilisateurs peuvent faire glisser des images depuis d'autres applications (comme un navigateur Web, une galerie photo ou un gestionnaire de fichiers) et les déposer directement sur le canevas d'une note. Pour ce faire, Cahier utilise le modificateur dragAndDropTarget pour définir une zone de dépôt, rechercher du contenu compatible (comme image/*) et traiter l'URI entrant.
  • Partage facile : il est aussi facile de partager du contenu dans Cahier que dans d'autres applications. Les utilisateurs peuvent appuyer de manière prolongée sur une image dans une note de texte, ou sur l'ensemble du canevas d'une note de dessin et d'une composition d'images, puis la faire glisser vers une autre application.

Présentation technique détaillée : faire glisser des éléments depuis la zone de dessin

L'implémentation du geste de déplacement sur le canevas de dessin présente un défi unique. Dans notre DrawingSurface, les composables qui gèrent l'entrée de dessin en direct (InProgressStrokes de l'API Ink) et le Box qui détecte le geste d'appui prolongé pour lancer un déplacement sont des composables frères.

Par défaut, le système de saisie au pointeur de Jetpack Compose est conçu de sorte qu'un seul composable frère (le premier dans l'ordre de déclaration qui chevauche l'emplacement du doigt) reçoive l'événement. Dans le cas de Cahier, nous voulons que notre logique de gestion des entrées par glisser-déposer ait la possibilité de s'exécuter et potentiellement de consommer des entrées avant que le composable InProgressStrokes n'utilise toutes les entrées non consommées pour le dessin, puis ne consomme ces entrées. Si nous ne disposons pas les éléments dans le bon ordre, notre Box ne détectera pas le geste d'appui prolongé pour commencer un déplacement, ou InProgressStrokes ne recevra pas l'entrée pour dessiner.

Pour résoudre ce problème, nous avons créé un modificateur pointerInputWithSiblingFallthrough personnalisé et nous avons placé notre Box à l'aide de ce modificateur avant InProgressStrokes dans le code composable. Cet utilitaire est un wrapper fin autour du système pointerInput standard, mais avec un changement essentiel : il remplace la fonction sharePointerInputWithSiblings() pour renvoyer true. Cela indique au framework Compose d'autoriser les événements de pointeur à passer aux composables frères, même après avoir été consommés.

  internal fun Modifier.pointerInputWithSiblingFallthrough(

    pointerInputEventHandler: PointerInputEventHandler

) = this then PointerInputSiblingFallthroughElement(pointerInputEventHandler)


private class PointerInputSiblingFallthroughModifierNode(

    pointerInputEventHandler: PointerInputEventHandler

) : PointerInputModifierNode, DelegatingNode() {


    var pointerInputEventHandler: PointerInputEventHandler

        get() = delegateNode.pointerInputEventHandler

        set(value) {

            delegateNode.pointerInputEventHandler = value

        }


    val delegateNode = delegate(

        SuspendingPointerInputModifierNode(pointerInputEventHandler)

    )


    override fun onPointerEvent(

        pointerEvent: PointerEvent,

        pass: PointerEventPass,

        bounds: IntSize

    ) {

        delegateNode.onPointerEvent(pointerEvent, pass, bounds)

    }


    override fun onCancelPointerInput() {

        delegateNode.onCancelPointerInput()

    }


    override fun sharePointerInputWithSiblings() = true

}


private data class PointerInputSiblingFallthroughElement(

    val pointerInputEventHandler: PointerInputEventHandler

) : ModifierNodeElement<PointerInputSiblingFallthroughModifierNode>() {


    override fun create() = PointerInputSiblingFallthroughModifierNode(pointerInputEventHandler)


    override fun update(node: PointerInputSiblingFallthroughModifierNode) {

        node.pointerInputEventHandler = pointerInputEventHandler

    }


    override fun InspectorInfo.inspectableProperties() {

        name = "pointerInputWithSiblingFallthrough"

        properties["pointerInputEventHandler"] = pointerInputEventHandler

    }

}

Voici comment il est utilisé dans DrawingSurface :

  Box(

    modifier = Modifier

        .fillMaxSize()

        // Our custom modifier enables this gesture to coexist with the drawing input.

        .pointerInputWithSiblingFallthrough {

            detectDragGesturesAfterLongPress(

                onDragStart = { onStartDrag() },

                onDrag = { _, _ -> /* consume drag events */ },

                onDragEnd = { /* No action needed */ }

            )

        }

) 

// The Ink API's composable for live drawing sits here as a sibling.

InProgressStrokes(...)

Le système détecte alors correctement les traits de dessin et le geste de déplacement par appui prolongé simultanément. Une fois le déplacement lancé, nous créons un URI content:// partageable avec FileProvider et transmettons l'URI au framework de glisser-déposer du système à l'aide de view.startDragAndDrop(). Cette solution garantit une expérience utilisateur robuste et intuitive, et montre comment surmonter les conflits de gestes complexes dans les UI en couches.

Conçu avec une architecture moderne

Au-delà des API spécifiques, Cahier illustre des modèles architecturaux essentiels pour créer des applications adaptatives de haute qualité.

La couche de présentation : Jetpack Compose et l'adaptabilité

La couche de présentation est entièrement conçue avec Jetpack Compose. Comme mentionné précédemment, Cahier adopte la bibliothèque material3-adaptive pour l'adaptabilité de l'UI. La gestion de l'état suit un modèle strict de flux de données unidirectionnel (UDF), avec des instances ViewModel utilisées comme conteneurs de données contenant des informations sur les notes et l'état de l'UI.

La couche de données : dépôts et Room

Pour la couche de données, Cahier utilise une interface NoteRepository pour abstraire toutes les opérations de données. Ce choix de conception permet à l'application de passer facilement d'une source de données locale (Room) à un éventuel backend distant. Le flux de données pour une action telle que la modification d'une note est simple :

  1. L'UI Jetpack Compose déclenche une méthode dans le ViewModel.
  2. ViewModel récupère la note à partir de NoteRepository, gère la logique et renvoie la note mise à jour au dépôt.
  3. NoteRepository enregistre la mise à jour dans une base de données Room.

Prise en charge complète des entrées

Pour être un véritable outil de productivité, une application doit gérer parfaitement différents modes de saisie. Cahier est conçu pour être conforme aux consignes relatives aux grands écrans et est compatible avec les éléments suivants :

  • Stylet : intégration à l'API Ink, rejet de la paume, enregistrement pour le rôle de notes, saisie au stylet dans les champs de texte et mode immersif.
  • Clavier : prise en charge des raccourcis et combinaisons clavier les plus courants (comme Ctrl+clic, meta+clic) et indication claire de la sélection au clavier.
  • Souris et pavé tactile : prise en charge du clic droit et des états de survol.

La prise en charge des interactions avancées avec le clavier, la souris et le pavé tactile est un axe majeur pour les améliorations à venir. 

Commencez dès maintenant

Nous espérons que Cahier vous servira de tremplin pour votre prochaine application. Nous l'avons conçu comme une ressource Open Source complète qui montre comment combiner une UI adaptative, des API puissantes comme Ink et le rôle Notes, et une architecture moderne et adaptative.

Vous êtes prêt à vous lancer ?

  • Explorer le code : accédez à notre dépôt GitHub pour explorer la codebase Cahier et voir les principes de conception en action.
  • Créer votre propre application : utilisez Cahier comme base pour votre propre application de prise de notes, de balisage de documents ou de création.
  • Contribuez : vos contributions sont les bienvenues ! Aidez-nous à faire de Cahier une ressource encore plus utile pour la communauté des développeurs Android.

Consultez les guides officiels pour les développeurs et commencez dès aujourd'hui à créer votre application de productivité et de créativité de nouvelle génération. Nous avons hâte de découvrir vos créations !

Écrit par :

Lire la suite