Ce tuto vous montre comment animer une bille à l'écran en tenant compte des informations retournées par vos accéléromètres. Il vous suffira de pencher votre périphérique Android dans différentes directions pour déplacer la bille. La seconde partie de ce tuto vous montre comment déplacer la bille grâce à la dalle tactile : appuyez sur la bille avec votre doigt pouis déplacez le pour repositionner la bille.
Voici la vidéo expliquant les différents codes présentés. Vous retrouverez ces codes à la suite de la vidéo.
Notez que l'exemple ci-dessous présuppose qu'une image nommée blueball.png
a été placée dans le répertoire drawable-mdpi
.
Si vous souhaitez gérer différentes densités d'écran, il est aussi possible d'utiliser les autre répertoires "drawable
" (ldpi, hdpi, xhdpi, xxhpdi et xxxhdpi).
Si vous manquez d'inspiration pour l'image de la bille, vous pouvez faire une recherche sur un moteur de recherche. Vous y trouverez
certainement votre bonheur.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
package com.infinisoftware.megaball; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.util.AttributeSet; import android.view.View; public class BallView extends View implements SensorEventListener { private Paint paint = new Paint(); private Bitmap ballBitmap; private int imageWidth; private int imageHeight; private int currentX; private int currentY; public BallView( Context context ) { super( context ); this.init( context ); } public BallView( Context context, AttributeSet attrSet ) { super( context, attrSet ); this.init( context ); } private void init( Context context ) { this.ballBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blueball ); this.imageWidth = ballBitmap.getWidth(); this.imageHeight = ballBitmap.getHeight(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); this.currentX = (getWidth() - this.imageWidth) / 2; this.currentY = (getHeight() - this.imageHeight) / 2; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap( this.ballBitmap, this.currentX, this.currentY, this.paint ); } private void moveImage( float x, float y ) { this.currentX += (int) x; this.currentY += (int) y; if ( this.currentX < 0 ) { this.currentX = 0; } else if ( this.currentX + this.imageWidth > this.getWidth() ){ this.currentX = this.getWidth() - this.imageWidth; } if ( this.currentY < 0 ) { this.currentY = 0; } else if ( this.currentY + this.imageHeight > this.getHeight() ){ this.currentY = this.getHeight() - this.imageHeight; } this.invalidate(); } @Override public void onAccuracyChanged(Sensor arg0, int arg1) { } @Override public void onSensorChanged(SensorEvent event) { float x = event.values[0]; float y = event.values[1]; //float z = event.values[2]; this.moveImage( -x*5, y*5 ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
package com.infinisoftware.megaball; import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorManager; import android.os.Bundle; public class MainActivity extends Activity { private BallView ballView; private SensorManager sensorManager = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ballView = new BallView( this ); setContentView( ballView ); sensorManager = (SensorManager) getSystemService( SENSOR_SERVICE ); /* --- For verify if accelerometers are present into the device --- List<Sensor> sensors = sensorManager.getSensorList( Sensor.TYPE_ALL ); for( Sensor sensor : sensors ) { Log.i( "DEBUG", sensor.getName() + " --- " + sensor.getVendor() ); } */ } @Override protected void onResume() { super.onResume(); sensorManager.registerListener( ballView, sensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER ), sensorManager.SENSOR_DELAY_GAME ); } @Override protected void onPause() { super.onPause(); sensorManager.unregisterListener( ballView ); } } |
Les méthodes onResume
et onPause
permettent d'enregistrer notre widget ballView
au niveau du
SensorManager
si l'activité est en cours d'affichage et de désabonner le widget quand l'activité passe en arrière plan.
Cela permet d'économiser la batterie quand l'application n'est pas visible (moins d'appels de méthodes).
Jouez à pivoter votre périphérique afin de faire déclencher les accéléromètres et déplacer la bille sur l'écran.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
package com.infinisoftware.megaball; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Vibrator; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; public class BallViewWithGesture extends View implements SensorEventListener, GestureDetector.OnGestureListener { private Paint paint = new Paint(); private Bitmap ballBitmap; private Vibrator vibrator; private GestureDetector gestureDetector; private int imageWidth; private int imageHeight; private int currentX; private int currentY; public BallViewWithGesture( Context context ) { super( context ); this.init( context ); } public BallViewWithGesture( Context context, AttributeSet attrSet ) { super( context, attrSet ); this.init( context ); } private void init( Context context ) { this.vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); this.gestureDetector = new GestureDetector( context, this ); this.ballBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blueball ); this.imageWidth = ballBitmap.getWidth(); this.imageHeight = ballBitmap.getHeight(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); this.currentX = (getWidth() - this.imageWidth) / 2; this.currentY = (getHeight() - this.imageHeight) / 2; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap( this.ballBitmap, this.currentX, this.currentY, this.paint ); } private void moveImage( float x, float y ) { this.currentX += (int) x; this.currentY += (int) y; if ( this.currentX < 0 ) { this.currentX = 0; } else if ( this.currentX + this.imageWidth > this.getWidth() ){ this.currentX = this.getWidth() - this.imageWidth; } if ( this.currentY < 0 ) { this.currentY = 0; } else if ( this.currentY + this.imageHeight > this.getHeight() ){ this.currentY = this.getHeight() - this.imageHeight; } this.invalidate(); } @Override public void onAccuracyChanged(Sensor arg0, int arg1) { } @Override public void onSensorChanged(SensorEvent event) { float x = event.values[0]; float y = event.values[1]; //float z = event.values[2]; this.moveImage( -x*5, y*5 ); } @Override public boolean onTouchEvent(MotionEvent event) { return this.gestureDetector.onTouchEvent(event); } @Override public boolean onDown(MotionEvent event) { this.vibrator.vibrate( 20 ); // Time in ms return true; } @Override public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) { // TODO Auto-generated method stub return false; } @Override public void onLongPress(MotionEvent arg0) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent srcEvent, MotionEvent destEvent, float x, float y) { this.moveImage(-x, -y); return true; } @Override public void onShowPress(MotionEvent arg0) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent arg0) { // TODO Auto-generated method stub return false; } } |
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :