Rispondi 
 
Valutazione discussione:
  • 0 voti - 0 media
  • 1
  • 2
  • 3
  • 4
  • 5
Custom View: come realizzare un orologio analogico
Autore Messaggio
Bay's Chef Offline
Administrator
*******

Messaggi: 73
Registrato: Jun 2012
Reputazione: 0
Messaggio: #1
Custom View: come realizzare un orologio analogico
Una delle caratteristiche più interessanti del sistema grafico di Android è quella di permetterci di creare delle View personalizzate (custom view, per l'appunto), per permetterci di rappresentare dati in forme non previste dalle View offerte di default. Per mostrare come, ho scelto di realizzare un semplicissimo orologio analogico, dotato delle tre lancette per ore, minuti e secondi.

Vediamo direttamente il codice, che poi andrò a spiegare passo per passo:

    PROGRAMMAZIONE ANDROID
public class ClockView extends View {
 
	float ore = 0;
	float minuti = 0;
	float secondi = 0;
	Paint paint;
	Bitmap bg, resBg;
	int width, height;
 
	public ClockView(Context context, AttributeSet attr) {
		super(context, attr);
	    init();
	}
 
	private void init() {
		paint = new Paint();
	    paint.setAntiAlias(true);
	    paint.setStrokeWidth(2);
	    paint.setTextSize(25);
	    paint.setStyle(Paint.Style.STROKE);
	    paint.setColor(Color.RED);
 
	    bg=BitmapFactory.decodeResource(getResources(), R.drawable.bgclock2);
	    resBg=null;
	}
 
	@Override
	protected void onDraw(Canvas canvas) {
 
		if (resBg==null){
 
			int mWidth = getMeasuredWidth();
			int s=mWidth/bg.getWidth();
			width=bg.getWidth()*s;
			height=bg.getHeight()*s;
 
			resBg=Bitmap.createScaledBitmap(bg, width, height, true);
 
		}
 
		int xPoint = getMeasuredWidth() / 2;
	    int yPoint = getMeasuredHeight() / 2;
 
	    float radius = (float) (Math.max(xPoint, yPoint) * 0.38);	    
 
	    canvas.drawBitmap(resBg, xPoint-(resBg.getWidth()/2), (float) (yPoint-(resBg.getHeight()*0.62)), paint);
 
	    paint.setStrokeWidth(2);
	    paint.setColor(Color.RED);
	    canvas.drawLine(xPoint,
	        yPoint,
	        (float) (xPoint + radius * Math.sin((double) (secondi) / 180 * 3.143)),
	        (float) (yPoint - radius * Math.cos((double) (secondi) / 180 * 3.143)), 
	        paint);
 
	    paint.setStrokeWidth(5);
	    paint.setColor(Color.DKGRAY);
	    canvas.drawLine(xPoint,
	        yPoint,
	        (float) (xPoint + ((radius/4)*3) * Math.sin((double) (minuti) / 180 * 3.143)),
	        (float) (yPoint - ((radius/4)*3) * Math.cos((double) (minuti) / 180 * 3.143)), 
	        paint);
 
	    paint.setColor(Color.BLACK);
	    canvas.drawLine(xPoint,
	        yPoint,
	        (float) (xPoint + (radius/2) * Math.sin((double) (ore) / 180 * 3.143)),
	        (float) (yPoint - (radius/2) * Math.cos((double) (ore) / 180 * 3.143)), 
	        paint);
 
	    paint.setStyle(Paint.Style.FILL);
	    canvas.drawCircle(xPoint, yPoint, radius/20, paint);
 
 
	}
 
	public void update(float ore, float minuti, float secondi) {
 
		this.ore  = ore;
		this.minuti = minuti;
		this.secondi = secondi;
 
	    invalidate();
	}
 
}



La classe si chiama ClockView. Ricordo, una volta per tutte, che è sempre preferibile dare ad una classe (ed in particolare ad una Custom View) un nome che ricordi il suo impiego, specie se si usano diverse view personalizzate. Sarebbe altrimenti scomodo dover poi ricordare di cosa si occupi un'ipotetica myCustomView023...

Ad ogni modo, all'interno di ClockView, per prima cosa vengono definiti dei field (float ore, minuti e secondi, Paint paint, Bitmap bg e resBg, int width ed height). Definendo le variabili e le etichette come field, o se preferite come variabili globali, è possibile usarle in tutta la classe senza incorrere in errori.

Una custom view ha naturalmente bisogno di un costruttore.

    PROGRAMMAZIONE ANDROID
public ClockView(Context context, AttributeSet attr) {
    super(context, attr);
    init();
}



Le view personalizzate ammettono due tipi di costruttori, uno che permette di passare degli attributi ed uno che invece non ne utilizza. Gli attributi che si possono passare sono quelli che permettono di scalare la view, o meglio, di passargli le dimensioni tramite un layout.xml.
Nel costruttore viene quindi invocata la funzione d'inizializzazione init().

    PROGRAMMAZIONE ANDROID
private void init() {
	paint = new Paint();
	paint.setAntiAlias(true);
	paint.setStrokeWidth(2);
	paint.setTextSize(25);
	paint.setStyle(Paint.Style.STROKE);
	paint.setColor(Color.RED);
 
	bg=BitmapFactory.decodeResource(getResources(), R.drawable.bgclock2);
	resBg=null;
}



Questa funzione non fa altro che inizializzare la superficie di disegno della custom view. Le ultime due linee, in particolare, si occupano di caricare un background per la view (nel mio caso specifico, un quadrante coi numeri romani).

Il grosso del lavoro viene svolto da onDraw(), che verrà poi chiamata autonomamente dal sistema ogni volta che viene disegnata od aggiornata la custom view. Per prima cosa, onDraw() verifica se il resource background è pronto per l'impiego. Se non lo è, allora lo ricava dal background caricato in init(), riscalandolo sulle dimensioni della view:

    PROGRAMMAZIONE ANDROID
if (resBg==null){
 
	int mWidth = getMeasuredWidth();
	int s=mWidth/bg.getWidth();
	width=bg.getWidth()*s;
	height=bg.getHeight()*s;
 
	resBg=Bitmap.createScaledBitmap(bg, width, height, true);
 
}



La parte seguente di onDraw() si occupa di disegnare la posizione delle lancette attraverso i valori che vengono passati attraverso il metodo update(). Quest'ultimo, è molto semplice:

    PROGRAMMAZIONE ANDROID
public void update(float ore, float minuti, float secondi) {
 
	this.ore  = ore;
	this.minuti = minuti;
	this.secondi = secondi;
 
	invalidate();
}



La sua funzione è quella di modificare i valori di ore, minuti e secondi utilizzati per disegnare la custom view. Al suo interno viene infine invocata la funzione invalidate(), che forza l'esecuzione di onDraw() per aggiornare la ClockView coi nuovi valori.

Per inserire la custom view nel vostro layout, non dovrete far altro che dichiararla in questo modo:
    PROGRAMMAZIONE ANDROID
<your.package.name.ClockView
        android:id="@+id/clockview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="10"/>



Per gestirla via codice, invece:

    PROGRAMMAZIONE ANDROID
public class Chronograph extends Activity {
ClockView clock;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	clock = (ClockView)findViewById(R.id.clockview);
	clock.update(7, 35, 45);
}



Un'implementazione di questa classe si trova nell'applicazione Cool Analog Timer di MeToo, che ringrazio per avermi passato il codice.


11-03-2013 01:07 PM
Trova tutti i messaggi di questo utente Cita questo messaggio nella tua risposta

Tags
MeToo Offline
Junior Member
**

Messaggi: 8
Registrato: Jun 2012
Reputazione: 0
Messaggio: #2
RE: Custom View: come realizzare un orologio analogico
(11-03-2013 01:07 PM)Bays Chef Ha scritto:  
Un'implementazione di questa classe si trova nell'applicazione Cool Analog Timer di MeToo, che ringrazio per avermi passato il codice.

Non c'è di che! Big Grin

MeToo - Android App
11-05-2013 11:09 AM
Visita il sito web di questo utente Trova tutti i messaggi di questo utente Cita questo messaggio nella tua risposta
Rispondi 


Vai al forum:


Utente(i) che stanno guardando questa discussione: 1 Ospite(i)

Contattaci | Android Bay | Torna all'inizio della pagina | Torna al contenuto | Mobile Version | RSS Syndication
Iscriviti subito a BannerPromotion.it