tv future is apps - tvos vs androidtv

Post on 09-Apr-2017

223 Views

Category:

Software

5 Downloads

Preview:

Click to see full reader

TRANSCRIPT

TV Future is AppstvOS vs AndroidTVby @pablito_az @hugojperal @jr_salazares

MADRID · NOV 18-19 · 2016

Agenda ¿Quiénes somos? Introducción a la plataforma Dinámica del workshop. Primeros pasos ¿Cómo buscar contenido dentro de la app? Vayamos al detalle. Cosas que nos dejamos en el tintero

¿Quiénes somos?

http://www.edreamsodigeocareers.com

Introducción. Experiencia

Introducción. Interacción

Introducción. UX

Introducción. Foco

Dinámica del workshop

Repo AndroidTV: https://github.com/odigeoteam/AndroidTV-workshop

Repo tvOS y TVML: https://github.com/odigeoteam/tvOS-workshop

Primeros pasos

Step 1 - 2

Para que sea compatible en AndroidTV ...… tenemos que hacer algunas cosas:

● Nuestras activity principal CATEGORY_LEANBACK_LAUNCHER

● <uses-feature android:name = “android.software.leanback”android:required = “false”>

● <uses-feature android:name = “android.hardware.touchscreen”android:required = “false”>

… y nuestro dispositivo tiene limitaciones:

● Touchscreen● Telephony● Camera

● GPS● Microphone● Sensors

Adaptando el comportamiento ... … en tiempo de ejecución:

if (getPackageManager().hasSystemFeature("android.hardware.camera")) {

// Hago algo con la cámara

} else {

// Adapto mi comportamiento

}

Algunas características de los layoutsDebemos tener en cuenta:

● Layouts en Landscape.● UI en secciones fácilmente navegables.● Suficiente margen entre elementos.● Cuidado con el Overscan● Textos suficientemente visibles.

v17 Leanback to the rescue

compile 'com.android.support:leanback-v17:24.2.1'

Nuestra primera vista: BrowseFragment

Configurando el BrowseFragmentPodemos configurar elementos en la interfaz muy fácil:

setBadgeDrawable(...);setOnSearchClickedListener(...);setSearchAffordanceColor(...);

Pintando contenido

Pintando contenidoclass ContentAdapter extends ArrayObjectAdapter {

for (CategoryList) {ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new CardItemPresenter());for (awesomePlaces) {

listRowAdapter.add(places);}HeaderItem header = new HeaderItem(Category);add(new ListRow(header, listRowAdapter));

}}

Nuestro CardItemPresenterpublic class CardItemPresenter extends Presenter{

@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent) {

// Creo mi ImageCardView aquí}

@Overridepublic void onBindViewHolder(ViewHolder viewHolder,

Object item) {// Pinto la información en la ImageCardView

}}

Configurando ImageCardViewTiene 3 elementos principales, además de la imágen de fondo:

Se pueden configurar, mediante un Style combinando estos elementos:

<item name="lbImageCardViewType">Title|Content|IconOnLeft</item>

● Título● Contenido● Badge

Step 1 - 2

Limitaciones 200MB No LocalStorage No WebViews No Custom Video Player No Contacts, HandOff...

Universal PurchaseMisma entrada en iTunes ConnectMismo bundle IDSubidas a iTunes Connect separadasDistintas versionesDistintos procesos de revisiónEsta unión es para… siempre

Construyamos un layout

Grids, grids everywhere¿puedo tener el foco? -> canBecomeFocusedUIButton, UIControl, UISegmentedControl, UITabBar, UITextField, UISearchBar(UITextField)collectionView(_:canFocusItemAtIndexPath:)tableView(_:canFocusRowAtIndexPath:)

y yo, ¿tengo el foco? -> focuseddidUpdateFocusInContext(_:withAnimationCoordinator:)

Step 1-2

TVMLTVML (TV Markup Language)TVJS (TV Javascript)TVMLKit

TVML

Templates, templates everywhere18 templates a elegirElementos simplesElementos compuestos

carousel, collectionList, shelf, lockup

