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
1 comment:
PLEASE PLEASE PLEASE !!
I 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
Post a Comment