1. Code
  2. Mobile Development
  3. Android Development

Android SDK: Dibujar con opacidad

Este tutorial muestra cómo permitir a los usuarios dibujar con valores de opacidad. Si bien esta publicación se basa en tutoriales relacionados publicados en Mobiletuts+, puedes sumergirte directamente en esta lección sin completar las publicaciones anteriores. ¡Sigue leyendo!
Scroll to top

Spanish (Español) translation by CYC (you can also view the original English article)

Este tutorial muestra cómo permitir a los usuarios dibujar con valores de opacidad. Si bien esta publicación se basa en tutoriales relacionados publicados en Mobiletuts+, puedes sumergirte directamente en esta lección sin completar las publicaciones anteriores. ¡Sigue leyendo!

La plataforma Android proporciona los recursos para crear la funcionalidad de dibujo mediante la interacción con pantalla táctil. En una serie previa de Mobiletuts+ sobre la creación de una aplicación de dibujo, trabajamos a través de las características esenciales de la interacción de dibujo en Android, incluida la selección de una paleta de colores y la elección de tamaños de pincel. En este tutorial, nos centraremos en cómo mejorar una aplicación de dibujo añadiendo opacidad a las funciones de dibujo de la aplicación. Puedes completar este tutorial sin haber completado las publicaciones relacionadas, pero haremos referencia a todo el material anterior.


Vista previa final

Aquí hay una vista previa de la funcionalidad de opacidad para la aplicación de dibujo:

Drawing With OpacityDrawing With OpacityDrawing With Opacity

La descarga del código fuente incluye la aplicación independiente que creamos en este tutorial, así como una versión mejorada de la aplicación que creamos durante la serie de dibujos. Aquí hay una vista previa con la funcionalidad adicional:

Drawing With OpacityDrawing With OpacityDrawing With Opacity

1. Inicia tu aplicación

Paso 1

Al igual que con el tutorial de dibujo de patrones, vamos a pasar por alto algunos de los detalles que exploramos en la serie de dibujos anterior para que podamos centrarnos en la funcionalidad de opacidad en el dibujo. Además de usar niveles de opacidad, también agregaremos un control a la interfaz de usuario para que el usuario pueda seleccionar su propio nivel de opacidad para el dibujo.

Si completaste la serie de aplicaciones de dibujo, puedes ir directamente a la parte 2, paso 1 ahora. Si estás creando una nueva aplicación para este tutorial, inicia un nuevo proyecto de Android en Eclipse ahora. Elija 14 como tu nivel mínimo de API y selecciona otras configuraciones de tu elección. Al crear la aplicación, puedes dejar que Eclipse cree una actividad y un diseño en blanco.

Agrega una nueva clase a tu aplicación, llamándola "DrawingView". Comienza con el mismo contenido de clase que usamos para el tutorial de dibujo de patrones:

1
import android.content.Context;
2
import android.graphics.Bitmap;
3
import android.graphics.Canvas;
4
import android.graphics.Paint;
5
import android.graphics.Path;
6
import android.util.AttributeSet;
7
import android.view.MotionEvent;
8
import android.view.View;
9
10
public class DrawingView extends View {
11
12
  //drawing path

13
	private Path drawPath;
14
	//drawing and canvas paint

15
	private Paint drawPaint, canvasPaint;
16
	//initial color

17
	private int paintColor = 0xFFFF0000;
18
	//canvas

19
	private Canvas drawCanvas;
20
	//canvas bitmap

21
	private Bitmap canvasBitmap;
22
23
	//constructor

24
	public DrawingView(Context context, AttributeSet attrs){
25
		super(context, attrs);
26
		setupDrawing();
27
	}
28
29
	//prepare drawing

30
	private void setupDrawing(){
31
		drawPath = new Path();
32
		drawPaint = new Paint();
33
		drawPaint.setColor(paintColor);
34
		drawPaint.setAntiAlias(true);
35
		drawPaint.setStrokeWidth(50);
36
		drawPaint.setStyle(Paint.Style.STROKE);
37
		drawPaint.setStrokeJoin(Paint.Join.ROUND);
38
		drawPaint.setStrokeCap(Paint.Cap.ROUND);
39
		canvasPaint = new Paint(Paint.DITHER_FLAG);
40
	}
41
42
	//view assigned size

43
	@Override
44
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
45
		super.onSizeChanged(w, h, oldw, oldh);
46
		canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
47
		drawCanvas = new Canvas(canvasBitmap);
48
	}
