Εικονογράφηση της Virginia Poltrack

Κινώντας σε ένα Πρόγραμμα

Κινούμενες εικόνες στην εφαρμογή I / O Google

Ήμουν πρόσφατα μέλος μιας εξαιρετικής ομάδας που εργάζεται στην εφαρμογή Google I / O 2018 Android. Πρόκειται για μια εφαρμογή συνοδευτικού συνεδρίου, που επιτρέπει σε συμμετέχοντες και απομακρυσμένους ανθρώπους να βρουν περιόδους σύνδεσης, να δημιουργήσουν ένα εξατομικευμένο πρόγραμμα και να διατηρήσουν θέσεις στο χώρο (αν είστε αρκετά τυχεροί για να είστε εκεί!). Έχουμε δημιουργήσει μια σειρά από ενδιαφέροντα κινούμενα χαρακτηριστικά στην εφαρμογή που πιστεύω ότι ενίσχυσε σημαντικά την εμπειρία. Ο κώδικας για αυτήν την εφαρμογή μόλις άνοιξε και ήθελα να επισημάνω μερικές από αυτές τις περιπτώσεις και μερικές ενδιαφέρουσες λεπτομέρειες υλοποίησης.

Μερικά κινούμενα στοιχεία στην εφαρμογή I / O

Γενικά, υπάρχουν 3 τύποι κινούμενων εικόνων που χρησιμοποιήσαμε στην εφαρμογή:

  1. Hero animations - χρησιμοποιείται για να ενισχύσει το branding και να φέρει στιγμές απόλαυσης
  2. Μεταβάσεις οθόνης
  3. Κρατικές αλλαγές

Θα ήθελα να μπω σε λεπτομέρειες μερικών από αυτά.

Αντίστροφη μέτρηση

Μέρος του ρόλου της εφαρμογής είναι η δημιουργία ενθουσιασμού και πρόβλεψης για τη διάσκεψη. Ως εκ τούτου φέτος συμπεριελάβαμε μια μεγάλη κινούμενη αντίστροφη μέτρηση στην αρχή της διάσκεψης που εμφανίζεται τόσο στην οθόνη επί της επιβίβασης όσο και στην ενότητα Info. Αυτή ήταν επίσης μια μεγάλη ευκαιρία για να ενσωματώσετε την επωνυμία της εκδήλωσης στην εφαρμογή, φέρνοντας πολλούς χαρακτήρες.

Η αντίστροφη μέτρηση μέχρι την έναρξη της διάσκεψης

Αυτή η κινούμενη εικόνα σχεδιάστηκε από έναν σχεδιαστή κίνησης και παραδόθηκε ως μια σειρά αρχείων Lotte json: κάθε 1 δευτερόλεπτο που δείχνει έναν αριθμό animation 'in' τότε 'out'. Η μορφή Lottie έκανε εύκολη την απομάκρυνση των αρχείων σε στοιχεία και μάλιστα πρόσφερε μεθόδους ευκολίας όπως το setMinAndMaxProgress που μας έδινε τη δυνατότητα να παίξουμε μόνο το πρώτο ή το τελευταίο μισό μιας κινούμενης εικόνας (για να δείξουμε έναν αριθμό κινούμενο μέσα ή έξω).

Το ενδιαφέρον κομμάτι ήταν η ενορχήστρωση αυτών των πολλαπλών κινούμενων εικόνων στη συνολική αντίστροφη μέτρηση. Για να γίνει αυτό, δημιουργήσαμε μια προσαρμοσμένη CountdownView η οποία είναι μια αρκετά περίπλοκη ConstraintLayout που κατέχει μια σειρά από LottieAnimationViews. Σε αυτό, δημιουργήσαμε έναν αντιπρόσωπο της Kotlin για να εγκαινιάσει την κατάλληλη κινούμενη εικόνα. Αυτό μας επέτρεψε να αναθέσουμε απλώς ένα Int σε κάθε αντιπρόσωπο του ψηφίου που θα έπρεπε να εμφανίσει και ο εκπρόσωπος θα ορίσει και θα ξεκινήσει το animation (s). Επεκτάσαμε τον εκπρόσωπο του ObservableProperty, ο οποίος διασφαλίζει ότι έχουμε κάνει μόνο μια κινούμενη εικόνα όταν αλλάζει το ψηφίο. Στη συνέχεια, ο βρόχος κινούμενου animation έγραψε ένα τρέξιμο κάθε δευτερόλεπτο (όταν προσαρμόστηκε η προβολή), το οποίο υπολογίζει ποιο ψηφίο πρέπει να εμφανίζει κάθε προβολή και να ενημερώνει τους αντιπροσώπους.

