Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Interfaz de Usuario en Dispositivos móviles. Android Avanzado Personalización de componentes © 2014-2015 Escuela Politécnica Superior Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Puntos a tratar 1. Componentes compuestos Nuevas vistas a partir de agrupaciones de vistas 2. Componentes propios Crear nuevas vistas desde cero 3. Modificar vistas existentes Extender la funcionalidad de vistas existentes IUDM © 2014-2015 Escuela Politécnica Superior 2 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes compuestos • Conjunto de vistas tratadas de forma atómica. • Por ejemplo: Agrupar un campo de edición y un botón para que al pulsar se borre el texto. • Pasos para crear un componente compuesto: 1. Crear un layout de forma normal con las vistas a agrupar. 2. Crear una clase Java que extienda un ViewGroup (normalmente un layout). 3. Asignar el layout XML que hemos creado a nuestra clase Java. 4. Utilizar el componente compuesto de forma normal (pero a partir del espacio de nombres de la aplicación). IUDM © 2014-2015 Escuela Politécnica Superior 3 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes compuestos • Paso 1: Crear el Layout del componente compuesto en los recursos de la aplicación. • Ejemplo: <?xml version="1.0" encoding="utf­8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <EditText android:id="@+id/editText" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Borrar" /> </LinearLayout> IUDM © 2014-2015 Escuela Politécnica Superior 4 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes compuestos • Paso 2: crear una Subclase de ViewGroup (normalmente un layout) • Esqueleto de la subclase: public class MiComponente extends LinearLayout { public MiComponente(Context context) { super(context); } public MiComponente(Context context, AttributeSet atts) { super(context, atts); } } IUDM © 2014-2015 Escuela Politécnica Superior 5 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes compuestos • Paso 3: Asignar el layout XML a nuestro componente: public class EdicionBorrable extends LinearLayout { EditText editText; Button button; public EdicionBorrable(Context context) { super(context); // Creamos la interfaz a partir del layout String infService = Context.LAYOUT_INFLATER_SERVICE; LayoutInflater li; li = (LayoutInflater)getContext().getSystemService(infService); li.inflate(R.layout.edicion_borrable, this, true); // Obtenemos las referencias a las vistas hijas editText = (EditText)findViewById(R.id.editText); button = (Button)findViewById(R.id.button); } } IUDM © 2014-2015 Escuela Politécnica Superior 6 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes compuestos • Paso 3.1: • Añadir funcionalidad definiendo manejadores de eventos de manera habitual. • Ejemplo: borrar el contenido del cuadro de edición al pulsar el botón. button.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { editText.setText(""); } }); IUDM © 2014-2015 Escuela Politécnica Superior 7 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes compuestos • Paso 4. Uso: incluir el componente en una actividad • Añadido como una vista cualquiera • Añadir espacio de nombres al nombre del componente <?xml version="1.0" encoding="utf­8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <es.ua.jtech.android.compuestos.EdicionBorrable android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> IUDM © 2014-2015 Escuela Politécnica Superior 8 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes compuestos • Otra opción: definir el layout mediante código public EdicionBorrable(Context context) { // CONSTRUCTOR super(context); // Cambiamos la orientación del layout a vertical setOrientation(LinearLayout.VERTICAL); // Creamos las vistas hijas editText = new EditText(getContext()); button = new Button(getContext()); button.setText("Borrar"); // Colocamos estas vistas en el control compuesto int lHeight = LayoutParams.WRAP_CONTENT; int lWidth = LayoutParams.FILL_PARENT; addView(editText, new LinearLayout.LayoutParams(lWidth, lHeight)); addView(button, new LinearLayout.LayoutParams(lWidth, lHeight)); } IUDM © 2014-2015 Escuela Politécnica Superior 9 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Puntos a tratar 1. Componentes compuestos Nuevas vistas a partir de agrupaciones de vistas 2. Componentes propios Crear nuevas vistas desde cero 3. Modificar vistas existentes Extender la funcionalidad de vistas existentes IUDM © 2014-2015 Escuela Politécnica Superior 10 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios • Creación de nuevas vistas desde cero • Subclase de View • Sobrecarga de onDraw public class MiVista extends View { public MiVista(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { // TODO Definir como dibujar el componente } } IUDM © 2014-2015 Escuela Politécnica Superior 11 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios: lienzo y pincel • El método onDraw recibe un Canvas • Encapsula el contexto gráfico de la vista • Para dibujar algunos elementos es necesario definir propiedades del pincel (Paint) • Color, grosor, etc. • Ejemplo: Paint p = new Paint(); p.setColor(Color.RED); • Tras definir sus propiedades, podemos utilizarlo para dibujar elementos usando métodos de la clase Canvas IUDM © 2014-2015 Escuela Politécnica Superior 12 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios: lienzo y pincel • Propiedades pincel: • Color plano: setARGB y setColor • Gradientes y shaders: shaders de gradiente (LinearShader, RadialShader, SweepShader), mapa de bits (BitmapShader), combinación de shaders (ComposeShader) Paint p = new Paint(); p.setColor(Color.RED); p.setARGB(0, 255, 0, 0); p.setShader(new RadialGradient(centerX, centerY, radius, color0, color1, Shader.TileMode.MIRROR)); IUDM © 2014-2015 Escuela Politécnica Superior 13 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios: lienzo y pincel • Propiedades pincel: • Máscaras: suavizado (BlurMaskFilter) o relieve (EmbossMaskFilter) • Se aplican con setMaskFilter IUDM © 2014-2015 Escuela Politécnica Superior 14 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios: lienzo y pincel • Propiedades pincel: • Sombras: efectos de sombras con setShadowLayer • Filtros de color: setColorFilter (alterar color original) • Estilo de figura: indicar con setStyle que se dibuje sólo el trazo, el relleno, o ambos Paint p = new Paint(); p.setStyle(Style.STROKE); p.setStyle(Style.FILL); p.setStyle(Style.FILL_AND_STROKE); IUDM © 2014-2015 Escuela Politécnica Superior 15 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios: lienzo y pincel • Propiedades pincel: • Estilo del trazo • • • • IUDM Grosor del trazo: setStrokeWidth El tipo de línea: setPathEffect Uniones en polilíneas: setStrokeJoint Forma de las terminaciones: setStrokeCap © 2014-2015 Escuela Politécnica Superior 16 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios: lienzo y pincel • Propiedades pincel: • Antialiasing: setAntiAlias(bool) • Dithering: evitamos cambios bruscos de color para gradientes en dispositivos con poca densidad de color con setDither(bool) • Modo de transferencia: setXferMode Permite dibujar solamente sobre zonas con un determinado color. IUDM © 2014-2015 Escuela Politécnica Superior 17 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios: lienzo y pincel • Propiedades lienzo (Canvas): • Área de recorte: clipRect • Área de recorte no rectangular: clipPath • Transformaciones geométricas: translate, scale, rotate, skew, setMatrix • Almacenar y restaurar propiedades: save y restore IUDM © 2014-2015 Escuela Politécnica Superior 18 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios: lienzo y pincel • Primitivas geométricas del lienzo (Canvas): • Puntos: drawPoint • Líneas: drawLine • Polilíneas: drawPath • Objeto de la clase Path compuesto de segmentos • • • • • • IUDM Rectángulos: drawRect Rectángulos con bordes redondeados: drawRoundRect Círculos: drawCircle Óvalos: drawOval Arcos: drawArc Todo el lienzo: drawColor o drawARGB © 2014-2015 Escuela Politécnica Superior 19 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios: lienzo y pincel • Ejemplo (polilínea y rectángulo) Paint paint = new Paint(); paint.setStyle(Style.FILL); paint.setStrokeWidth(5); paint.setColor(Color.BLUE); Path path = new Path(); path.moveTo(50, 130); path.lineTo(50, 60); path.lineTo(30, 80); canvas.drawPath(path, paint); canvas.drawRect(new RectF(180, 20, 220, 80), paint); IUDM © 2014-2015 Escuela Politécnica Superior 20 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Cadenas de texto • Dibujado de texto a partir de Canvas • Normal: drawText • Posición de cada carácter: drawPosText • A lo largo de una ruta (Path): drawTextOnPath • Propiedades de Paint para texto • setTypeFace, setTextSize, setTextScaleX, setTextSkewX, setUnderlineText, setStrikeThruText, setFakeBoldText, setTextAlign, y cualquier otro efecto aplicado al resto de contornos Paint ptexto = new Paint(); ptexto.setTypeface(Typeface.SANS_SERIF); ptexto.setTextSize(10); ptexto.setTextAlign(Align.CENTER); canvas.drawText("Hola Mundo", posX, posY, ptexto); IUDM © 2014-2015 Escuela Politécnica Superior 21 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Componentes propios: otros elementos • Imágenes: drawBitmap • Objetos Bitmap • Un Bitmap se puede crear a partir de una imagen, de un recurso drawable, de un array de píxeles o vacíos. Bitmap img = BitmapFactory.decodeResource( getResources(), R.drawable.image_file); • Drawables: método draw de la clase Drawable Drawable d = getResources().getDrawable(R.drawable.resource); d.draw( canvas ); IUDM © 2014-2015 Escuela Politécnica Superior 22 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Medición del componente IUDM • Además de sobrecargar onDraw es conveniente sobrecargar onMeasure • Invocado por el sistema para asignar un tamaño al elemento antes de asignarlo al layout • Para cada dimensión (altura y anchura) se reciben dos parámetros: • Tamaño: tamaño en píxeles solicitado • Modo: EXACTLY, AT_MOST, UNSPECIFIED • Antes de finalizar onMeasure es necesaria una llamada a setMeasuredDimension(width, height) © 2014-2015 Escuela Politécnica Superior 23 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Medición del componente • Ejemplo: @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width = DEFAULT_SIZE; int height = DEFAULT_SIZE; ... • width y height: las podemos declarar como miembros de la clase para acceder a ellas desde onDraw. O también podemos usar: this.getMeasuredWidth() y this.getMeasuredHeight() IUDM © 2014-2015 Escuela Politécnica Superior 24 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Medición del componente • Ejemplo (continuación): ... switch(widthMode) { case MeasureSpec.EXACTLY: width = widthSize; break; case MeasureSpec.AT_MOST: if(width > widthSize) { width = widthSize; } break; } ... IUDM © 2014-2015 Escuela Politécnica Superior 25 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Medición del componente • Ejemplo (continuación): ... switch(heightMode) { case MeasureSpec.EXACTLY: height = heightSize; break; case MeasureSpec.AT_MOST: if(height > heightSize) { height = heightSize; } break; } this.setMeasuredDimension(width, height); } IUDM © 2014-2015 Escuela Politécnica Superior 26 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Atributos propios • Permiten parametrizar determinados elementos de nuestras vistas • En XML: declarar nuevo atributo • Declaración en /res/values/attrs.xml <?xml version="1.0" encoding="utf­8"?> <resources> <declare­styleable name="Grafica"> <attr name="percentage" format="integer"/> </declare­styleable> </resources> • En código: Obtener valor de los atributos IUDM © 2014-2015 Escuela Politécnica Superior 27 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Atributos propios • Obtener al valor del atributo desde el código: public class GraficaView extends View { private float mPorcentaje = 25; public GraficaView(Context context) { super(context); } public GraficaView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.init(attrs); } public GraficaView(Context context, AttributeSet attrs) { super(context, attrs); this.init(attrs); } private void init(AttributeSet attrs) { TypedArray ta = this.getContext().obtainStyledAttributes(attrs, R.styleable.Grafica); this.mPorcentaje = ta.getInt(R.styleable.Grafica_percentage, 0); } } IUDM © 2014-2015 Escuela Politécnica Superior 28 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Atributos propios • Uso: En el layout de la actividad: <?xml version="1.0" encoding="utf­8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res/es.ua.jtech.android.grafica" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <es.ua.jtech.android.grafica.GraficaView android:layout_width="wrap_content" android:layout_height="wrap_content" app:percentage="60" /> </LinearLayout> IUDM © 2014-2015 Escuela Politécnica Superior 29 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Actualización del contenido • Forzar redibujado: método invalidate de View miVista.invalidate(); • Es posible usarlo para realizar animaciones • Para alto rendimiento • Hilos, temporizadores • SurfaceView IUDM © 2014-2015 Escuela Politécnica Superior 30 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Puntos a tratar 1. Componentes compuestos Nuevas vistas a partir de agrupaciones de vistas 2. Componentes propios Crear nuevas vistas desde cero 3. Modificar vistas existentes Extender la funcionalidad de vistas existentes IUDM © 2014-2015 Escuela Politécnica Superior 31 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Modificar vistas existentes • Alternativa simple para la creación de vistas propias • Permite ahorrar mucho código • Basado en: • Herencia de la vista en la que nos queremos basar • Extender su funcionalidad añadiendo nuevos métodos • Modificar su comportamiento sobrecargando IUDM © 2014-2015 Escuela Politécnica Superior 32 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Un TextView extendido • Primer paso: subclase de la clase que queremos modificar • Esqueleto: public class MiTextView extends TextView { public MiTextView (Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public MiTextView (Context context) { super(context); } public MiTextView (Context context, AttributeSet attrs) { super(context, attrs); } } IUDM © 2014-2015 Escuela Politécnica Superior 33 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles Un TextView extendido • Siguiente paso: sobrecarga manejadores @Override public void onDraw(Canvas canvas) { // Primero dibujamos en el canvas bajo el texto... // ... luego mostramos el texto de la manera habitual // haciendo uso de la clase base... super.onDraw(canvas); // ... y por último dibujamos cosas sobre el texto } @Override public boolean onKeyDown(int keyCode, KeyEvent keyEvent) { // Primero realizamos las acciones que sean oportunas // según la tecla pulsada... // ...y a continuación hacemos también uso de la clase base return super.onKeyDown(keyCode, keyEvent); } IUDM © 2014-2015 Escuela Politécnica Superior 34 Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Máster Universitario en Desarrollo de Software para Dispositivos Móviles ¿Preguntas...? IUDM © 2014-2015 Escuela Politécnica Superior 35