49
50
	//draw view

51
	@Override
52
	protected void onDraw(Canvas canvas) {
53
		canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
54
		canvas.drawPath(drawPath, drawPaint);
55
	}
56
57
	//respond to touch interaction

58
	@Override
59
	public boolean onTouchEvent(MotionEvent event) {
60
		float touchX = event.getX();
61
		float touchY = event.getY();
62
		//respond to down, move and up events

63
		switch (event.getAction()) {
64
		case MotionEvent.ACTION_DOWN:
65
			drawPath.moveTo(touchX, touchY);
66
			break;
67
		case MotionEvent.ACTION_MOVE:
68
			drawPath.lineTo(touchX, touchY);
69
			break;
70
		case MotionEvent.ACTION_UP:
71
			drawPath.lineTo(touchX, touchY);
72
			drawCanvas.drawPath(drawPath, drawPaint);
73
			drawPath.reset();
74
			break;
75
		default:
76
			return false;
77
		}
78
		//redraw

79
		invalidate();
80
		return true;
81
	}
82
}

El contenido de la clase contiene la funcionalidad estándar de la aplicación de dibujo. Para obtener más información sobre los detalles, consulta la serie aplicación de dibujo.

Paso 2

Vamos a incluir ahora la nueva Vista en la interfaz de usuario de la aplicación junto con los otros controles. Abre tu archivo de diseño. Reemplaza el contenido con el siguiente diseño:

1
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
2
	xmlns:tools="http://schemas.android.com/tools"
3
	android:layout_width="match_parent"
4
	android:layout_height="match_parent"
5
	android:background="#FFCCCCCC"
6
	android:orientation="vertical"
7
	tools:context=".MainActivity" >
8
9
</LinearLayout>

Dentro del diseño lineal, primero agrega una instancia de la vista personalizada, cambiando el nombre del paquete para adaptarlo al tuyo:

1
<com.example.opacitydraw.DrawingView
2
	android:id="@+id/drawing"
3
	android:layout_width="fill_parent"
4
	android:layout_height="0dp"
5
	android:layout_marginBottom="3dp"
6
	android:layout_marginLeft="5dp"
7
	android:layout_marginRight="5dp"
8
	android:layout_marginTop="3dp"
9
	android:layout_weight="1"
10
	android:background="#FFFFFFFF" />

Añadiremos más a la interfaz de usuario en la siguiente sección.


2. Agrega el control de opacidad

Paso 1

En esta sección, agregaremos un botón para controlar el nivel de opacidad de nuestro "pincel".

En tu diseño, después de la Vista personalizada, agrega el botón para un control de opacidad:

1
<ImageButton
2
	android:id="@+id/opacity_btn"
3
	android:layout_width="wrap_content"
4
	android:layout_height="fill_parent"
5
	android:layout_gravity="center"
6
	android:contentDescription="opacity"
7
	android:src="@drawable/opacity" />

El botón lanzará un control a través del cual el usuario podrá establecer el nivel de opacidad para el dibujo. Usaremos una ID para referirnos al botón en el código de Actividad.

Consejo: Si estás mejorando la aplicación de la serie de dibujos, agrega este botón en la sección superior de tu archivo de diseño junto con los otros botones, usando las mismas propiedades de diseño que utilizó para ellos.

Paso 2

Notarás que el Botón de Imagen hace referencia a un archivo dibujable. Vamos a crear esto ahora. Agrega un nuevo archivo a la(s) carpeta(s) dibujable(s) de tu aplicación y asígnale el nombre "opacity.xml" para que coincida con el atributo fuente que agregamos al elemento XML del botón Imagen. Incluye el siguiente contenido:

1
<shape xmlns:android="http://schemas.android.com/apk/res/android"
2
	android:dither="true"
3
	android:shape="oval" >
4
5
	<size
6
		android:height="20dp"
7
		android:width="20dp" />
8
9
	<gradient
10
		android:endColor="#00000000"
11
		android:startColor="#FF000000"
12
		android:type="linear" />
13
14
	<stroke
15
		android:width="1dp"
16
		android:color="#66000000" />
17
18
</shape>

La forma es un círculo con una opacidad completa en un lado y una transparencia total en el otro, con un relleno de degradado entre ellos.

Consejo: Si estás trabajando en la aplicación de la serie de dibujos, puedes usar los valores de dimensión para el tamaño mediano en lugar de codificar con fuerza un valor de dimensión en tu forma dibujable.

Paso 3