Κράτηση

Μία από τις βασικές ενέργειες της εφαρμογής είναι να επιτρέψει στους συμμετέχοντες να κρατήσουν θέσεις. Ως εκ τούτου, εμφανίσαμε αυτή τη δράση εμφανώς σε ένα FAB στην οθόνη λεπτομερειών της περιόδου σύνδεσης. Θεωρήσαμε ότι ήταν σημαντικό να αναφέρουμε ότι η σύνοδος διατηρήθηκε μόλις ολοκληρώθηκε με επιτυχία στο backend (αντίθετα από τις λιγότερο σημαντικές δράσεις, όπως η συμμετοχή σε μια συνάντηση όπου ενημερώνουμε αισιόδοξα το UI αμέσως). Αυτό μπορεί να χρειαστεί λίγο χρόνο, ενώ περιμένουμε μια απάντηση από το backend έτσι ώστε να γίνει αυτό πιο ευαίσθητο που χρησιμοποιήσαμε το κινούμενο εικονίδιο για να δώσουμε ανατροφοδότηση ότι εργαζόμαστε σε αυτό και για την ομαλή μετάβαση στο νέο κράτος.

Ανατροφοδότηση ενώ διατηρεί ένα κάθισμα σε μια συνεδρία

Αυτό περιπλέκεται από το γεγονός ότι υπήρχαν αρκετές πολιτείες που η εικόνα αυτή έπρεπε να αντικατοπτρίζει: η σύνοδος μπορεί να είναι διατηρήσιμη, μπορεί να έχουν ήδη κρατήσει μια έδρα, εάν η σύνοδος είναι πλήρης τότε μπορεί να είναι διαθέσιμη μια λίστα αναμονής ή μπορεί να βρίσκονται στο λίστα αναμονής ή κοντά στην έναρξη της κράτησης. Αυτό είχε ως αποτέλεσμα πολλές μεταβολές διαφορετικών κρατών να κινούνται μεταξύ. Για να απλοποιήσουμε αυτές τις μεταβάσεις, αποφασίσαμε πάντα να περάσουμε από ένα «εργασιακό» κράτος. την κινούμενη κλεψύδρα παραπάνω. Επομένως, κάθε μετάβαση είναι στην πραγματικότητα ένα ζεύγος: κατάσταση 1 → εργασία και εργασία → κατάσταση 2. Αυτό απλοποίησε τα πράγματα σε μεγάλο βαθμό. Έχουμε δημιουργήσει κάθε ένα από αυτά τα κινούμενα σχέδια χρησιμοποιώντας shapeshifter. δείτε τα αρχεία avd_state_to_state εδώ.

Για να εμφανιστεί αυτό, χρησιμοποιήσαμε μια προσαρμοσμένη προβολή και ένα AnimatedStateListDrawable (ASLD). Εάν δεν έχετε χρησιμοποιήσει προηγουμένως ASLD, είναι (όπως υποδηλώνει το όνομά του) μια κινούμενη έκδοση του StateListDrawable που πιθανότατα έχετε συναντήσει - επιτρέποντάς σας όχι μόνο να παρέχετε διαφορετικά σχεδιαγράμματα ανά κατάσταση αλλά και μεταβάσεις μεταξύ καταστάσεων (υπό τη μορφή AnimatedVectorDrawable ή ένα AnimationDrawable). Εδώ είναι το σχεδιάγραμμα που ορίζει τις στατικές εικόνες και τις μεταβάσεις προς και από την κατάσταση λειτουργίας για το εικονίδιο κράτησης.

Δημιουργήσαμε μια προσαρμοσμένη προβολή για να υποστηρίξουμε τις προσαρμοσμένες καταστάσεις μας. Οι προβολές προσφέρουν κάποιες τυπικές καταστάσεις όπως πατημένο ή επιλεγμένο. Ομοίως, μπορείτε να ορίσετε τη δική σας και να έχετε τη διαδρομή προβολής που εμφανίζει σε οποιαδήποτε Drawables. Καθορίσαμε το δικό μας state_reservable, state_reserved κλπ. Στη συνέχεια δημιουργήσαμε ένα enum αυτών των διαφορετικών καταστάσεων, εγκλωβίζοντας την κατάσταση προβολής συν οποιεσδήποτε σχετικές ιδιότητες όπως μια σχετική περιγραφή περιεχομένου. Η επιχειρησιακή λογική μας θα μπορούσε απλώς να ορίσει την κατάλληλη τιμή από αυτό το enum στην προβολή (μέσω δεσμεύσεων δεδομένων), η οποία θα ενημερώνει την κατάσταση του σχεδιαστή, η οποία ξεκίνησε μια κινούμενη εικόνα μέσω του ASLD. Ο συνδυασμός προσαρμοσμένων καταστάσεων και AnimatedStateListDrawable ήταν ένας τακτικός τρόπος για να εφαρμοστεί αυτό, διατηρώντας το πλήθος των κρατών στις δηλωτικές στρώσεις, με αποτέλεσμα τον ελάχιστο κωδικό θέασης.

Μετάβαση του ηχείου

Πολλές από τις μεταβάσεις της οθόνης λειτουργούσαν καλά με τα τυπικά κινούμενα γραφικά παραθύρων. Ένα σημείο που αποκλίνουμε από αυτό είναι η μετάβαση στην οθόνη λεπτομερειών ομιλητών. Αυτό έδειξε την εικόνα των ομιλητών και στις δύο πλευρές της μετάβασης και ήταν ένας τέλειος υποψήφιος για μια κοινή μετάβαση στοιχείων. Αυτό διευκολύνει την αλλαγή περιβάλλοντος μεταξύ των οθονών.

Μια κοινή μετάβαση στοιχείων

Πρόκειται για μια αρκετά σταθερή κοινή μετάβαση στοιχείων, χρησιμοποιώντας τις πλατφόρμες ChangeBounds και ArcMotion σε ένα ImageView.

Αυτό που ήταν πιο ενδιαφέρον ήταν το πώς η έναρξη αυτής της μετάβασης προσαρμόστηκε στο μοτίβο συμβάντος που χρησιμοποιήσαμε για πλοήγηση. Ουσιαστικά, αυτό το μοτίβο αποσυνδέει τα γεγονότα εισόδου (όπως την εγγραφή σε ένα ηχείο) από τα γεγονότα πλοήγησης, θέτοντας το ViewModel υπεύθυνο για τον τρόπο απόκρισης στην είσοδο. Σε αυτήν την περίπτωση, αυτή η αποσύνδεση σημαίνει ότι το ViewModel εξέθεσε μια LiveData των Εκδηλώσεων, η οποία γνώριζε μόνο την ταυτότητα του ομιλητή για να πλοηγηθεί. Η έναρξη μιας κοινής μετάβασης στοιχείων απαιτεί την κοινή προβολή, την οποία δεν είχαμε σε αυτό το σημείο. Το λύσαμε αυτό αποθηκεύοντας το αναγνωριστικό του ομιλητή ως ετικέτα στην προβολή όταν είναι δεσμευμένο, έτσι ώστε η προβολή να μπορεί αργότερα να ανακτηθεί όταν πρέπει να πλοηγηθεί σε μια συγκεκριμένη οθόνη λεπτομερειών ομιλητών.

Φίλτρα

Ένα βασικό μέρος της εφαρμογής διάσκεψης φιλτράρει τα πολλά γεγονότα κάτω από αυτά που σας ενδιαφέρει. Κάθε θέμα είχε ένα χρώμα που συσχετίζεται με αυτό για εύκολη αναγνώριση και λάβαμε ένα εξαιρετικό σχέδιο για ένα προσαρμοσμένο «τσιπ» που θα χρησιμοποιήσει κατά την επιλογή φίλτρων:

Κινούμενα τσιπ φίλτρων

