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"?>
<LinearLayoutxmlns: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.PathViewxmlns: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 {@Overrideprotected 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() {@Overridepublic 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();@Overridepublic int getWidth() {return width;}@Overridepublic int getHeight() {return height;}@Overridepublic void drawPath(Path path, Paint paint) {Path dst = new Path();//noinspection deprecationgetMatrix(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 earliersvgPath.path.rLineTo(0.0f, 0.0f);}}@Overrideprotected 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(); } } }

Android实现炫酷SVG动画效果相关推荐

  1. android svg动画框架,Android实现炫酷SVG动画效果

    svg是目前十分流行的图像文件格式了,svg严格来说应该是一种开放标准的矢量图形语言,使用svg格式我们可以直接用代码来描绘图像,可以用任何文字处理工具打开svg图像,通过改变部分代码来使图像具有交互 ...

  2. 纯html+css炫酷地球仪动画效果

    纯html+css炫酷地球仪动画效果 <!DOCTYPE html> <html lang="en"> <head><meta chars ...

  3. html中flash的简单动画效果,css实现快速炫酷抖动动画效果

    1.Animate.css简介 Animate.css是一个可在您的Web项目中使用的即用型跨浏览器动画库.非常适合强调,首页,滑块和引导注意的提示.它是一个来自国外的 CSS3 动画库,它预设了抖动 ...

  4. 【每日一练】138—CSS实现炫酷背景动画效果

    以下是今天练习的最终效果: HTML代码: <!DOCTYPE html> <html lang="en"> <head><meta na ...

  5. android 炫酷进度条,Android打造炫酷进度条效果

    本文实例为大家分享了Android炫酷进度条效果的具体代码,供大家参考,具体内容如下 HorizontalProgressbarWithProgress的代码 import android.conte ...

  6. android炫酷的动画效果

    这段时间看到一些比较好看的android动画效果,下面我就给大家一些我比较喜欢的动画效果,并附上源码希望对你们有用处. 1.很简单却很酷的粒子破碎效果 介绍:  实现思路 1.新建一个 Bean Pa ...

  7. 如何利用 Android 自定义控件实现炫酷的动画?|CSDN 博文精选

    作者 | u012551350 本文精选自 CSDN 博客,已获作者授权 「知足常乐」,很多人不满足现状,各种折腾,往往舍本逐末,常乐才能少一分浮躁,多一分宁静.近期在笔者身上发生了许多事情,心态也发 ...

  8. iOS动画开发之五——炫酷的粒子效果

    iOS动画开发之五--炫酷的粒子效果 在上几篇博客中,我们对UIView层的动画以及iOS的核心动画做了介绍,基本已经可以满足iOS应用项目中所有的动画需求,如果你觉得那些都还不够炫酷,亦或是你灵光一 ...

  9. android 天气动画,为app制作炫酷天气动画 – WeatherView

    WeatherView 从1.1.0版本开始这个库使用了一个不同的setter结构. WeatherView是一个为app制作一个炫酷天气动画的Android库. Setup Android Stud ...

最新文章

  1. SQL Server 中update的小计
  2. 深度学习在高德的探索与实践
  3. 关于华为虚拟操作键收起后页面高度不会刷新问题的总结
  4. java 泛型例子_java中的泛型的一些常见例子
  5. docker删除镜像命令_第三章 Docker常用命令之镜像命令
  6. 项目使用encode_Spring Cloud Security:Oauth2使用入门
  7. LeetCode45 Jump Game II
  8. css中改变边距会影响原大小,CSS:更改父容器中子项的边距会改变子项的宽度吗?...
  9. scala 当前日期_如何在Scala中检查当前日期和时间?
  10. 揭秘自编码器,一种捕捉数据最重要特征的神经网络(视频+代码)
  11. 今天闲来无事,做了个简易的ORM 感觉有点像ActiveRecord作业风格,又有点像iBatis...
  12. CNN中的卷积、1x1卷积及在pytorch中的验证
  13. 关于判断卡BIN的修正
  14. 基于java疫情防控管理系统
  15. SCRT同网段的ping不通
  16. ajax php投票记录功能,PHP 实例 AJAX 投票 | 菜鸟教程
  17. mysql类exadata功能_Exadata:Smart Scan(一)
  18. 大学生计算机应用大赛广告设计,第11届全国大学生计算机应用能力与信息素养大赛 “平面视觉设计” 赛项圆满结束...
  19. 天牛须算法(BAS)python实现
  20. 全国增值税发票查验平台验证码识别

热门文章

  1. jstl:sql标签介绍
  2. linux与window中sleep函数的头文件
  3. 操作系统储存管理功能
  4. 英特尔推出颠覆性架构:3D堆叠芯片,10nm制程明年上市
  5. APK Expansion Files / Obb 接入介绍
  6. python3.5和pip3安装路径不匹配问题
  7. [bzoj 1954]Pku3764 The xor-longest Path
  8. 完美世界第二题:模拟读数字
  9. onInterceptTouchEvent和onTouchEvent调用时序
  10. 使用电脑一定得有良好的习惯呀!