السبت، 7 يونيو 2014

Animation follow touch path forward and backward

Further modify the example of "Change speed of Animation follow touch path" to add feature of animation direction, forward and backward.


AnimationView.java
package com.example.androidanimationalongpath;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class AnimationView extends View {

Paint paint;

Bitmap bm;
int bm_offsetX, bm_offsetY;

Path animPath;
PathMeasure pathMeasure;
float pathLength;

float step; //distance each step
float distance; //distance moved
float curX, curY;

float curAngle; //current angle
float targetAngle; //target angle
float stepAngle; //angle each step

float[] pos;
float[] tan;

Matrix matrix;

Path touchPath;

static int FORWARD = 1;
static int BACKWARD = -1;
int direction;

public AnimationView(Context context) {
super(context);
initMyView();
}

public AnimationView(Context context, AttributeSet attrs) {
super(context, attrs);
initMyView();
}

public AnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initMyView();
}

public void initMyView(){
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(1);
paint.setStyle(Paint.Style.STROKE);

bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
bm_offsetX = bm.getWidth()/2;
bm_offsetY = bm.getHeight()/2;

animPath = new Path();

pos = new float[2];
tan = new float[2];

matrix = new Matrix();

touchPath = new Path();

step = 1; //default
stepAngle = 1; //default

direction = FORWARD; //default
}

@Override
protected void onDraw(Canvas canvas) {
if(animPath.isEmpty()){
return;
}

canvas.drawPath(animPath, paint);

matrix.reset();

if((targetAngle-curAngle)>stepAngle){
curAngle += stepAngle;
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);

invalidate();
}else if((curAngle-targetAngle)>stepAngle){
curAngle -= stepAngle;
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);

invalidate();
}else{
curAngle=targetAngle;

if((direction==FORWARD && distance < pathLength)
||(direction==BACKWARD && distance > 0)){

pathMeasure.getPosTan(distance, pos, tan);

targetAngle = (float)(Math.atan2(tan[1], tan[0])*180.0/Math.PI);
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);

curX = pos[0]-bm_offsetX;
curY = pos[1]-bm_offsetY;
matrix.postTranslate(curX, curY);

canvas.drawBitmap(bm, matrix, null);

distance += step * direction;

invalidate();
}else{
matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
matrix.postTranslate(curX, curY);
canvas.drawBitmap(bm, matrix, null);
}
}

}

@Override
public boolean onTouchEvent(MotionEvent event) {

int action = event.getAction();

switch(action){
case MotionEvent.ACTION_DOWN:
touchPath.reset();
touchPath.moveTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
touchPath.lineTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_UP:
touchPath.lineTo(event.getX(), event.getY());
animPath = new Path(touchPath);

pathMeasure = new PathMeasure(animPath, false);
pathLength = pathMeasure.getLength();

//step = 1;
distance = 0;
curX = 0;
curY = 0;

//stepAngle = 1;
curAngle = 0;
targetAngle = 0;

direction = FORWARD;

invalidate();

break;

}

return true;
}

public void setSpeed(int sp){
step = sp;
stepAngle = sp;
}

public void replayForward(){
direction = FORWARD;
invalidate();
}

public void replayBackward(){
direction = BACKWARD;
invalidate();
}

}

/res/layout/activity_main.xml
<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:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.androidanimationalongpath.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" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<Button
android:id="@+id/replayfor"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="Replay/Forward" />
<Button
android:id="@+id/replayback"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="Replay/Backward" />

</LinearLayout>

<SeekBar
android:id="@+id/speedbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:progress="1"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >

<com.example.androidanimationalongpath.AnimationView
android:id="@+id/animationview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@android:color/darker_gray" />

</LinearLayout>

</LinearLayout>

MainActivity.java
package com.example.androidanimationalongpath;

import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.os.Bundle;

public class MainActivity extends ActionBarActivity {

AnimationView animationView;
SeekBar speedBar;
Button btnForward, btnbackward;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

animationView = (AnimationView)findViewById(R.id.animationview);
speedBar = (SeekBar)findViewById(R.id.speedbar);
speedBar.setOnSeekBarChangeListener(speedBarOnSeekBarChangeListener);
animationView.setSpeed(speedBar.getProgress()); //set default speed

btnForward = (Button)findViewById(R.id.replayfor);
btnForward.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
animationView.replayForward();
}});

btnbackward = (Button)findViewById(R.id.replayback);
btnbackward.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
animationView.replayBackward();
}});
}

OnSeekBarChangeListener speedBarOnSeekBarChangeListener =
new OnSeekBarChangeListener(){

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
//offset from SeekBar 0~19 to step 1~10
animationView.setSpeed(progress);
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
};

}


download filesDownload the files.

More example of Drawing Path on canvas of custom View.


ليست هناك تعليقات:

إرسال تعليق