Ahora diseñemos el pequeño control emergente que queremos que aparezca cuando el usuario presione el botón de opacidad. Agrega un nuevo archivo a la carpeta de diseño de tu aplicación, dándole el nombre "opacity_chooser.xml". Ingresa el siguiente esquema de diseño:

1
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2
	android:layout_width="match_parent"
3
	android:layout_height="match_parent"
4
	android:gravity="center"
5
	android:orientation="vertical" >
6
</LinearLayout>

Dentro del diseño lineal, primero agrega un texto informativo:

1
<TextView
2
	android:id="@+id/opq_txt"
3
	android:layout_width="fill_parent"
4
	android:layout_height="wrap_content"
5
	android:layout_marginTop="5dp"
6
	android:gravity="center"
7
	android:text="100%"
8
	android:textStyle="bold" />

Actualizaremos el texto a medida que el usuario cambie el nivel, comenzando al 100% para una opacidad total al principio. También usaremos la ID en Java. Para establecer el nivel de opacidad, el elemento lógico de la interfaz de usuario de Android es una barra de búsqueda. Con una barra de búsqueda, el usuario interactúa con un control deslizante, que configuraremos para tener 0% de opacidad a la izquierda y 100% a la derecha. Agrega la barra de búsqueda después de la vista de texto:

1
<SeekBar
2
	android:id="@+id/opacity_seek"
3
	android:layout_width="fill_parent"
4
	android:layout_height="wrap_content"
5
	android:layout_margin="5dp" />

También nos referiremos a esto en Java. Finalmente, agrega un botón Aceptar:

1
<Button
2
	android:id="@+id/opq_ok"
3
	android:layout_width="wrap_content"
4
	android:layout_height="wrap_content"
5
	android:text="OK" />

Cuando el usuario hace clic en Aceptar, implementaremos el nivel de opacidad elegido para las siguientes operaciones de dibujo. También retendremos el nivel de opacidad elegido si el usuario vuelve a lanzar el control.

Opacity LevelOpacity LevelOpacity Level

3. Implementar cambios de opacidad

Paso 1

Consejo: Ahora puedes saltar al paso 2 si estás mejorando la aplicación de la serie de dibujos. Agrega el código restante a tus clases de vista de dibujo principal y personalizado.

Abre tu clase principal de Actividad. Agrega las siguientes declaraciones de importación:

1
import android.app.Dialog;
2
import android.view.View;
3
import android.view.View.OnClickListener;
4
import android.widget.Button;
5
import android.widget.ImageButton;
6
import android.widget.SeekBar;
7
import android.widget.SeekBar.OnSeekBarChangeListener;
8
import android.widget.TextView;

Extiende la línea de apertura de la declaración de clase para implementar recepción por clic:

1
public class MainActivity extends Activity implements OnClickListener

Agrega un método onClick a tu clase:

1
@Override
2
public void onClick(View view){
3
//respond to clicks		

4
}

Agregaremos un método a la clase de Vista personalizada para establecer el nivel de opacidad para las operaciones de dibujo. Para que podamos hacer esto, agrega una variable de instancia a la clase, antes de onCreate:

1
private DrawingView drawView;

En onCreate, obtén una referencia a la instancia de la clase de vista personalizada que tiene en el diseño de tu aplicación:

1
drawView = (DrawingView)findViewById(R.id.drawing);

Podremos llamar a métodos en este objeto para controlar lo que ocurre durante el dibujo.

Paso 2

Antes del método onCreate en tu actividad principal, agrega una variable de instancia para el botón de opacidad:

1
private ImageButton opacityBtn;

En onCreate, recupera una referencia al botón:

1
opacityBtn = (ImageButton)findViewById(R.id.opacity_btn);

Recibe los clics en el botón:

1
opacityBtn.setOnClickListener(this);

En tu método onClick, agrega una prueba condicional para el botón de opacidad (usa un else if si estás mejorando la aplicación de la serie):

1
if(view.getId()==R.id.opacity_btn){
2
	//launch opacity chooser

3
}

Paso 3

Ahora podemos lanzar un control selector para establecer la opacidad usando el diseño que definimos. Dentro del bloque condicional para el botón de opacidad en onClick, crea un objeto Dialog, estableciendo el título y el diseño para él:

1
final Dialog seekDialog = new Dialog(this);
2
seekDialog.setTitle("Opacity level:");
3
seekDialog.setContentView(R.layout.opacity_chooser);

Recupera referencias a la Vista de texto y la Barra de búsqueda que incluimos en el diseño:

