svg是目前十分流行的图像文件格式了,svg严格来说应该是一种开放标准的矢量图形语言,使用svg格式我们可以直接用代码来描绘图像,可以用任何文字处理工具打开svg图像,通过改变部分代码来使图像具有交互功能,并可以随时插入到HTML中通过浏览器(如火狐浏览器)来观看。使用svg格式可让你设计激动人心的、高分辨率的Web图形页面。
svg格式具备目前网络流行的jpg和png等格式无法具备的优势:可以任意放大图形显示,但绝不会以牺牲图像质量为代价;可在svg图像中保留可编辑和可搜寻的状态;平均来讲,svg文件比其它格式的图像文件要小很多,因而下载也很快。
我们先来看几张Android上使用SVG的效果图:
从上面的图片看到,如果我们自己来实现这样的特效,非常的麻烦,不过接下来给大家介绍一个开源控件,就可以配合SVG实现这些效果。
首先我们来了解SVG文件的格式,举个例子:
- <svg xmlns="http://www.w3.org/2000/svg" id="svg" class="svg" viewBox="0 0 960 480" preserveAspectRatio="xMinYMin meet">
- <path fill="#B4BEC8" stroke="#B4BEC8" stroke-width="2px" stroke-miterlimit="10" d="M570.14 440.2l-29.165-28.99c-7.103-8.5-6.152-36.718-6.02-40.665H425.048c.133 3.947 1.082 32.164-6.018 40.666l-29.166 28.99c-1.237 1.404-1.712 2.505-1.623 3.37h-.054c.76 7.727 6.664 6.332 13.607 6.332H558.01c6.696 0 12.412 1.27 13.493-5.56.58-.953.274-2.282-1.364-4.14z" style="fill-opacity: 1; stroke-opacity: 0; -webkit-transition: fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out; transition: fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out; stroke-dasharray: 474.095184326172px, 474.095184326172px; stroke-dashoffset: 0px;"></path>
- <path fill="#C8D2DC" stroke="#C8D2DC" stroke-width="2px" stroke-miterlimit="10" d="M727.488 355.125c0 8.514-6.597 15.42-14.738 15.42h-465.5c-8.14 0-14.74-6.906-14.74-15.42V45.42c0-8.517 6.6-15.42 14.74-15.42h465.5c8.142 0 14.738 6.903 14.738 15.42v309.705z" style="fill-opacity: 1; stroke-opacity: 0; -webkit-transition: fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out; transition: fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out; stroke-dasharray: 1645.18310546875px, 1645.18310546875px; stroke-dashoffset: 0px;"></path>
- <path fill="#fff" stroke="#C8D2DC" stroke-width="2px" stroke-miterlimit="10" d="M489.01 343.713c-.042-4.223 3.447-6.254 3.605-6.352-1.963-2.866-5.018-3.263-6.102-3.31-2.602-.26-5.074 1.53-6.39 1.53s-3.356-1.49-5.506-1.448c-2.836.04-5.445 1.645-6.907 4.182-2.942 5.11-.75 12.672 2.116 16.814 1.4 2.02 3.072 4.305 5.268 4.22 2.114-.08 2.913-1.362 5.467-1.362 2.556 0 3.274 1.363 5.51 1.322 2.273-.04 3.716-2.064 5.105-4.098 1.61-2.35 2.273-4.63 2.313-4.748-.05-.02-4.434-1.7-4.48-6.75M484.807 331.31c1.168-1.41 1.953-3.37 1.738-5.327-1.68.068-3.713 1.12-4.916 2.53-1.08 1.247-2.027 3.245-1.77 5.16 1.87.143 3.784-.95 4.947-2.362" style="fill-opacity: 1; stroke-opacity: 0; -webkit-transition: fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out; transition: fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out; stroke-dasharray: 115.244583129883px, 115.244583129883px; stroke-dashoffset: 0px;"></path>
- <path fill="#3C4650" stroke="#3C4650" stroke-width="2px" stroke-miterlimit="10" d="M727.488 315.527V45.982c0-8.828-6.597-15.982-14.738-15.982h-465.5c-8.14 0-14.74 7.155-14.74 15.982v269.545H727.49z" style="fill-opacity: 1; stroke-opacity: 0; -webkit-transition: fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out; transition: fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out; stroke-dasharray: 1547.85571289063px, 1547.85571289063px; stroke-dashoffset: 0px;"></path>
- <path fill="#141E28" stroke="#141E28" stroke-width="2px" stroke-miterlimit="10" d="M251.2 48.887h457.205v245.52H251.2z" style="fill-opacity: 1; stroke-opacity: 0; -webkit-transition: fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out; transition: fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out; stroke-dasharray: 1405.44995117188px, 1405.44995117188px; stroke-dashoffset: 0px;"></path>
- </svg>
上面的代码很复杂,如果说它们是代码的话,但是我们可以注意到,这种书写方式,有点类似于html,都是使用标签
使用最多的标签是path,也就是路径
有的人也会想到,要实现照片上的动态效果,我们可以使用Android自带的绘图类和函数,复杂的曲线路径,我们可以使用path这个类来制定
那会不会SVG里面的path,其实也是这样,那么我们就可以将SVG中的path,对应到android,然后绘制出来就好了。
SVG里面还有各种标签:
包括line直线,circle圆,rect矩形,eliipse椭圆,polygon多边形,等等
这些只要我们又一个SVG文件,都可以将其转换成java代码
作为一个程序员,我们当然不能手动去做这个工作,那就涉及两个问题,一个是SVG的解析,一个是解析后的绘制
幸运的是,已经有人完成了这个工作,并且在Github上开源 https://github.com/geftimov/android-pathview
这篇文章将作为一个简单的例子,来使用上面的开源控件
为了解析SVG,我们需要将一个androidsvg.jar包含进我们的lib
下面我们来看这个控件的简单使用,作为一个自定义控件,我们只需要在布局文件里面添加
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:background="#ff0000"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <com.example.kaiyicky.myapplication.PathView
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/pathView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:pathColor="@android:color/white"
- app:svg="@raw/ironman_white"
- app:pathWidth="5"/>
- </LinearLayout>
其实app:svg指定了一个SVG文件,我们可以把这个文章放在raw目录下面
然后来看Activity里面:
- public class MainActivity extends FragmentActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- final PathView pathView = (PathView) findViewById(R.id.pathView);
- // final Path path = makeConvexArrow(50, 100);
- // pathView.setPath(path);
- pathView.setFillAfter(true);
- pathView.useNaturalColors();
- pathView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- pathView.getPathAnimator().
- delay(100).
- duration(1500).
- interpolator(new AccelerateDecelerateInterpolator()).
- start();
- }
- });
- }
- private Path makeConvexArrow(float length, float height) {
- final Path path = new Path();
- path.moveTo(0.0f, 0.0f);
- path.lineTo(length / 4f, 0.0f);
- path.lineTo(length, height / 2.0f);
- path.lineTo(length / 4f, height);
- path.lineTo(0.0f, height);
- path.lineTo(length * 3f / 4f, height / 2f);
- path.lineTo(0.0f, 0.0f);
- path.close();
- return path;
- }
- }
看到注释的部分,调用了makeConvexArraw()方法,如果我们没有在xml文件里面指定svg文件,我们也可以在代码中手动指定绘制的路径
让代码跑起来,点击屏幕,于是就实现了以下效果:
就是这么简单,至于这么制作SVG文件,大家可以找美工帮忙,使用ps和ai,可以将图片转换成SVG
最后是源码下载地址:http://download.csdn.net/detail/kangaroo835127729/9016349
整个过程有两个类,一个是SVG解析工具类:
- /**
- * Util class to init and get paths from svg.
- */
- public class SvgUtils {
- /**
- * It is for logging purposes.
- */
- private static final String LOG_TAG = "SVGUtils";
- /**
- * All the paths with their attributes from the svg.
- */
- private final List<SvgPath> mPaths = new ArrayList<SvgPath>();
- /**
- * The paint provided from the view.
- */
- private final Paint mSourcePaint;
- /**
- * The init svg.
- */
- private SVG mSvg;
- /**
- * Init the SVGUtils with a paint for coloring.
- *
- * @param sourcePaint - the paint for the coloring.
- */
- public SvgUtils(final Paint sourcePaint) {
- mSourcePaint = sourcePaint;
- }
- /**
- * Loading the svg from the resources.
- *
- * @param context Context object to get the resources.
- * @param svgResource int resource id of the svg.
- */
- public void load(Context context, int svgResource) {
- if (mSvg != null) return;
- try {
- mSvg = SVG.getFromResource(context, svgResource);
- mSvg.setDocumentPreserveAspectRatio(PreserveAspectRatio.UNSCALED);
- } catch (SVGParseException e) {
- Log.e(LOG_TAG, "Could not load specified SVG resource", e);
- }
- }
- /**
- * Draw the svg to the canvas.
- *
- * @param canvas The canvas to be drawn.
- * @param width The width of the canvas.
- * @param height The height of the canvas.
- */
- public void drawSvgAfter(final Canvas canvas, final int width, final int height) {
- final float strokeWidth = mSourcePaint.getStrokeWidth();
- rescaleCanvas(width, height, strokeWidth, canvas);
- }
- /**
- * Render the svg to canvas and catch all the paths while rendering.
- *
- * @param width - the width to scale down the view to,
- * @param height - the height to scale down the view to,
- * @return All the paths from the svg.
- */
- public List<SvgPath> getPathsForViewport(final int width, final int height) {
- final float strokeWidth = mSourcePaint.getStrokeWidth();
- Canvas canvas = new Canvas() {
- private final Matrix mMatrix = new Matrix();
- @Override
- public int getWidth() {
- return width;
- }
- @Override
- public int getHeight() {
- return height;
- }
- @Override
- public void drawPath(Path path, Paint paint) {
- Path dst = new Path();
- //noinspection deprecation
- getMatrix(mMatrix);
- path.transform(mMatrix, dst);
- paint.setAntiAlias(true);
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(strokeWidth);
- mPaths.add(new SvgPath(dst, paint));
- }
- };
- rescaleCanvas(width, height, strokeWidth, canvas);
- return mPaths;
- }
- /**
- * Rescale the canvas with specific width and height.
- *
- * @param width The width of the canvas.
- * @param height The height of the canvas.
- * @param strokeWidth Width of the path to add to scaling.
- * @param canvas The canvas to be drawn.
- */
- private void rescaleCanvas(int width, int height, float strokeWidth, Canvas canvas) {
- final RectF viewBox = mSvg.getDocumentViewBox();
- final float scale = Math.min(width
- / (viewBox.width() + strokeWidth),
- height / (viewBox.height() + strokeWidth));
- canvas.translate((width - viewBox.width() * scale) / 2.0f,
- (height - viewBox.height() * scale) / 2.0f);
- canvas.scale(scale, scale);
- mSvg.renderToCanvas(canvas);
- }
- /**
- * Path with bounds for scalling , length and paint.
- */
- public static class SvgPath {
- /**
- * Region of the path.
- */
- private static final Region REGION = new Region();
- /**
- * This is done for clipping the bounds of the path.
- */
- private static final Region MAX_CLIP =
- new Region(Integer.MIN_VALUE, Integer.MIN_VALUE,
- Integer.MAX_VALUE, Integer.MAX_VALUE);
- /**
- * The path itself.
- */
- final Path path;
- /**
- * The paint to be drawn later.
- */
- final Paint paint;
- /**
- * The length of the path.
- */
- final float length;
- /**
- * The bounds of the path.
- */
- final Rect bounds;
- /**
- * The measure of the path, we can use it later to get segment of it.
- */
- final PathMeasure measure;
- /**
- * Constructor to add the path and the paint.
- *
- * @param path The path that comes from the rendered svg.
- * @param paint The result paint.
- */
- SvgPath(Path path, Paint paint) {
- this.path = path;
- this.paint = paint;
- measure = new PathMeasure(path, false);
- this.length = measure.getLength();
- REGION.setPath(path, MAX_CLIP);
- bounds = REGION.getBounds();
- }
- }
- }
一个是SVG控件类:
- /**
- * PathView is an View that animate paths.
- */
- public class PathView extends View {
- /**
- * Logging tag.
- */
- public static final String LOG_TAG = "PathView";
- /**
- * The paint for the path.
- */
- private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- /**
- * Utils to catch the paths from the svg.
- */
- private final SvgUtils svgUtils = new SvgUtils(paint);
- /**
- * All the paths provided to the view. Both from Path and Svg.
- */
- private List<SvgUtils.SvgPath> paths = new ArrayList<SvgUtils.SvgPath>(0);
- /**
- * This is a lock before the view is redrawn
- * or resided it must be synchronized with this object.
- */
- private final Object mSvgLock = new Object();
- /**
- * Thread for working with the object above.
- */
- private Thread mLoader;
- /**
- * The svg image from the raw directory.
- */
- private int svgResourceId;
- /**
- * Object that build the animation for the path.
- */
- private AnimatorBuilder animatorBuilder;
- /**
- * The progress of the drawing.
- */
- private float progress = 0f;
- /**
- * If the used colors are from the svg or from the set color.
- */
- private boolean naturalColors;
- /**
- * If the view is filled with its natural colors after path drawing.
- */
- private boolean fillAfter;
- /**
- * The width of the view.
- */
- private int width;
- /**
- * The height of the view.
- */
- private int height;
- /**
- * Default constructor.
- *
- * @param context The Context of the application.
- */
- public PathView(Context context) {
- this(context, null);
- }
- /**
- * Default constructor.
- *
- * @param context The Context of the application.
- * @param attrs attributes provided from the resources.
- */
- public PathView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
- /**
- * Default constructor.
- *
- * @param context The Context of the application.
- * @param attrs attributes provided from the resources.
- * @param defStyle Default style.
- */
- public PathView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- paint.setStyle(Paint.Style.STROKE);
- getFromAttributes(context, attrs);
- }
- /**
- * Get all the fields from the attributes .
- *
- * @param context The Context of the application.
- * @param attrs attributes provided from the resources.
- */
- private void getFromAttributes(Context context, AttributeSet attrs) {
- final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PathView);
- try {
- if (a != null) {
- paint.setColor(a.getColor(R.styleable.PathView_pathColor, 0xff00ff00));
- paint.setStrokeWidth(a.getFloat(R.styleable.PathView_pathWidth, 8.0f));
- svgResourceId = a.getResourceId(R.styleable.PathView_svg, 0);
- }
- } finally {
- if (a != null) {
- a.recycle();
- }
- }
- }
- /**
- * Set paths to be drawn and animated.
- *
- * @param paths - Paths that can be drawn.
- */
- public void setPaths(final List<Path> paths) {
- for (Path path : paths) {
- this.paths.add(new SvgUtils.SvgPath(path, paint));
- }
- synchronized (mSvgLock) {
- updatePathsPhaseLocked();
- }
- }
- /**
- * Set path to be drawn and animated.
- *
- * @param path - Paths that can be drawn.
- */
- public void setPath(final Path path) {
- paths.add(new SvgUtils.SvgPath(path, paint));
- synchronized (mSvgLock) {
- updatePathsPhaseLocked();
- }
- }
- /**
- * Animate this property. It is the percentage of the path that is drawn.
- * It must be [0,1].
- *
- * @param percentage float the percentage of the path.
- */
- public void setPercentage(float percentage) {
- if (percentage < 0.0f || percentage > 1.0f) {
- throw new IllegalArgumentException("setPercentage not between 0.0f and 1.0f");
- }
- progress = percentage;
- synchronized (mSvgLock) {
- updatePathsPhaseLocked();
- }
- invalidate();
- }
- /**
- * This refreshes the paths before draw and resize.
- */
- private void updatePathsPhaseLocked() {
- final int count = paths.size();
- for (int i = 0; i < count; i++) {
- SvgUtils.SvgPath svgPath = paths.get(i);
- svgPath.path.reset();
- svgPath.measure.getSegment(0.0f, svgPath.length * progress, svgPath.path, true);
- // Required only for Android 4.4 and earlier
- svgPath.path.rLineTo(0.0f, 0.0f);
- }
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- synchronized (mSvgLock) {
- canvas.save();
- canvas.translate(getPaddingLeft(), getPaddingTop());
- final int count = paths.size();
- for (int i = 0; i < count; i++) {
- final SvgUtils.SvgPath svgPath = paths.get(i);
- final Path path = svgPath.path;
- final Paint paint1 = naturalColors ? svgPath.paint : paint;
- canvas.drawPath(path, paint1);
- }
- fillAfter(canvas);
- canvas.restore();
- }
- }
- /**
- * If there is svg , the user called setFillAfter(true) and the progress is finished.
- *
- * @param canvas Draw to this canvas.
- */
- private void fillAfter(final Canvas canvas) {
- if (svgResourceId != 0 && fillAfter && progress == 1f) {
- svgUtils.drawSvgAfter(canvas, width, height);
- }
- }
- @Override
- protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- if (mLoader != null) {
- try {
- mLoader.join();
- } catch (InterruptedException e) {
- Log.e(LOG_TAG, "Unexpected error", e);
- }
- }
- if (svgResourceId != 0) {
- mLoader = new Thread(new Runnable() {
- @Override
- public void run() {
- svgUtils.load(getContext(), svgResourceId);
- synchronized (mSvgLock) {
- width = w - getPaddingLeft() - getPaddingRight();
- height = h - getPaddingTop() - getPaddingBottom();
- paths = svgUtils.getPathsForViewport(width, height);
- updatePathsPhaseLocked();
- }
- }
- }, "SVG Loader");
- mLoader.start();
- }
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (svgResourceId != 0) {
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- setMeasuredDimension(widthSize, heightSize);
- return;
- }
- int desiredWidth = 0;
- int desiredHeight = 0;
- final float strokeWidth = paint.getStrokeWidth() / 2;
- for (SvgUtils.SvgPath path : paths) {
- desiredWidth += path.bounds.left + path.bounds.width() + strokeWidth;
- desiredHeight += path.bounds.top + path.bounds.height() + strokeWidth;
- }
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(widthMeasureSpec);
- int measuredWidth, measuredHeight;
- if (widthMode == MeasureSpec.AT_MOST) {
- measuredWidth = desiredWidth;
- } else {
- measuredWidth = widthSize;
- }
- if (heightMode == MeasureSpec.AT_MOST) {
- measuredHeight = desiredHeight;
- } else {
- measuredHeight = heightSize;
- }
- setMeasuredDimension(measuredWidth, measuredHeight);
- }
- /**
- * If the real svg need to be drawn after the path animation.
- *
- * @param fillAfter - boolean if the view needs to be filled after path animation.
- */
- public void setFillAfter(final boolean fillAfter) {
- this.fillAfter = fillAfter;
- }
- /**
- * If you want to use the colors from the svg.
- */
- public void useNaturalColors() {
- naturalColors = true;
- }
- /**
- * Animator for the paths of the view.
- *
- * @return The AnimatorBuilder to build the animation.
- */
- public AnimatorBuilder getPathAnimator() {
- if (animatorBuilder == null) {
- animatorBuilder = new AnimatorBuilder(this);
- }
- return animatorBuilder;
- }
- /**
- * Get the path color.
- *
- * @return The color of the paint.
- */
- public int getPathColor() {
- return paint.getColor();
- }
- /**
- * Set the path color.
- *
- * @param color -The color to set to the paint.
- */
- public void setPathColor(final int color) {
- paint.setColor(color);
- }
- /**
- * Get the path width.
- *
- * @return The width of the paint.
- */
- public float getPathWidth() {
- return paint.getStrokeWidth();
- }
- /**
- * Set the path width.
- *
- * @param width - The width of the path.
- */
- public void setPathWidth(final float width) {
- paint.setStrokeWidth(width);
- }
- /**
- * Get the svg resource id.
- *
- * @return The svg raw resource id.
- */
- public int getSvgResource() {
- return svgResourceId;
- }
- /**
- * Set the svg resource id.
- *
- * @param svgResource - The resource id of the raw svg.
- */
- public void setSvgResource(int svgResource) {
- svgResourceId = svgResource;
- }
- /**
- * Object for building the animation of the path of this view.
- */
- public static class AnimatorBuilder {
- /**
- * Duration of the animation.
- */
- private int duration = 350;
- /**
- * Interpolator for the time of the animation.
- */
- private Interpolator interpolator;
- /**
- * The delay before the animation.
- */
- private int delay = 0;
- /**
- * ObjectAnimator that constructs the animation.
- */
- private final ObjectAnimator anim;
- /**
- * Listener called before the animation.
- */
- private ListenerStart listenerStart;
- /**
- * Listener after the animation.
- */
- private ListenerEnd animationEnd;
- /**
- * Animation listener.
- */
- private PathViewAnimatorListener pathViewAnimatorListener;
- /**
- * Default constructor.
- *
- * @param pathView The view that must be animated.
- */
- public AnimatorBuilder(final PathView pathView) {
- anim = ObjectAnimator.ofFloat(pathView, "percentage", 0.0f, 1.0f);
- }
- /**
- * Set the duration of the animation.
- *
- * @param duration - The duration of the animation.
- * @return AnimatorBuilder.
- */
- public AnimatorBuilder duration(final int duration) {
- this.duration = duration;
- return this;
- }
- /**
- * Set the Interpolator.
- *
- * @param interpolator - Interpolator.
- * @return AnimatorBuilder.
- */
- public AnimatorBuilder interpolator(final Interpolator interpolator) {
- this.interpolator = interpolator;
- return this;
- }
- /**
- * The delay before the animation.
- *
- * @param delay - int the delay
- * @return AnimatorBuilder.
- */
- public AnimatorBuilder delay(final int delay) {
- this.delay = delay;
- return this;
- }
- /**
- * Set a listener before the start of the animation.
- *
- * @param listenerStart an interface called before the animation
- * @return AnimatorBuilder.
- */
- public AnimatorBuilder listenerStart(final ListenerStart listenerStart) {
- this.listenerStart = listenerStart;
- if (pathViewAnimatorListener == null) {
- pathViewAnimatorListener = new PathViewAnimatorListener();
- anim.addListener(pathViewAnimatorListener);
- }
- return this;
- }
- /**
- * Set a listener after of the animation.
- *
- * @param animationEnd an interface called after the animation
- * @return AnimatorBuilder.
- */
- public AnimatorBuilder listenerEnd(final ListenerEnd animationEnd) {
- this.animationEnd = animationEnd;
- if (pathViewAnimatorListener == null) {
- pathViewAnimatorListener = new PathViewAnimatorListener();
- anim.addListener(pathViewAnimatorListener);
- }
- return this;
- }
- /**
- * Starts the animation.
- */
- public void start() {
- anim.setDuration(duration);
- anim.setInterpolator(interpolator);
- anim.setStartDelay(delay);
- anim.start();
- }
- /**
- * Animation listener to be able to provide callbacks for the caller.
- */
- private class PathViewAnimatorListener implements Animator.AnimatorListener {
- @Override
- public void onAnimationStart(Animator animation) {
- if (listenerStart != null) listenerStart.onAnimationStart();
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- if (animationEnd != null) animationEnd.onAnimationEnd();
- }
- @Override
- public void onAnimationCancel(Animator animation) {
- }
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
- }
- /**
- * Called when the animation start.
- */
- public interface ListenerStart {
- /**
- * Called when the path animation start.
- */
- void onAnimationStart();
- }
- /**
- * Called when the animation end.
- */
- public interface ListenerEnd {
- /**
- * Called when the path animation end.
- */
- void onAnimationEnd();
- }
- }
- }