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();
-
}
-
}
-
}
转自:https://blog.csdn.net/crazy__chen/article/details/47728241