Você está na página 1de 13

1

!"# %&'()*+, -. /+, /)0-.,)+.-,



!"#! 12 034+/+ +.5&6789

Los botones, como el iesto ue vistas, poseen su piopia implementacion uel mtouo
onDraw(). Este mtouo se ejecuta automticamente cuanuo se iepiesenta la vista.
veamos un sencillo ejemplo que uibuja una banueia belga:
/src/MyButton.java

package com.programming.android.prueba;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.widget.Button;

public class MyButton extends Button {
Paint paint = new Paint();

public MyButton(Context context) {
super(context);
}

public void onDraw(Canvas canvas) {

paint.setColor(Color.BLACK);
canvas.drawRect(30, 10, 90, 100, paint);

paint.setColor(Color.YELLOW);
canvas.drawRect(30, 40, 90, 70, paint );

paint.setColor(Color.RED);
canvas.drawRect(30, 70, 90, 100, paint );
}
}
Comencemos el estuuio ue la clase MyButton poi los coloies.
Los coloies en Anuioiu vienen iepiesentauos como enteios en foima ue 4 bytes:
alfa, iojo, veiue y azul (ARuB). Caua componente est compienuiua entie u y 2SS.
La piimeia miue la tianspaiencia: u es totalmente tianspaiente y 2SS totalmente
opaco. Paia las uems, u significa que la componente no contiibuye al coloi y 2SS
que contiibuye al 1uu%. Poi ejemplo, el azul opaco al 1uu% es 0xFF0000FF, y el
veiue 0xFF00FF00.
Paia utilizai un coloi bsico pueues iecuiiii a una ue las constantes ue la clase
Color:
int color = Color.WHITE;

Sin embaigo, es muy iecomenuable cieai iecuisos ue coloi en el aichivo
colors.xml, ya que pueuen sei actualizauos comouamente:

2

/res/values/colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="background_color">#F0F0F0</color>
</resources>
Paia acceuei al iecuiso ue coloi uesue }ava es necesaiio hacei lo siguiente:
int color = getResources().getColor(R.color.background_color);

El mtouo onDraw() tiene un paimetio ue tipo Canvas, que es el maico en el que
se uibuja. Paia uibujai es necesaiio instanciai un objeto ue tipo Paint uonue se
especifica, entie otias cosas, el coloi ue la pintuia y el ancho ue la biocha:
Paint paint = new Paint();
paint.setColor(Color.BLACK);

La clase Canvas uispone ue mtouos paia uibujai lineas, iectngulos, ciiculos, etc.
El piototipo ue drawRect() es el siguiente:
void drawRect (float left, float top, float right, float bottom, Paint paint);

uonue (left, top) son las cooiuenauas uel extiemo supeiioi izquieiuo y (right,
bottom) las uel extiemo infeiioi ueiecho uel iectngulo.
Poi ejemplo, la siguiente instiuccion
canvas.drawRect(30, 10, 90, 100, paint);

uibuja un iectngulo cuyo vitice supeiioi izquieiuo est en (Su, 1u) y el infeiioi
ueiecho en (9u, 1uu):

El mtouo onDraw() uibuja uos iectngulos ms sin contoinos: uno amaiillo con
vitices (Su, 4u) y (9u, 7u), y otio iojo con vitices (Su, 7u) y (9u, 1uu):
paint.setColor(Color.YELLOW);
canvas.drawRect(30, 40, 90, 70, paint );
paint.setColor(Color.RED);
canvas.drawRect(30, 70, 90, 100, paint );

La pintuia ue estos iectngulos se supeipone a la negia uel iectngulo oiiginal,
cieanuo asi una banueia como se pueue vei en la figuia uel piincipio.
La clase Main se encaiga ue instanciai el objeto but ue tipo MyButton, ponei el
fonuo uel boton ue coloi blanco e inflai la vista:

S
/src/Main.java
package com.programming.android.prueba;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;

