Creating a View Class with ball moving animation
1. Add a Sound file bounce_sound.mp3.
2. Add a new java class file BouncingBallView.java. Put following codes in it.
package com.my.animation;
import android.view.View;
import android.content.Context;
import android.media.SoundPool;
import android.media.AudioAttributes;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Color;
import android.graphics.Canvas;
public class BouncingBallView extends View {
private Paint mypaint;
private SoundPool soundPool;
private int soundId;
private boolean isLoaded = false;
int directionX = 1; // 1 = moving right, -1 = moving left
int directionY = 1; // 1 = moving down, -1 = moving up
int speed = 4;
int radius = 30;
int distanceX = radius;
int distanceY = radius;
int timeX = 0;
int timeY = 0;
int viewWidth = 0;
int viewHeight = 0;
public BouncingBallView(Context context) {
super(context);
init(context);
}
// Optional constructor with AttributeSet (for XML attributes)
public BouncingBallView(Context context, android.util.AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context){
mypaint = new Paint();
mypaint.setStyle(Style.FILL);
mypaint.setColor(Color.RED);
initializeSoundPool(context);
}
@Override
protected void onDraw(Canvas canvas){
viewWidth = this.getMeasuredWidth();
viewHeight = this.getMeasuredHeight();
canvas.drawCircle(distanceX, distanceY, radius, mypaint);
calculateNewPosition();
invalidate();
}
private void initializeSoundPool(Context context) {
// Create AudioAttributes for SoundPool
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME) // Use case
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) // Type of content
.build();
// Create SoundPool with max streams
soundPool = new SoundPool.Builder()
.setMaxStreams(1) // Maximum number of simultaneous streams
.setAudioAttributes(audioAttributes)
.build();
// Load sound file
soundId = soundPool.load(context, R.raw.bounce_sound, 1);
// Set listener for when sound is loaded
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
if (status == 0) {
isLoaded = true;
}
}
});
}
private void playSound() {
if (isLoaded) {
// Parameters: soundId, leftVolume, rightVolume, priority, loop, rate
soundPool.play(soundId, 1.0f, 1.0f, 1, 0, 1.0f);
}
}
private void calculateNewPosition(){
if (distanceX > (viewWidth - radius)){
timeX = 0; directionX = -1;
playSound();
} else if (distanceX < radius){
timeX = 0; directionX = 1;
playSound();
}
timeX++;
if (directionX == -1){
distanceX = viewWidth - radius - speed*timeX;
} else {
distanceX = radius + speed*timeX;
}
if (distanceY > (viewHeight - radius)){
timeY = 0; directionY = -1;
playSound();
} else if (distanceY < radius){
timeY = 0; directionY = 1;
playSound();
}
timeY++;
if (directionY == -1){
distanceY = viewHeight - radius - speed*timeY;
} else {
distanceY = radius + speed*timeY;
}
}
public void setBallPosition(int x, int y) {
this.distanceX = Math.max(radius, Math.min(x, viewWidth - radius));
this.distanceY = Math.max(radius, Math.min(y, viewHeight - radius));
// Reset timers
this.timeX = 0;
this.timeY = 0;
// Redraw
invalidate();
}
public void setBallSpeed(int speed) {
if (speed > 0) {
this.speed = speed;
// Reset timers
if (directionX == -1){
this.timeX= (viewWidth - radius - distanceX)/speed;
} else {
this.timeX = (distanceX - radius)/speed;
}
if (directionY == -1){
this.timeY= (viewHeight - radius - distanceY)/speed;
} else {
this.timeY = (distanceY - radius)/speed;
}
}
}
// Set the radius of the ball
public void setBallRadius(int radius) {
if (radius > 0) {
this.radius = radius;
// Adjust current position to stay within bounds
if (viewWidth > 0 && viewHeight > 0) {
distanceX = Math.max(radius, Math.min(distanceX, viewWidth - radius));
distanceY = Math.max(radius, Math.min(distanceY, viewHeight - radius));
}
invalidate(); // Redraw with new radius
}
}
// Set ball color
public void setBallColor(int color) {
mypaint.setColor(color);
invalidate();
}
// Reset ball to its initial settings
public void resetBall() {
this.speed = 4;
this.radius = 30;
mypaint.setColor(Color.RED);
this.distanceX = radius;
this.distanceY = radius;
this.directionX = 1;
this.directionY = 1;
this.timeX = 0;
this.timeY = 0;
invalidate();
}
// Clean up SoundPool when view is destroyed
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (soundPool != null) {
soundPool.release();
soundPool = null;
}
}
}
3. Add a Linear Layout. Set id to boxView, padding to 0, set some background color, set height to 300. Convert this to {package name}.BouncingBallView.
4. Add three spinners spinner_speed, spinner_color, and spinner_radius. Add a Button resetBtn.
5. Add a number variable n and three String List speeds, colors, and radii.
6. In onCreate, add values to the lists and display them in the spinners. See image below.
7. In spinner_speed onItemSelected event, use following codes.
binding.boxView.setBallSpeed(Integer.valueOf(speeds.get(_position)));
8. In spinner_color onItemSelected event, use following codes.
int[] ball_colors = new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.BLACK, Color.WHITE};
binding.boxView.setBallColor(ball_colors[_position]);
9. In spinner_radius onItemSelected event, use following codes.
binding.boxView.setBallRadius(Integer.valueOf(radii.get(_position)));
10. In resetBtn onClick event, use following codes.
binding.boxView.resetBall();
Check video below



Comments
Post a Comment