TVML

JS Principalesapplication.js:

JS Inicial. Carga otros JS y la primera pantallaDocumentLoader:

Encargado de cargar documentosDocumentController:

Es el controller y tiene asociado un loader y un template. Nos abstrae de la navegación

TVML

Aspecto template● Para navegar entre pantallas

usaremos el atributo “documentURL” en cualquier elemento focusable

TVML

Step 1 - 2TVML

¿Cómo buscamos dentro de la app?

Step 3

In-app search: SearchFragment

SearchFragmentclass SearchViewImp extends SearchFragment implements SearchResultProvider {

@Overridepublic ObjectAdapter getResultsAdapter() {}

@Overridepublic boolean onQueryTextChange(String newQuery) {}

@Overridepublic boolean onQueryTextSubmit(String query) {}

}

Cards interaction: BackgroundManager

private BackgroundManager mBackgroundManager;

// Inicializamos el BackgroundManagermBackgroundManager = BackgroundManager.getInstance(getActivity());mBackgroundManager.attach(getActivity().getWindow());

// Cambiamos el fondo cada vez que seleccione una cardmBackgroundManager.setDrawable(backgroundDrawable);

Step 3

¿Cómo buscar dentro de la app?//Swiftlet searchResultsController = SearchResultsViewController()

let searchController = UISearchController(searchResultsController: searchResultsController)

searchController.searchResultsUpdater = searchResultsController let searchContainer = UISearchContainerViewController(searchController: searchController)

Gestos

Veamos los styles//Con el Appearance ProxyUIButton.appearance().setTitleColor(.red, for: [])let light = UITraitCollection(userInterfaceStyle: .light)let dark = UITraitCollection(userInterfaceStyle: .dark)UIButton.appearance(for: light).setTitleColor(.red, for:[])UIButton.appearance(for: dark).setTitleColor(.blue, for:[])

// UIScreen, UIWindow, UIViewController, UIPresentationController, UIViewfunc traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)

Step 3

TVJSEventos:Document → load, unload, appear, disappear…Focusable Elements → select, highlight, holdselect, play

event.target vs event.currentTarget

TVML

SearchTemplateTVML

Step 3TVML

Vayamos al detalle

Step 4

Construyendo cualquier layoutLo más importante, la navegación

Controlando la navegación

if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {// Vamos abajo

} else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) {// Vamos arriba

} else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) {

// Vamos a la derecha} else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) {

// Vamos a la izquiera}

Controlando la navegación

<TextView android:id="@+id/Category1"

android:nextFocusDown="@+id/Category2"\>

Manejando recursos pesados

● Carga imágenes solo cuando se muestren en la pantalla.

● Recicla los Bitmaps cuando ya no sean necesarios.

● Si traes imágenes de red, hazlo siempre en un hilo aparte.

● Escala las imágenes al tamaño que realmente necesitas.

Step 4

Cargar un videoLo más fácil es usar la clase AVPlayerViewController y el resto sería así://Creamos el player con la URL del videoplayer = AVPlayer(url: url)//configuramos el payer con las opciones deseadasplayer?.play()

Step 4

TVML. Elementos Custom I TVML

TVML. Elementos Custom II 1.Implementar protocolo TVInterfaceCreating2.Asignar el extendedInterfaceCreator del objeto

singleton TVInterfaceFactory3.Registrar elemento4.Usar en nuestros TVMLs

TVML

Custom template

Step 4TVML

Cosas que nos dejamos en el tintero

Finding content outside the app

● Recommendation Row:○ Continuation content○ New content○ Related content

● Hacer que el contenido de tu aplicación sea encontrable desde fuera de ella.

Más vistas reutilizables

Modo picture-in-picture

Cosas que nos dejamos en el tintero

Testing. Unit Test y UI Test Top Shelf Dinámico Parallax Artwork Más Focus Engine:

∘ UIFocusGuide∘ var preferredFocusEnvironments: [UIFocusEnvironment]

Cosas que nos dejamos en el tintero

Video features Now playing Animar DOM updates

¡Gracias!

top related