public class Main extends Activity {
MyButton but;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

but = new MyButton(this);
but.setBackgroundColor(Color.WHITE);
setContentView(but);
}
}
El lienzo (canvas) uispone ue muchos otios mtouos que se ilustian en el siguiente
ejemplo:
setAntiAlias(true) hace que el tiazo sea ms suave.
drawCircle(140,50,20,paint) uibuja un ciiculo ue iauio 2u centiauo en
(x=14u, y=Su), y con el pincel paint.
setStyle(Style.STROKE) fija el estilo uel pincel como solo contoino . 0tias
posibiliuaues son Style.FILL (poi uefecto) y Style.FILL_AND_STROKE.
setStrokeCap(Cap.ROUND) hace que el tiazo se extienua en foima ue
semiciiculo. Las otias posibiliuaues son Cap.SQUARE y Cap.BUTT (el tiazo no
se extienue ue ninguna maneia, es la opcion poi uefecto).
drawLine(205,30,205,70,paint) tiaza una iecta uesue (2uS,Su) a (2uS,
7u), es uecii, una iecta veitical con el pincel paint.
drawLines(pts,paint) tiaza las lineas especificauas en el aiiay pts en
giupos ue 4. Poi ejemplo, la piimeia linea sei la que va ue (pts|uj,pts|1j) a
(pts|2j,pts|Sj); la segunua ue (pts|4j,pts|Sj) a (pts|6j,pts|7j), etc.
drawRoundRect(rf,10,10,paint) uibuja un iectngulo ieuonueauo a paitii
uel objeto RectF pasauo como piimei aigumento, que especifica las
fionteias. El segunuo y teicei aigumentos especifican el iauio en el eje x y
en el eje y, iespectivamente, ue ieuonueo ue las esquinas.
drawBitmap(bitmap,30,180,paint) uibuja el objeto ue tipo Bitmap pasauo
como piimei aigumento, colocanuo su esquina supeiioi izquieiua en el
punto ue cooiuenauas (x=Su, y=18u).
:+, ;&6/)-.4-,

0n giauiente ue coloi peimite sombieai las figuias entie uos coloies. Existen
vaiios tipos ue giauientes: LinearGradient, RadialGradient y SweepGradient. En
el ejemplo que sigue se utiliza uno iauial:
RadialGradient grad = new RadialGradient (0, 0, 40,
Color.RED, Color.BLUE, Shader.TileMode.REPEAT);

Los cambios comienzan en un punto y se espaicen iauialmente en ciiculo. El
centio ue este ciiculo ue giauiente coiiesponue a los uos piimeios aigumentos:
(x=u,y=u). El teiceio es el iauio uel ciiculo paia el giauiente ue coloi. El cuaito y
4
quinto aigumentos son, iespectivamente, el coloi uel centio (Color.RED) y uel
extiemo uel ciiculo ue giauiente (Color.BLUE). El ltimo aigumento es el mouo ue
sombieauo: las posibiliuaues son: CLAMP, MIRROR y REPEAT.
/src/Main.java
package com.example.drawing;

import android.os.Bundle;
...
import android.widget.Button;

class MyButton extends Button {
Paint paint = new Paint();
public MyButton(Context context) {
super(context);
}
public void onDraw(Canvas canvas) {
paint.setColor(Color.BLACK);
paint.setStrokeWidth(3);
canvas.drawCircle(40, 50, 20, paint);

paint.setAntiAlias(true);
canvas.drawCircle(90, 50, 20, paint);

paint.setStyle(Style.STROKE);
canvas.drawCircle(140, 50, 20, paint);

canvas.drawPoint(190, 50, paint);

paint.setStrokeCap(Cap.ROUND);
canvas.drawLine(205, 30, 205, 70, paint);
canvas.drawLine(205, 70, 255, 70, paint);

float[] pts = new float[8];
pts[0]=205; pts[1]=30; pts[2]=205; pts[3]=70;
pts[0]=205; pts[1]=70; pts[2]=255; pts[3]=70;
canvas.drawLines(pts, paint);

Rect r = new Rect(20, 90, 80, 120);
canvas.drawRect(r, paint);

RectF rf = new RectF(90, 90, 150, 120);
canvas.drawRoundRect(rf, 10, 10, paint);

RadialGradient grad = new RadialGradient (0, 0, 40,
Color.RED, Color.BLUE, Shader.TileMode.REPEAT);
paint.setShader(grad);
paint.setStyle(Style.FILL);
canvas.drawCircle(190, 120, 30, paint);

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.imagen);
canvas.drawBitmap(bitmap, 30, 180, paint);
}
}
public class Main extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyButton button = new MyButton(this);
setContentView(button);
}
}

