Android Custom View diegozabot@yahoo.it
Creazione di una Custom View (1) La classe View è la classe madre di tutti i componenti visuali di Android. Ogni sottoclasse implementa il metodo ondraw(canvas) responsabile del disegno della componente. Procediamo come segue: 1. creare una nuova classe estendendo View 2. implementare un costruttore 3. fare l override del metodo ondraw( ) 4. impostare la View come vista della Activity 5. nel caso serva, implementare l ontouch
Creazione di una Custom View (2) 1. Creare una nuova classe estendendo View e dichiarare gli attributi che servono all'interno della View: public class MyView extends View{ private float x,y; private float raggio; private Paint p; In questo esempio vogliamo disegnare un cerchio, quindi dichiariamo due variabili per il centro, un raggio e un oggetto di classe Paint (utilizzato per il disegno).
Creazione di una Custom View (3) 2. Implementare un costruttore che inizializza gli attributi: public MyView(Context context) { super(context); p=new Paint(); p.setantialias(true); p.setcolor(color.blue); x=100; y=200; raggio=100; Inizializzo l'oggetto di classe Paint per poter disegnare in blu e assegno un valore iniziare al centro e al raggio del cerchio.
Creazione di una Custom View (4) 3. Effettuare l'override del metodo ondraw: protected void ondraw(canvas canvas) { super.ondraw(canvas); canvas.drawcolor(color.black); canvas.drawcircle(x, y, raggio, p); Utilizzo dei metodi della classe Canvas per impostare il colore di sfondo e disegnare un cerchio.
Creazione di una Custom View (5) 4. Impostare la view come vista della activity: public class MainActivity extends Activity { @Override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(new MyView(this));
Creazione di una Custom View (6) 5. Eventualmente implementiamo il metodo ontouchevent: public boolean ontouchevent(motionevent event) { // istruzioni return super.ontouchevent(event); Possiamo utilizzare event.getx() ed event.gety() per ricavare il punto di touch sullo schermo e mediante event.getaction() l'azione effettuata che può essere: MotionEvent.ACTION_DOWN MotionEvent.ACTION_UP MotionEvent.ACTION_MOVE
Creazione di una Custom View (6) Quindi nell'esempio faremo disegnare un nuovo cerchio al tocco: public boolean ontouchevent(motionevent event) { switch(event.getaction()){ case MotionEvent.ACTION_DOWN: x=event.getx(); y=event.gety(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_MOVE: invalidate(); // forza il ridisegno della view return true; // abbiamo gestito l'evento Spostiamo il cerchio solo quando tocchiamo lo schermo.
Esercizio CustomView Creare una view che ad ogni tocco genera 100 cerchi blu con dimensioni, posizioni e alpha channel differenti.
Nascondere StatusBar e TitleBar Una applicazione Android solitamente riserva dello spazio nella parte alta dello schermo per la Taskbar (o statusbar) e la Titlebar. Per eliminarle e avere la view a schermo intero: protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); // elimina la titlebar requestwindowfeature(window.feature_no_title); // elimina la statusbar getwindow().setflags(windowmanager.layoutparams.flag_fullscreen, WindowManager.LayoutParams.FLAG_FULLSCREEN); setcontentview(new MyView(this)); * Attenzione: eliminanto la statusbar, l utente non vede le notifiche di sistema
CustomView da xml Nel caso in cui vogliamo utilizzare la nostra View impostando i parametri da xml, dobbiamo utilizzare un altro costruttore della Custom, quello che riceve anche gli attributi di layout: public MyView(Context context, AttributeSet attrs) { super(context, attrs); Se nella palette di oggetti ci spostiamo nel cassetto Custom & Library Views e diamo refresh, potremmo trovare la nostra View che possiamo personalizzare da xml.
Caricare una bitmap La classe BitmapFactory possiede un metodo statico chiamato decoderesource. Come primo argomento gli passiamo un puntatore alle risorse (mediante il metodo getresources) e come secondo argomento l id dell immagine. Bitmap b=bitmapfactory.decoderesource(getresources(), R. drawable.ic_launcher); Per disegnarla utilizziamo il metodo drawbitmap di Canvas (quindi nel metodo ondraw). drawbitmap vuole la bitmap, la posizione e un oggetto Paint (che ora non utilizzeremo): canvas.drawbitmap(b, x, y, null);
Esercizio CustomView Esercizio 1: Spostare una immagine in maniera automatica per il canvas, facendo attenzione a non farla uscire dai limiti. Esercizio 2: Creare due zone di touch a destra e sinistra del canvas da usare come controllo per far spostare una immagine a destra e a sinistra.
Definire un hot-spot (1) In una View custom possiamo definire alcune zone sensibili al tocco. Solitamente sono zone rettangolari, contraddistinte da un punto di origine (top, left) e un punto di termine (bottom, right). Per questo motivo possiamo utilizzare la classe Rect per definire una zona rettangolare mediante interi (o RectF se le coordinate sono float). Rect zona1=new Rect(top, left, bottom, right); Uno dei metodi della classe Rect è contains(x, y) che ritorna vero o falso a seconda se il punto (x,y) è contenuto nella zona rettangolare.
Definire un hot-spot (2) L oggetto Rect può essere utilizzato sia per disegnare una immagine direttamente in una zona che per rilevare una pressione (touch) nella zona stessa. Esempio: Bitmap b; Rect zona1; public MyView(Context context) { super(context); b = BitmapFactory.decodeResource( getresources(), R.drawable.ic_launcher); zona1 = new RectF(100, 100, 100 + b.getwidth(), 100 + b.getheight()); Definisco una zona che contiene l immagine ma traslata di (100,100) dall origine
Definire un hot-spot (3) Per disegnare l immagine usiamo un metodo drawbitmap differente Canvas.drawBitmap(Bitmap b, Rect source, Rect dest, Paint paint); Disegnamo la bitmap (o la parte delimitata da source) dentro dest. protected void ondraw(canvas canvas) { super.ondraw(canvas); canvas.drawcolor(color.black); canvas.drawbitmap(b, null, zona1, null); La zona rettangolare può anche essere disegnata con il metodo drawrect di Canvas: canvas.drawrect(zona1, paint);
Definire un hot-spot (4) Per rilevare il touch sulla zona, utilizziamo il metodo contains in ontouch: public boolean ontouch(motionevent event) { switch(event.getaction( )){ case MotionEvent.ACTION_UP: if( zona1.contains(event.getx(), event.gety()) // abbiamo toccato la zona, fare qualcosa break; Se dobbiamo rilevare più zone di touch su una View Custom, può esser comodo istanziare un array di Rect che definiscono gli hot-spot.