Refer to my old exercise "Animation of moving bitmap along path", the bitmap and path are hard-coded inside custom view. It's a modified version; the thing to be drawn (bitmap/path) are held separated and referenced by custom view in a list, such that it is easy to insert more things.
Please notice:
- I don't thing it's a good approach to do this, I just show a interesting exercise.
- You should not do the calculation (such as move the bitmap) inside onDraw(), it's suggested to do it in another thread.
Create a new class AnimationThing.java. It hold the bitmap and path of individual thing.
package com.blogspot.android_er.androidmovingbitmapalongpath;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
public class AnimationThing {
Paint paint;
Path animPath;
PathMeasure pathMeasure;
float pathLength;
Bitmap bm;
int bm_offsetX, bm_offsetY;
float step;
float distance;
float[] pos;
float[] tan;
Matrix matrix;
public AnimationThing(Paint paint,
Path animPath,
Bitmap bm,
float step) {
this.paint = paint;
this.animPath = animPath;
pathMeasure = new PathMeasure(this.animPath, false);
pathLength = pathMeasure.getLength();
this.bm = bm;
bm_offsetX = bm.getWidth()/2;
bm_offsetY = bm.getHeight()/2;
this.step = step;
distance = 0;
pos = new float[2];
tan = new float[2];
matrix = new Matrix();
}
}
Create our custom view, AnimationView .java.
package com.blogspot.android_er.androidmovingbitmapalongpath;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
public class AnimationView extends View {
List<AnimationThing> animationThingsList;
public AnimationView(Context context) {
super(context);
initAnimationView();
}
public AnimationView(Context context, AttributeSet attrs) {
super(context, attrs);
initAnimationView();
}
public AnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAnimationView();
}
private void initAnimationView(){
animationThingsList = new ArrayList<>();
}
public void insertThing(AnimationThing thing){
animationThingsList.add(thing);
}
@Override
protected void onDraw(Canvas canvas) {
for (AnimationThing thing : animationThingsList){
//!!! Only the path of the last thing will be drawn on screen
canvas.drawPath(thing.animPath, thing.paint);
if(thing.distance < thing.pathLength){
thing.pathMeasure.getPosTan(thing.distance, thing.pos, thing.tan);
thing.matrix.reset();
float degrees = (float)(Math.atan2(thing.tan[1], thing.tan[0])*180.0/Math.PI);
thing.matrix.postRotate(degrees, thing.bm_offsetX, thing.bm_offsetY);
thing.matrix.postTranslate(thing.pos[0]-thing.bm_offsetX, thing.pos[1]-thing.bm_offsetY);
canvas.drawBitmap(thing.bm, thing.matrix, null);
thing.distance += thing.step;
}else{
thing.distance = 0;
}
}
invalidate();
}
}
Layout, activity_main.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:padding="16dp"
android:orientation="vertical"
tools:context="com.blogspot.android_er.androidmovingbitmapalongpath.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<com.blogspot.android_er.androidmovingbitmapalongpath.AnimationView
android:id="@+id/MyAnimationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F0F0F0"/>
</LinearLayout>
MainActivity.java
package com.blogspot.android_er.androidmovingbitmapalongpath;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
AnimationView myAnimationView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myAnimationView = (AnimationView)findViewById(R.id.MyAnimationView);
prepareThings();
}
private void prepareThings(){
Paint paint;
Path animPath;
float step;
Bitmap bm;
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(1);
paint.setStyle(Paint.Style.STROKE);
bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
animPath = new Path();
animPath.moveTo(100, 100);
animPath.lineTo(200, 100);
animPath.lineTo(300, 50);
animPath.lineTo(400, 150);
animPath.lineTo(100, 300);
animPath.lineTo(600, 300);
animPath.lineTo(100, 100);
animPath.close();
step = 1;
AnimationThing thing = new AnimationThing(paint, animPath, bm, step);
myAnimationView.insertThing(thing);
//The second thing
bm = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_add);
animPath.reset();
animPath.addCircle(400, 400, 300, Path.Direction.CW);
step = 3;
thing = new AnimationThing(paint, animPath, bm, step);
myAnimationView.insertThing(thing);
}
}
Download the files .
Next:
- Custom view to draw bitmap along path, calculate in background thread
PLEASE PLEASE PLEASE !!
ReplyDeleteI am new to Android Studio and struggling along on AS 3.6.3
Do you have an update of this Project that will work in AS 3.6.3 ?
I am trying to build something and I need to know how to move a bitmap along a set path as you have done. I have spent the past 2 weeks searching the net but found nothing until now.
PLEASE !
Regards
Paul