1
final TextView seekTxt = (TextView)seekDialog.findViewById(R.id.opq_txt);
2
final SeekBar seekOpq = (SeekBar)seekDialog.findViewById(R.id.opacity_seek);

Establece el máximo en la barra de búsqueda:

1
seekOpq.setMax(100);

Usamos 100 ya que el nivel alfa máximo posible será del 100%.

Paso 4

Antes de continuar con el control de opacidad, agreguemos algunas funcionalidades requeridas a la clase de vista de dibujo personalizado. Comienza con una nueva variable de instancia para almacenar el nivel de opacidad actual:

1
private int paintAlpha = 255;

El método Paint que utilizaremos para establecer la opacidad espera un valor entre 0 y 255. Agrega un método de obtención simple para el valor:

1
public int getPaintAlpha(){
2
	return Math.round((float)paintAlpha/255*100);
3
}

El nivel se almacena como un valor entre 0 y 255, pero queremos mostrarlo como un porcentaje, por lo cual devolveremos un valor entre 0 y 100. Ahora, agrega un método para establecer el valor:

1
public void setPaintAlpha(int newAlpha){
2
	paintAlpha=Math.round((float)newAlpha/100*255);
3
	drawPaint.setColor(paintColor);
4
	drawPaint.setAlpha(paintAlpha);
5
}

En lo anterior, analizamos el valor porcentual, establecimos el color y establecimos el alfa.

Paso 5

Atrás en tu clase de actividad principal, en onClick después de establecer el máximo en el control de Seek Bar, primero recupera el nivel de opacidad existente:

1
int currLevel = drawView.getPaintAlpha();

Muestra esto en la vista de texto y la barra de búsqueda:

1
seekTxt.setText(currLevel+"%");
2
seekOpq.setProgress(currLevel);

Ahora queremos que la pantalla se actualice a medida que el usuario deslice el control hacia arriba y hacia abajo. Agrega el siguiente código de recepción de eventos:

1
seekOpq.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
2
	@Override
3
	public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
4
		seekTxt.setText(Integer.toString(progress)+"%");
5
	}
6
	@Override
7
	public void onStartTrackingTouch(SeekBar seekBar) {}
8
	@Override
9
	public void onStopTrackingTouch(SeekBar seekBar) {}
10
});

Solo tenemos que responder al evento modificado de progreso, en cuyo caso actualizamos la Vista de texto; esto permitirá que el usuario vea su nivel elegido como un valor numérico. Ahora debemos recibir la información del usuario cuando haga clic en el botón Aceptar. Después de que la barra de búsqueda cambie el bloque de código de recepción, recupera una referencia desde el botón Aceptar:

1
Button opqBtn = (Button)seekDialog.findViewById(R.id.opq_ok);

Ahora maneja los clics en él:

1
opqBtn.setOnClickListener(new OnClickListener(){
2
	@Override
3
	public void onClick(View v) {
4
		drawView.setPaintAlpha(seekOpq.getProgress());
5
		seekDialog.dismiss();
6
	}
7
});

Cuando se hace clic en el botón, llamamos al nuevo método que agregamos para cambiar el nivel de opacidad, pasando el nivel elegido por el usuario y luego descartando el diálogo. Completa la sección del botón de opacidad de onClick mostrando el cuadro de diálogo:

1
seekDialog.show();

Sugerencia: Si extiendes la aplicación de la serie con control de opacidad, puedes suponer que el usuario desea utilizar la opacidad completa cuando elige un nuevo color o que desea conservar el nivel de opacidad elegido. Para restablecer al 100%, puedes llamar al método setPaintAlpha en el método paintClicked. Para conservar el nivel alfa elegido, puedes agregar código al método setColor para volver a aplicar el nivel alfa elegido después de configurar el nuevo color.


Conclusión

¡Esto completa la funcionalidad de dibujo de opacidad! Deberías poder ejecutar tu aplicación, establecer un nivel de opacidad y luego ver los resultados en tus operaciones de dibujo. Si estabas trabajando en la aplicación de la serie y la mejoraste con los rellenos de patrón, observa que el control de opacidad también se aplica al dibujo con patrones. Ahora hemos explorado los diversos tipos típicos de procesamiento en las aplicaciones de dibujo, pero todavía hay muchas más que puedes probar en tus propias aplicaciones. En un próximo tutorial, veremos cómo puedes adaptarte a los usuarios que no interactúan a través de pantallas táctiles.