S
!"#< :6 *26,- ===>?44+.

Nuestia clase TTTButton plantea el siguiente pioblema: al cambiai el coloi ue
fonuo uel boton iemplazamos los uibujables (uiawable) con que la clase Button
viene poi uefecto. Poi uefecto, el boton se uibuja como un iectngulo centiauo en
la vista ue fonuo peio ligeiamente ms pequeo que la vista. En la uniuau 9, al
cambiai el coloi ue fonuo uel boton, eliminamos ese ligeio pauuing, y como
iesultauo los botones uel tableio apaiecian pegauos unos a otios como se pueue
vei en la siguiente figuia.


El boton TTTButton ue la uniuau 9 utilizaba la implementacion poi uefecto ue
onDraw(). En esta uniuau, vamos a sobiecaigai el mtouo onDraw() como sigue:
protected void onDraw (Canvas canvas){
super.onDraw(canvas);

float width = getWidth();
float height = getHeight();
float padding = 10;

Paint backgroundPaint = new Paint();
backgroundPaint.setColor(color);
canvas.drawRect(padding, padding, width-padding, height-padding, backgroundPaint);

float x = 0.5f * width;
float y = 0.5f * height;

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(textColor);
paint.setStrokeWidth(2);
paint.setTextAlign(Align.CENTER);
paint.setTextSize(20);
canvas.drawText(symbol, x, y, paint);
}
6
Al comienzo ue onDraw() se guaiua la anchuia y la altuia uel boton en width y
height, iespectivamente:
float width = getWidth();
float height = getHeight();

A continuacion, instanciamos un objeto ue tipo Paint y le asignamos el coloi
iepiesentauo poi el miembio color (echa un vistazo a la clase TTTButton.java
completa ms auelante):
Paint backgroundPaint = new Paint();
backgroundPaint.setColor(color);

Seguiuamente, se uibuja un iectngulo con la biocha backgroundPaint en el maico
canvas:
canvas.drawRect(padding, padding, width-padding, height-padding, backgroundPaint);

Este iectngulo tiene como vitice supeiioi izquieiuo (10, 10) y como vitice
infeiioi ueiecho (width-10, height-10).
Paia esciibii el simbolo uel jugauoi actual uentio uel iectngulo utilizamos el
mtouo drawText() ue Canvas, que esciibe la cauena pasaua como piimei
aigumento con la biocha pasaua como ltimo aigumento:
canvas.drawText(symbol, x, y, paint);

uonue x e y son las cooiuenauas uel punto meuio uel iectngulo:
float x = 0.5f * width;
float y = 0.5f * height;

En la uniuau anteiioi los simbolos se uibujaban meuiante llamauas a drawX() y
drawO(). En nuestia nueva veision, el mtouo onDraw() se ejecutai
automticamente cuanuo el boton necesite uibujaise. Esto ocuiiii uespus ue las
llamauas a los nuevos drawX() y drawO(), que alteian el coloi uel texto y uel fonuo,
asi como el simbolo uibujauo.
Poi ejemplo, drawX() queua ue la siguiente maneia:
public void drawX(){
color = xBackgrColor;
symbol = x;
textColor = xColor;
this.setClickable(false);
}

uonue xBackgrColor, x y xColor son miembios estticos constantes ue TTTButton:
private String symbol = noSymbol;
private int color = voidColor;
private int textColor = voidColor;

private static String x = "x";
private static int xColor = Color.WHITE;
private static int xBackgrColor = Color.RED;

La clase TTTButton al completo queua como sigue:


7
src/TTTButton.java

package com.programming.android.ttt.ttt2;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.util.AttributeSet;
import android.widget.Button;

public class TTTButton extends Button {
private String symbol = noSymbol;
private int color = voidColor;
private int textColor = voidColor;

private static String noSymbol = "";
private static String x = "x";
private static String o = "o";

private static int voidColor = Color.BLACK;
private static int xColor = Color.WHITE;
private static int oColor = Color.BLACK;

private static int voidBackgrColor = Color.LTGRAY;
private static int xBackgrColor = Color.RED;
private static int oBackgrColor = Color.WHITE;

protected void onDraw (Canvas canvas){
super.onDraw(canvas);

float width = getWidth();
float height = getHeight();
float padding = 10;

Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
backgroundPaint.setColor(color);
canvas.drawRect(padding, padding, width-padding, height-padding,
backgroundPaint);

float x = 0.5f * width;
float y = 0.5f * height;

Paint paint = new Paint();
paint.setColor(textColor);
paint.setStrokeWidth(2);
paint.setTextAlign(Align.CENTER);
paint.setTextSize(20);
canvas.drawText(symbol, x, y, paint);
}
public TTTButton(Context context, AttributeSet attrs){
super(context, attrs);
reset();
}
public void drawX(){
color = xBackgrColor;
symbol = x;
textColor = xColor;
this.setClickable(false);
}
public void drawO(){
color = oBackgrColor;
symbol = o;
textColor = oColor;
this.setClickable(false);
}
public void reset(){
color = voidBackgrColor;
symbol = noSymbol;
textColor = voidColor;
this.setClickable(true);
}
}
8
!"#@ :6 *26,- A6).#B6C6

Esta clase no cambia con iespecto a la ue la uniuau 9. La incluimos aqui poi
completituu:
src/Main.java

package com.programming.android.ttt.ttt2;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class Main extends Activity implements View.OnClickListener{
private Game game;
private TextView textView;
private int ids [] = {R.id.button1, R.id.button2, R.id.button3,
R.id.button4, R.id.button5, R.id.button6,
R.id.button7, R.id.button8, R.id.button9};

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
registerListeners();
textView = (TextView) findViewById(R.id.textView);
game = new Game();
}

private int fromIdToPosition (int id){
for (int i=0; i<9; i++)
if (id == ids[i])
return i+1;
return -1;
}

public void onClick(View v) {
TTTButton button = (TTTButton) v;

if (!game.isGameActive())
return;

if (game.isCurrentSymbolX())
button.drawX();
else
button.drawO();

game.play(fromIdToPosition(button.getId()));

if (game.isWon())
textView.setText("Player " + game.getCurrentPlayer() + " is the winner");
else if (game.isDrawn())
textView.setText("Game drawn");

game.switchCurrentSymbolAndPlayer();
}

private void registerListeners(){
TTTButton button;
for (int i=0; i<9; i++) {
button = (TTTButton) findViewById(ids[i]);
button.setText(Integer.toString(i+1));
button.setOnClickListener(this);
}
}
}

9
El ficheio ue uiseo utiliza ahoia los nuevos botones, como es natuial:
res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<com.programming.android.ttt.ttt2.TTTButton
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"/>
<com.programming.android.ttt.ttt2.TTTButton
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2"/>
<com.programming.android.ttt.ttt2.TTTButton
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.programming.android.ttt.ttt2.TTTButton
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="4"/>
...
<com.programming.android.ttt.ttt2.TTTButton
android:id="@+id/button9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="9"/>
</LinearLayout>

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Scores" />

</LinearLayout>








1u
1B-&*)*)+ !"#!

En este ejeicicio pueues ieutilizai las clases Main.java y Game.java uel ejeicicio
9.2. El nico cambio tenui lugai en la clase TTTButton, en la que vas a auaptai los
mtouos on() y off() paia que ajusten el valoi ue currentColor a veiue y giis,
iespectivamente, en lugai ue invocai setText(). Tambin tenuis que sobiesciibii
el mtouo onDraw() paia uibujai un ciiculo ue iauio 1S centiauo en el centio uel
iectngulo uel boton. El mtouo drawCircle() ue Canvas tiene el siguiente
piototipo:
void drawCircle (float x, float y, float radio, Paint paint);
uonue (x,y) es el centio uel ciiculo, radio es el iauio uel ciiculo y paint es la
biocha. El coloi uel ciiculo sei currentColor, ue tal foima que apaiezca veiue
cuanuo el boton est on y giis cuanuo est off. Tambin pueues utilizai un bitmap
uifeiente paia caua estauo uel boton.

