If you think the Android project muzei listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
Java Source Code
/*
* Copyright 2014 Google Inc./*fromwww.java2s.com*/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/package com.google.android.apps.muzei.util;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import java.text.ParseException;
importstatic com.google.android.apps.muzei.util.LogUtil.LOGE;
publicclass AnimatedMuzeiLoadingSpinnerView extends View {
privatestaticfinal String TAG = LogUtil.makeLogTag(AnimatedMuzeiLoadingSpinnerView.class);
privatestaticfinalint TRACE_TIME = 1000;
privatestaticfinalint MARKER_LENGTH_DIP = 16;
privatestaticfinalint TRACE_RESIDUE_COLOR = Color.argb(50, 255, 255, 255);
privatestaticfinalint TRACE_COLOR = Color.WHITE;
privatestaticfinal RectF VIEWPORT = new RectF(0, 88, 318, 300);
privatestaticfinal Interpolator INTERPOLATOR = new LinearInterpolator();
private GlyphData mGlyphData;
privatefloat mMarkerLength;
privateint mWidth;
privateint mHeight;
privatelong mStartTime = -1;
public AnimatedMuzeiLoadingSpinnerView(Context context) {
super(context);
init();
}
public AnimatedMuzeiLoadingSpinnerView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public AnimatedMuzeiLoadingSpinnerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
privatevoid init() {
mMarkerLength = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
MARKER_LENGTH_DIP, getResources().getDisplayMetrics());
// See https://github.com/romainguy/road-trip/blob/master/application/src/main/java/org/curiouscreature/android/roadtrip/IntroView.java
// Note: using a software layer here is an optimization. This view works with
// hardware accelerated rendering but every time a path is modified (when the
// dash path effect is modified), the graphics pipeline will rasterize the path
// again in a new texture. Since we are dealing with dozens of paths, it is much
// more efficient to rasterize the entire view into a single re-usable texture
// instead. Ideally this should be toggled using a heuristic based on the number
// and or dimensions of paths to render.
// Note that PathDashPathEffects can lead to clipping issues with hardware rendering.
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
publicvoid start() {
mStartTime = System.currentTimeMillis();
postInvalidateOnAnimation();
}
publicvoid stop() {
mStartTime = -1;
postInvalidateOnAnimation();
}
@Override
protectedvoid onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
rebuildGlyphData();
}
privatevoid rebuildGlyphData() {
SvgPathParser parser = new SvgPathParser() {
@Override
protectedfloat transformX(float x) {
return x * mWidth / VIEWPORT.width();
}
@Override
protectedfloat transformY(float y) {
return y * mHeight / VIEWPORT.height();
}
};
mGlyphData = new GlyphData();
try {
mGlyphData.path = parser.parsePath(LogoPaths.GLYPHS[0]);
} catch (ParseException e) {
mGlyphData.path = new Path();
LOGE(TAG, "Couldn't parse path", e);
}
PathMeasure pm = new PathMeasure(mGlyphData.path, true);
while (true) {
mGlyphData.length = Math.max(mGlyphData.length, pm.getLength());
if (!pm.nextContour()) {
break;
}
}
mGlyphData.paint = new Paint();
mGlyphData.paint.setStyle(Paint.Style.STROKE);
mGlyphData.paint.setAntiAlias(true);
mGlyphData.paint.setColor(Color.WHITE);
mGlyphData.paint.setStrokeWidth(
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,
getResources().getDisplayMetrics()));
}
@Override
protectedvoid onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mStartTime < 0 || mGlyphData == null) {
return;
}
long t = (System.currentTimeMillis() - mStartTime) % (TRACE_TIME * 2);
int sc = canvas.save();
canvas.translate(
-VIEWPORT.left * mWidth / VIEWPORT.width(),
-VIEWPORT.top * mHeight / VIEWPORT.height());
// Draw outlines (starts as traced)
float phase = MathUtil.constrain(0, 1, (t % TRACE_TIME) * 1f / TRACE_TIME);
float distance = INTERPOLATOR.getInterpolation(phase) * mGlyphData.length;
mGlyphData.paint.setColor(TRACE_RESIDUE_COLOR);
if (t < TRACE_TIME) {
mGlyphData.paint.setPathEffect(new DashPathEffect(
newfloat[]{distance, mGlyphData.length}, 0));
} else {
mGlyphData.paint.setPathEffect(new DashPathEffect(
newfloat[]{0, distance, mGlyphData.length, 0}, 0));
}
canvas.drawPath(mGlyphData.path, mGlyphData.paint);
mGlyphData.paint.setColor(TRACE_COLOR);
mGlyphData.paint.setPathEffect(new DashPathEffect(
newfloat[]{0, distance, phase > 0 ? mMarkerLength : 0,
mGlyphData.length}, 0));
canvas.drawPath(mGlyphData.path, mGlyphData.paint);
canvas.restoreToCount(sc);
postInvalidateOnAnimation();
}
privatestaticclass GlyphData {
Path path;
Paint paint;
float length;
}
}