Εξετάσαμε το Chip από τα στοιχεία υλικού αλλά επιλέξαμε να εφαρμόσουμε τη δική μας προσαρμοσμένη προβολή για μεγαλύτερο έλεγχο της οθόνης και της κίνησης μεταξύ των «ελεγμένων» καταστάσεων. Αυτό υλοποιείται χρησιμοποιώντας σχέδιο καμβά και ένα StaticLayout για την εμφάνιση κειμένου. Η προβολή έχει μια μοναδική πρόοδο ιδιότητα [0-1] μοντελοποίηση ανεξέλεγκτη-επιλεγμένο. Για την εναλλαγή της κατάστασης, απλά ζωντανεύουμε αυτήν την τιμή και ακυρώνουμε την προβολή και ο κώδικας απόδοσης γραμμικώς παρεμβάλλει τις θέσεις και τα μεγέθη των στοιχείων με βάση αυτό.

Αρχικά όταν το έκανα αυτό, έκανα την άποψη να εφαρμόσει τη διεπαφή Checkable και ξεκίνησε το κινούμενο σχέδιο όταν η setCheck method έθεσε μια νέα κατάσταση. Καθώς εμφανίζουμε πολλαπλά φίλτρα σε ένα RecyclerView, αυτό είχε το ατυχές αποτέλεσμα της εκτέλεσης της κινούμενης εικόνας, αν ένα επιλεγμένο φίλτρο μετακινηθεί προς τα έξω και η προβολή ήταν ανάκαμψη σε ένα μη επιλεγμένο φίλτρο κύλισης. Ως εκ τούτου, προσθέσαμε μια ξεχωριστή μέθοδο για να ξεκινήσουμε την κινούμενη εικόνα, επιτρέποντάς μας να διαφοροποιήσουμε μεταξύ της επιλογής και της άμεσης ενημέρωσης όταν συνδέουμε νέα δεδομένα στην προβολή.

Επιπλέον, όταν παρουσιάσαμε αυτήν την εναλλαγή κινούμενων εικόνων, διαπιστώσαμε ότι τσακίζουμε, δηλαδή ρίχνουμε πλαίσια. Ήταν ο κώδικας κινούμενης εικόνας μου; Αυτά τα φίλτρα εμφανίζονται σε ένα BottomSheet μπροστά από την κύρια οθόνη του προγράμματος διάσκεψης. Όταν ενεργοποιείται ένα φίλτρο, ξεκινάμε τη λογική φιλτραρίσματος που πρέπει να εφαρμοστεί στο πρόγραμμα (και ενημερώνουμε τον αριθμό των συμβάντων που ταιριάζουν στον τίτλο του φύλλου φίλτρου). Κάποια συμπερίληψη αργότερα, διαπιστώσαμε ότι το ζήτημα ήταν ότι όταν εφαρμόστηκαν τα φίλτρα, το ViewPager του RecyclerViews που εμφανίζει το πρόγραμμα υπονομεύθηκε και ενημερώθηκε με τα πρόσφατα παραδοθέντα δεδομένα. Αυτό προκάλεσε την εμφάνιση πληθώρας απόψεων και δεσμών. Όλη αυτή η δουλειά φυσούσε τον προϋπολογισμό μας ... αλλά το πρόγραμμα ενημέρωσης δεν ήταν ορατό, καθώς ήταν πίσω από το φύλλο φίλτρου. Κάναμε την απόφαση να καθυστερήσουμε την εκτέλεση του πραγματικού φιλτραρίσματος μέχρι να τρέξει το κινούμενο σχέδιο, αλλάζουμε κάπως περισσότερη πολυπλοκότητα εφαρμογής για μια ομαλότερη εμπειρία χρήστη. Αρχικά εφάρμοζα αυτό χρησιμοποιώντας PostDelayed αλλά αυτό προκάλεσε προβλήματα για τις δοκιμές UI. Αντ 'αυτού, αλλάξαμε τη μέθοδο μας, η οποία ξεκίνησε το κινούμενο σχέδιο, για να δεχτεί ένα λάμβδα που θα τρέξει στο τέλος. Αυτό μας επέτρεψε να σέβουμε καλύτερα τις ρυθμίσεις κινούμενης εικόνας του χρήστη και να δοκιμάζουμε σωστά την εκτέλεση.

Ζωντανέψτε

Συνολικά, αισθάνομαι ότι τα κινούμενα σχέδια πραγματικά συνέβαλαν στην εμπειρία, τον χαρακτήρα, το branding και την απόκριση της εφαρμογής. Ας ελπίσουμε ότι αυτή η θέση βοήθησε να εξηγήσει τόσο γιατί και πώς χρησιμοποιήθηκαν και σας έδωσαν δείκτες για την εφαρμογή τους.