!"#@ D.)06*)+.-,

La platafoima Anuioiu piopoiciona cuatio tipos ue animaciones:
Imgenes uIF animauas. Los uIF animauos son ficheios gificos que
contienen vaiios fotogiamas (fiames).
Animaciones fotogiama a fotogiama. Neuiante la clase AnimationDrawable,
el piogiamauoi suministia los fotogiamas y las tiansiciones entie ellos.
Animaciones ue inteipolacion (tweening). Estas animaciones pueuen
iesolveise con couigo XNL y se aplican a cualquiei vista.
Animaciones con la biblioteca 0PEN uL ES.

D.)06*)+.-, /- ).4-&E+26*)F.

Estos son los cuatio tipos ue animaciones ue inteipolacion:
Animacion alpha paia cambiai la tianspaiencia ue una vista.
Animacion rotate paia iotai una vista un cieito ngulo alieueuoi ue un eje
o punto ue pivote.
Animacion scale paia agianuai o uisminuii una vista segn el eje X e Y..
Animacion translate paia uesplazai una vista a lo laigo uel eje X e Y.
Las animaciones ue inteipolacion se pueuen uefinii tanto en XNL como en }ava.
Poi ejemplo, paia cieai una animacion alpha en XNL, aauiiemos una caipeta ue
nombie anim a la caipeta ies ue nuestio pioyecto. Bentio ue esta caipeta,
aauiiemos un aichivo ue nombie alpha.xml. En el ejemplo siguiente, el atiibuto
android:fromAlpha especifica el valoi inicial ue la tiaspaiencia y
11
android:toAlpha el valoi final. El atiibuto android:duration especifica la
uuiacion ue la animacion:
res/anim/alpha.xml

<?xml version="1.0" encoding="UTF-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="5000">
</alpha>
El ficheio ue uiseo ue este ejemplo especifica uos botones: uno que aiianca la
animacion y otio en el centio uel uispositivo que es el boton animauo:
res/layout/main.xml

<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=".Main" >

<Button
android:id="@+id/button_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Start alpha animation" />

<Button
android:id="@+id/button_animated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Animated button" />

</RelativeLayout>
El pioceso que asocia una animacion uefiniua en un ficheio XNL a una vista
concieta se uenomina caigai (loau) la animacion. Paia ello se utiliza la clase ue
ayuua AnimationUtils. El couigo que sigue caiga la animacion uefiniua en
alpha.xml y la asocia con el boton ue iuentificauoi button_animated:








12
src/Main.java

package com.example.animaciones;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.Toast;

public class Main extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button button_start = (Button) findViewById(R.id.button_start);
final Button button_animated = (Button) findViewById(R.id.button_animated);

button_start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Animation animation = AnimationUtils.loadAnimation(Main.this, R.anim.alpha);
button_animated.startAnimation(animation);
}
});
}
}
Las animaciones se pueuen combinai en XNL meuiante un elemento <set> . En el
siguiente ficheio se especifica una animacion ue escala seguiua poi una ue
iotacion. La segunua empieza cuanuo acaba la piimeia pues el atiibuto
android:startOffSet ue la segunua animacion se iguala a la uuiacion ue la
piimeia (Suuu milisegunuos). La piimeia animacion uobla el tamao ue la vista
segn el eje X y lo tiiplica segn el eje Y. La segunua animacion iota la vista
alieueuoi ue su punto meuio (android:pivotY="50%"):
res/anim/alpha.xml

<?xml version="1.0" encoding="UTF-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1.0"
android:toXScale="2.0"
android:fromYScale="1.0"
android:toYScale="3.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="5000"/>
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="4000"
android:startOffset="5000"/>
</set>

1S
El atiibuto android:fillAfter peimite especificai si se quieie que la vista vuelva
o no a su estauo inicial. Si le asignamos el valoi true, la vista no volvei a su estauo
inicial.

1B-&*)*)+ !"#<

0tiliza una animacion paia hacei ms atiactivo el juego.

Você também pode gostar