Modificación de vistas existentes

Si revisas la jerarquía de vistas en Android verás cómo hay pocas vistas que extiendan directamente de View. Lo más frecuente es aprovechar otra vista como Text View o ViewGroup para no empezar el trabajo desde cero.

En este apartado aprenderemos a utilizar esta estrategia.

Ejercicio paso a paso:  Un EditText tuneado.

 

En este ejercicio vamos a ver lo sencillo que resulta modificar el aspecto de una vista ya existente. En concreto vamos a modificar un EditTextpara que muestre los números de línea.

 

1.    Crea un nuevo proyecto. En el primer cuadro de diálogo introduce los siguientes datos:

Application Name: EditTextTuneado

Package name: com.example.edittexttuneado

Minimum Required SDK: API 4 (1.6)

Target SDK: API 17 (4.2)

Compile With: API 17 (4.2)

2.     Crea la nueva clase EditTextTuneado con el siguiente código.

public class EditTextTuneadoextends EditText {

       private Paint pincel;

       public EditTextTuneado(Context context, AttributeSet attrs) {

             super(context, attrs);

             pincel = new Paint();

             pincel.setColor(Color.BLACK);

             pincel.setTextAlign(Paint.Align.RIGHT);

             pincel.setTextSize(28);

       }

       @Override

       protected void onDraw(Canvas canvas) {

             Rect rect = new Rect();

             for (int linea = 0; linea < getLineCount(); linea++) {

                    int lineaBase = getLineBounds(linea, rect);

                    canvas.drawLine(rect.left, lineaBase + 2, rect.right,
                                                                                        lineaBase + 2, pincel);

                    canvas.drawText("" + (linea + 1), getWidth() - 2,
                                                                                       lineaBase, pincel);

             }

             super.onDraw(canvas);

       }

}

Observa como nuestra clase ha de extender la clase en la que nos queremos basar. En el constructor creamos un objeto Paint y lo inicializamos. Este objeto será utilizado exclusivamente en el método onDraw(); sin embargo no resulta conveniente crearlo dentro del método.

Si lo hiciéramos así el objeto tendría que ser creado cada vez que es utilizado, lo cual sería muy poco eficiente.

En el método onDraw vamos a recorrer todas las líneas. El método getLineCount() nos informa de cuántas hay. Para cada línea llamamos a getLineBouds() para averiguar dónde se dibuja esta línea. Nos devuelve en lineaBase la línea que usaríamos para subrayar esta línea y en rect un rectángulo que enmarcaría la línea. La siguiente línea dibuja una línea horizontal en todo el ancho y la siguiente introduce un texto a la derecha donde se muestra el número de la línea.

Terminamos llamando al super para que termine de dibujar el TextView. Esta acción suele realizarse en primer lugar; pero en nuestro caso se ha preferido que las líneas queden por debajo.

3.     Reemplaza el layout de la actividad principal por:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context=".MainActivity" >

    <com.example.edittexttuneado.EditTextTuneado

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:text="curso de Android\nSegunda línea\nTercera línea"

        android:textAppearance="?android:attr/textAppearanceLarge"

        android:typeface="monospace" />

</RelativeLayout>

4.     Verifica el resultado.

Ejercicio paso a paso:  Adaptando la vista a diferentes densidades gráficas.

 

1.    Si ejecutas la aplicación en dispositivos con diferentes resoluciones observarás que los números de línea se muestran con un tamaño muy diferente. A la izquierda se muestra el resultado con un ancho de 240 píxeles y a la derecha en uno de 800.

La causa de este problema es que se ha utilizado una tamaño de texto de 28 píxeles (setTextSize(28)) que puede ser adecuado para dispositivos con mucha densidad gráfica (píxeles/pulgada) y excesivo para otros. Este problema se soluciona en el diseño de layouts en XML usando medidas como dp (píxeles independientes de la densidad) en lugar de píxeles reales.

Cuando trabajamos con dp hemos de diseñar suponiendo una densidad de 160 ppp (píxeles/pulgada). Si luego el dispositivo tiene otra densidad, reajustará para que el tamaño no cambie. Visto desde otro punto de vista: un dp es una medida de tamaño real en pantalla, como puede ser mm o in. La diferencia es que un dp equivale a 1/160 pulgadas.

2.     Desde código no podemos usar dp; pero va a ser muy fácil emularlos. Introduce en el constructor (clase EditTextTuneado.java) la siguiente línea:

float densidad = getResources().getDisplayMetrics().density;

Ahora podemos multiplicar una medida expresada en dp por densidad y obtendremos los píxeles reales a los que corresponde en este dispositivo.

3.     Reemplaza setTextSize(28) por setTextSize(12*densidad). Donde 12 es el tamaño deseado en dp.

4.     Verifica ahora el resultado.