- Add location capabilities, using Google Play Services.

- Shift to using GlowPadBackport maven library
This commit is contained in:
2014-04-13 22:27:21 +02:00
parent ad051bc1c2
commit a0c2f37b07
48 changed files with 142 additions and 4516 deletions

View File

@ -1 +0,0 @@
/build

View File

@ -6,72 +6,14 @@
<option name="GRADLE_PROJECT_PATH" value=":GlowPadBackport" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugJava" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="LIBRARY_PROJECT" value="true" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes/debug" />
<output url="file://$MODULE_DIR$/build/classes/main" />
<output-test url="file://$MODULE_DIR$/build/classes/test" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/source/r/test/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/aidl/test/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/buildConfig/test/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/source/rs/test/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/res/rs/test/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/apk" />
<excludeFolder url="file://$MODULE_DIR$/build/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/res" />
<excludeFolder url="file://$MODULE_DIR$/build/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="library-2.4.0" level="project" />
</component>
</module>

View File

@ -1,23 +0,0 @@
apply plugin: 'android-library'
android {
compileSdkVersion 19
buildToolsVersion "19.0.1"
defaultConfig {
minSdkVersion 8
targetSdkVersion 16
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.nineoldandroids:library:2.4.0'
}

View File

@ -1,17 +0,0 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/tim/sources/android-studio/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.sebastianopoggi.ui.GlowPadBackport" >
<application />
</manifest>

View File

@ -1,134 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* 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 net.sebastianopoggi.ui.GlowPadBackport;
import net.sebastianopoggi.ui.GlowPadBackport.util.TimeInterpolator;
class Ease {
private static final float DOMAIN = 1.0f;
private static final float DURATION = 1.0f;
private static final float START = 0.0f;
static class Linear {
public static final TimeInterpolator easeNone = new TimeInterpolator() {
public float getInterpolation(float input) {
return input;
}
};
}
static class Cubic {
public static final TimeInterpolator easeIn = new TimeInterpolator() {
public float getInterpolation(float input) {
return DOMAIN * (input /= DURATION) * input * input + START;
}
};
public static final TimeInterpolator easeOut = new TimeInterpolator() {
public float getInterpolation(float input) {
return DOMAIN * ((input = input / DURATION - 1) * input * input + 1) + START;
}
};
public static final TimeInterpolator easeInOut = new TimeInterpolator() {
public float getInterpolation(float input) {
return ((input /= DURATION / 2) < 1.0f) ?
(DOMAIN / 2 * input * input * input + START)
: (DOMAIN / 2 * ((input -= 2) * input * input + 2) + START);
}
};
}
static class Quad {
public static final TimeInterpolator easeIn = new TimeInterpolator() {
public float getInterpolation(float input) {
return DOMAIN * (input /= DURATION) * input + START;
}
};
public static final TimeInterpolator easeOut = new TimeInterpolator() {
public float getInterpolation(float input) {
return -DOMAIN * (input /= DURATION) * (input - 2) + START;
}
};
public static final TimeInterpolator easeInOut = new TimeInterpolator() {
public float getInterpolation(float input) {
return ((input /= DURATION / 2) < 1) ?
(DOMAIN / 2 * input * input + START)
: (-DOMAIN / 2 * ((--input) * (input - 2) - 1) + START);
}
};
}
static class Quart {
public static final TimeInterpolator easeIn = new TimeInterpolator() {
public float getInterpolation(float input) {
return DOMAIN * (input /= DURATION) * input * input * input + START;
}
};
public static final TimeInterpolator easeOut = new TimeInterpolator() {
public float getInterpolation(float input) {
return -DOMAIN * ((input = input / DURATION - 1) * input * input * input - 1) + START;
}
};
public static final TimeInterpolator easeInOut = new TimeInterpolator() {
public float getInterpolation(float input) {
return ((input /= DURATION / 2) < 1) ?
(DOMAIN / 2 * input * input * input * input + START)
:
(-DOMAIN / 2 * ((input -= 2) * input * input * input - 2) + START);
}
};
}
static class Quint {
public static final TimeInterpolator easeIn = new TimeInterpolator() {
public float getInterpolation(float input) {
return DOMAIN * (input /= DURATION) * input * input * input * input + START;
}
};
public static final TimeInterpolator easeOut = new TimeInterpolator() {
public float getInterpolation(float input) {
return DOMAIN * ((input = input / DURATION - 1) * input * input * input * input + 1) + START;
}
};
public static final TimeInterpolator easeInOut = new TimeInterpolator() {
public float getInterpolation(float input) {
return ((input /= DURATION / 2) < 1) ?
(DOMAIN / 2 * input * input * input * input * input + START)
:
(DOMAIN / 2 * ((input -= 2) * input * input * input * input + 2) + START);
}
};
}
static class Sine {
public static final TimeInterpolator easeIn = new TimeInterpolator() {
public float getInterpolation(float input) {
return -DOMAIN * (float) Math.cos(input / DURATION * (Math.PI / 2)) + DOMAIN + START;
}
};
public static final TimeInterpolator easeOut = new TimeInterpolator() {
public float getInterpolation(float input) {
return DOMAIN * (float) Math.sin(input / DURATION * (Math.PI / 2)) + START;
}
};
public static final TimeInterpolator easeInOut = new TimeInterpolator() {
public float getInterpolation(float input) {
return -DOMAIN / 2 * ((float) Math.cos(Math.PI * input / DURATION) - 1.0f) + START;
}
};
}
}

View File

@ -1,247 +0,0 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* 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 net.sebastianopoggi.ui.GlowPadBackport;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.FloatMath;
import android.util.Log;
import java.util.ArrayList;
public class PointCloud {
private static final float MIN_POINT_SIZE = 2.0f;
private static final float MAX_POINT_SIZE = 4.0f;
private static int INNER_POINTS = 8;
private static final String TAG = "PointCloud";
private ArrayList<Point> mPointCloud = new ArrayList<Point>();
private Drawable mDrawable;
private float mCenterX;
private float mCenterY;
private Paint mPaint;
private float mScale = 1.0f;
private static final float PI = (float) Math.PI;
// These allow us to have multiple concurrent animations.
WaveManager waveManager = new WaveManager();
GlowManager glowManager = new GlowManager();
private float mOuterRadius, mInnerRadius;
public class WaveManager {
private float radius = 50;
private float width = 200.0f; // TODO: Make configurable
private float alpha = 0.0f;
public void setRadius(float r) {
radius = r;
}
public float getRadius() {
return radius;
}
public void setAlpha(float a) {
alpha = a;
}
public float getAlpha() {
return alpha;
}
}
public class GlowManager {
private float x;
private float y;
private float radius = 0.0f;
private float alpha = 0.0f;
public void setX(float x1) {
x = x1;
}
public float getX() {
return x;
}
public void setY(float y1) {
y = y1;
}
public float getY() {
return y;
}
public void setAlpha(float a) {
alpha = a;
}
public float getAlpha() {
return alpha;
}
public void setRadius(float r) {
radius = r;
}
public float getRadius() {
return radius;
}
}
class Point {
float x;
float y;
float radius;
public Point(float x2, float y2, float r) {
x = x2;
y = y2;
radius = r;
}
}
public PointCloud(Drawable drawable) {
mPaint = new Paint();
mPaint.setFilterBitmap(true);
mPaint.setColor(Color.rgb(255, 255, 255)); // TODO: make configurable
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mDrawable = drawable;
if (mDrawable != null) {
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
}
}
/*package*/ void setPointsMultiplier(int mult) {
INNER_POINTS = mult;
makePointCloud(mInnerRadius, mOuterRadius);
}
/*package*/ int getPointsMultiplier() {
return INNER_POINTS;
}
public void setCenter(float x, float y) {
mCenterX = x;
mCenterY = y;
}
public void makePointCloud(float innerRadius, float outerRadius) {
if (innerRadius == 0) {
Log.w(TAG, "Must specify an inner radius");
return;
}
mOuterRadius = outerRadius;
mInnerRadius = innerRadius;
mPointCloud.clear();
final float pointAreaRadius = (outerRadius - innerRadius);
final float ds = (2.0f * PI * innerRadius / INNER_POINTS);
final int bands = Math.round(pointAreaRadius / ds);
final float dr = pointAreaRadius / bands;
float r = innerRadius;
for (int b = 0; b <= bands; b++, r += dr) {
float circumference = 2.0f * PI * r;
final int pointsInBand = (int) (circumference / ds);
float eta = PI / 2.0f;
float dEta = 2.0f * PI / pointsInBand;
for (int i = 0; i < pointsInBand; i++) {
float x = r * FloatMath.cos(eta);
float y = r * FloatMath.sin(eta);
eta += dEta;
mPointCloud.add(new Point(x, y, r));
}
}
}
public void setScale(float scale) {
mScale = scale;
}
public float getScale() {
return mScale;
}
private static float hypot(float x, float y) {
return FloatMath.sqrt(x * x + y * y);
}
private static float max(float a, float b) {
return a > b ? a : b;
}
public int getAlphaForPoint(Point point) {
// Contribution from positional glow
float glowDistance = hypot(glowManager.x - point.x, glowManager.y - point.y);
float glowAlpha = 0.0f;
if (glowDistance < glowManager.radius) {
float cosf = FloatMath.cos(PI * 0.25f * glowDistance / glowManager.radius);
glowAlpha = glowManager.alpha * max(0.0f, (float) Math.pow(cosf, 10.0f));
}
// Compute contribution from Wave
float radius = hypot(point.x, point.y);
float distanceToWaveRing = (radius - waveManager.radius);
float waveAlpha = 0.0f;
if (distanceToWaveRing < waveManager.width * 0.5f && distanceToWaveRing < 0.0f) {
float cosf = FloatMath.cos(PI * 0.25f * distanceToWaveRing / waveManager.width);
waveAlpha = waveManager.alpha * max(0.0f, (float) Math.pow(cosf, 20.0f));
}
return (int) (max(glowAlpha, waveAlpha) * 255);
}
private float interp(float min, float max, float f) {
return min + (max - min) * f;
}
public void draw(Canvas canvas) {
ArrayList<Point> points = mPointCloud;
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(mScale, mScale, mCenterX, mCenterY);
for (int i = 0; i < points.size(); i++) {
Point point = points.get(i);
final float pointSize = interp(MAX_POINT_SIZE, MIN_POINT_SIZE,
point.radius / mOuterRadius);
final float px = point.x + mCenterX;
final float py = point.y + mCenterY;
int alpha = getAlphaForPoint(point);
if (alpha == 0) continue;
if (mDrawable != null) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
final float cx = mDrawable.getIntrinsicWidth() * 0.5f;
final float cy = mDrawable.getIntrinsicHeight() * 0.5f;
final float s = pointSize / MAX_POINT_SIZE;
canvas.scale(s, s, px, py);
canvas.translate(px - cx, py - cy);
mDrawable.setAlpha(alpha);
mDrawable.draw(canvas);
canvas.restore();
}
else {
mPaint.setAlpha(alpha);
canvas.drawCircle(px, py, pointSize, mPaint);
}
}
canvas.restore();
}
}

View File

@ -1,341 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* 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 net.sebastianopoggi.ui.GlowPadBackport;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.util.Log;
import java.lang.reflect.Method;
public class TargetDrawable {
private static final String TAG = "TargetDrawable";
private static final boolean DEBUG = false;
public static final int[] STATE_ACTIVE =
{android.R.attr.state_enabled, android.R.attr.state_active};
public static final int[] STATE_INACTIVE =
{android.R.attr.state_enabled, -android.R.attr.state_active};
public static final int[] STATE_FOCUSED =
{android.R.attr.state_enabled, -android.R.attr.state_active,
android.R.attr.state_focused};
// We're using Reflection to access these private APIs on older Android versions
static Method mGetStateDrawableIndex, mGetStateCount, mGetStateDrawable;
static {
// In this static block we initialize all reflected methods (so that we can work around
// the @hide annotations for those Android Framework methods). This is not ideal, but
// there's not much we can do about that either.
try {
mGetStateCount = StateListDrawable.class.getDeclaredMethod("getStateCount");
mGetStateCount.setAccessible(true);
}
catch (NoSuchMethodException e) {
Log.e(TAG, "Couldn't access the StateListDrawable#getStateCount() method. " +
"Some stuff might break!", e);
}
try {
mGetStateDrawable = StateListDrawable.class.getDeclaredMethod("getStateDrawable", int.class);
mGetStateDrawable.setAccessible(true);
}
catch (NoSuchMethodException e) {
Log.e(TAG, "Couldn't access the StateListDrawable#getStateDrawable(int) method. " +
"Some stuff might break!", e);
}
try {
mGetStateDrawableIndex = StateListDrawable.class.getDeclaredMethod("getStateDrawableIndex", int[].class);
mGetStateDrawableIndex.setAccessible(true);
}
catch (NoSuchMethodException e) {
Log.e(TAG, "Couldn't access the StateListDrawable#mGetStateDrawableIndex(int[]) method. " +
"Some stuff might break!", e);
}
}
private float mTranslationX = 0.0f;
private float mTranslationY = 0.0f;
private float mPositionX = 0.0f;
private float mPositionY = 0.0f;
private float mScaleX = 1.0f;
private float mScaleY = 1.0f;
private float mAlpha = 1.0f;
private Drawable mDrawable;
private boolean mEnabled = true;
private final int mResourceId;
/* package */ static class DrawableWithAlpha extends Drawable {
private float mAlpha = 1.0f;
private Drawable mRealDrawable;
public DrawableWithAlpha(Drawable realDrawable) {
mRealDrawable = realDrawable;
}
public void setAlphaFloat(float alpha) {
mAlpha = alpha;
}
public int getAlphaFloat() {
return (int) (mAlpha * 255);
}
public void draw(Canvas canvas) {
mRealDrawable.setAlpha(Math.round(mAlpha * 255f));
mRealDrawable.draw(canvas);
}
@Override
public void setAlpha(int alpha) {
mRealDrawable.setAlpha(alpha);
}
@Override
public int getAlpha() {
return mRealDrawable.getAlpha();
}
@Override
public void setColorFilter(ColorFilter cf) {
mRealDrawable.setColorFilter(cf);
}
@Override
public int getOpacity() {
return mRealDrawable.getOpacity();
}
}
public TargetDrawable(Resources res, int resId) {
mResourceId = resId;
setDrawable(res, resId);
}
public void setDrawable(Resources res, int resId) {
// Note we explicitly don't set mResourceId to resId since we allow the drawable to be
// swapped at runtime and want to re-use the existing resource id for identification.
Drawable drawable = resId == 0 ? null : res.getDrawable(resId);
// Mutate the drawable so we can animate shared drawable properties.
mDrawable = drawable != null ? drawable.mutate() : null;
resizeDrawables();
setState(STATE_INACTIVE);
}
public TargetDrawable(TargetDrawable other) {
mResourceId = other.mResourceId;
// Mutate the drawable so we can animate shared drawable properties.
mDrawable = other.mDrawable != null ? other.mDrawable.mutate() : null;
resizeDrawables();
setState(STATE_INACTIVE);
}
public void setState(int[] state) {
if (mDrawable instanceof StateListDrawable) {
StateListDrawable d = (StateListDrawable) mDrawable;
d.setState(state);
}
}
public boolean hasState(int[] state) {
if (mDrawable instanceof StateListDrawable) {
StateListDrawable d = (StateListDrawable) mDrawable;
// TODO: this doesn't seem to work
try {
return (Integer) mGetStateDrawableIndex.invoke(d, state) != -1;
}
catch (Exception e) {
Log.w(TAG, "StateListDrawable#getStateDrawableIndex(int[]) call failed!", e);
}
}
return false;
}
/**
* Returns true if the drawable is a StateListDrawable and is in the focused state.
*
* @return Returns true if the drawable is a StateListDrawable and is in the focused state
*/
public boolean isActive() {
if (mDrawable instanceof StateListDrawable) {
StateListDrawable d = (StateListDrawable) mDrawable;
int[] states = d.getState();
for (int i = 0; i < states.length; i++) {
if (states[i] == android.R.attr.state_focused) {
return true;
}
}
}
return false;
}
/**
* Returns true if this target is enabled. Typically an enabled target contains a valid
* drawable in a valid state. Currently all targets with valid drawables are valid.
*
* @return Returns true if the target is enabled, false otherwise
*/
public boolean isEnabled() {
return mDrawable != null && mEnabled;
}
/**
* Makes drawables in a StateListDrawable all the same dimensions.
* If not a StateListDrawable, then justs sets the bounds to the intrinsic size of the
* drawable.
*/
private void resizeDrawables() {
if (mDrawable instanceof StateListDrawable) {
StateListDrawable d = (StateListDrawable) mDrawable;
int maxWidth = 0;
int maxHeight = 0;
Integer stateCount = 0;
try {
stateCount = (Integer) mGetStateCount.invoke(d);
}
catch (Exception e) {
Log.w(TAG, "StateListDrawable#getStateCount() call failed!", e);
}
for (int i = 0; i < stateCount; i++) {
Drawable childDrawable;
try {
childDrawable = (Drawable) mGetStateDrawable.invoke(d, i);
}
catch (Exception e) {
Log.w(TAG, "StateListDrawable#getStateDrawable(int) call failed!", e);
continue;
}
maxWidth = Math.max(maxWidth, childDrawable.getIntrinsicWidth());
maxHeight = Math.max(maxHeight, childDrawable.getIntrinsicHeight());
}
if (DEBUG) {
Log.v(TAG, "union of childDrawable rects " + d + " to: "
+ maxWidth + "x" + maxHeight);
}
d.setBounds(0, 0, maxWidth, maxHeight);
for (int i = 0; i < stateCount; i++) {
Drawable childDrawable;
try {
childDrawable = (Drawable) mGetStateDrawable.invoke(d, i);
}
catch (Exception e) {
Log.w(TAG, "StateListDrawable#getStateDrawable(int) call failed!", e);
continue;
}
if (DEBUG) {
Log.v(TAG, "sizing drawable " + childDrawable + " to: "
+ maxWidth + "x" + maxHeight);
}
childDrawable.setBounds(0, 0, maxWidth, maxHeight);
}
}
else if (mDrawable != null) {
mDrawable.setBounds(0, 0,
mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
}
}
public void setX(float x) {
mTranslationX = x;
}
public void setY(float y) {
mTranslationY = y;
}
public void setScaleX(float x) {
mScaleX = x;
}
public void setScaleY(float y) {
mScaleY = y;
}
public void setAlpha(float alpha) {
mAlpha = alpha;
}
public float getX() {
return mTranslationX;
}
public float getY() {
return mTranslationY;
}
public float getScaleX() {
return mScaleX;
}
public float getScaleY() {
return mScaleY;
}
public float getAlpha() {
return mAlpha;
}
public void setPositionX(float x) {
mPositionX = x;
}
public void setPositionY(float y) {
mPositionY = y;
}
public float getPositionX() {
return mPositionX;
}
public float getPositionY() {
return mPositionY;
}
public int getWidth() {
return mDrawable != null ? mDrawable.getIntrinsicWidth() : 0;
}
public int getHeight() {
return mDrawable != null ? mDrawable.getIntrinsicHeight() : 0;
}
public void draw(Canvas canvas) {
if (mDrawable == null || !mEnabled) {
return;
}
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(mScaleX, mScaleY, mPositionX, mPositionY);
canvas.translate(mTranslationX + mPositionX, mTranslationY + mPositionY);
canvas.translate(-0.5f * getWidth(), -0.5f * getHeight());
mDrawable.setAlpha(Math.round(mAlpha * 255f));
mDrawable.draw(canvas);
canvas.restore();
}
public void setEnabled(boolean enabled) {
mEnabled = enabled;
}
public int getResourceId() {
return mResourceId;
}
}

View File

@ -1,190 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* 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 net.sebastianopoggi.ui.GlowPadBackport;
import android.util.Log;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.Animator.AnimatorListener;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.animation.PropertyValuesHolder;
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;
import net.sebastianopoggi.ui.GlowPadBackport.util.TimeInterpolator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
class Tweener {
private static final String TAG = "Tweener";
private static final boolean DEBUG = false;
ObjectAnimator animator;
private static HashMap<Object, Tweener> sTweens = new HashMap<Object, Tweener>();
public Tweener(ObjectAnimator anim) {
animator = anim;
}
private static void remove(Animator animator) {
Iterator<Entry<Object, Tweener>> iter = sTweens.entrySet().iterator();
while (iter.hasNext()) {
Entry<Object, Tweener> entry = iter.next();
if (entry.getValue().animator == animator) {
if (DEBUG) {
Log.v(TAG, "Removing tweener " + sTweens.get(entry.getKey())
+ " sTweens.size() = " + sTweens.size());
}
iter.remove();
break; // an animator can only be attached to one object
}
}
}
public static Tweener to(Object object, long duration, Object... vars) {
long delay = 0;
AnimatorUpdateListener updateListener = null;
AnimatorListener listener = null;
TimeInterpolator interpolator = null;
// Iterate through arguments and discover properties to animate
ArrayList<PropertyValuesHolder> props = new ArrayList<PropertyValuesHolder>(vars.length / 2);
for (int i = 0; i < vars.length; i += 2) {
if (!(vars[i] instanceof String)) {
throw new IllegalArgumentException("Key must be a string: " + vars[i]);
}
String key = (String) vars[i];
Object value = vars[i + 1];
if ("simultaneousTween".equals(key)) {
// TODO
}
else if ("ease".equals(key)) {
interpolator = (TimeInterpolator) value; // TODO: multiple interpolators?
}
else if ("onUpdate".equals(key) || "onUpdateListener".equals(key)) {
updateListener = (AnimatorUpdateListener) value;
}
else if ("onComplete".equals(key) || "onCompleteListener".equals(key)) {
listener = (AnimatorListener) value;
}
else if ("delay".equals(key)) {
delay = ((Number) value).longValue();
}
else if ("syncWith".equals(key)) {
// TODO
}
else if (value instanceof float[]) {
props.add(PropertyValuesHolder.ofFloat(key,
((float[]) value)[0], ((float[]) value)[1]));
}
else if (value instanceof int[]) {
props.add(PropertyValuesHolder.ofInt(key,
((int[]) value)[0], ((int[]) value)[1]));
}
else if (value instanceof Number) {
float floatValue = ((Number) value).floatValue();
props.add(PropertyValuesHolder.ofFloat(key, floatValue));
}
else {
throw new IllegalArgumentException(
"Bad argument for key \"" + key + "\" with value " + value.getClass());
}
}
// Re-use existing tween, if present
Tweener tween = sTweens.get(object);
ObjectAnimator anim;
if (tween == null) {
anim = ObjectAnimator.ofPropertyValuesHolder(object,
props.toArray(new PropertyValuesHolder[props.size()]));
tween = new Tweener(anim);
sTweens.put(object, tween);
if (DEBUG) Log.v(TAG, "Added new Tweener " + tween);
}
else {
anim = sTweens.get(object).animator;
replace(props, object); // Cancel all animators for given object
}
if (interpolator != null) {
anim.setInterpolator(interpolator);
}
// Update animation with properties discovered in loop above
anim.setStartDelay(delay);
anim.setDuration(duration);
if (updateListener != null) {
anim.removeAllUpdateListeners(); // There should be only one
anim.addUpdateListener(updateListener);
}
if (listener != null) {
anim.removeAllListeners(); // There should be only one.
anim.addListener(listener);
}
anim.addListener(mCleanupListener);
return tween;
}
Tweener from(Object object, long duration, Object... vars) {
// TODO: for v of vars
// toVars[v] = object[v]
// object[v] = vars[v]
return Tweener.to(object, duration, vars);
}
// Listener to watch for completed animations and remove them.
private static AnimatorListener mCleanupListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
remove(animation);
}
@Override
public void onAnimationCancel(Animator animation) {
remove(animation);
}
};
public static void reset() {
if (DEBUG) {
Log.v(TAG, "Reset()");
if (sTweens.size() > 0) {
Log.v(TAG, "Cleaning up " + sTweens.size() + " animations");
}
}
sTweens.clear();
}
private static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
for (final Object killobject : args) {
Tweener tween = sTweens.get(killobject);
if (tween != null) {
tween.animator.cancel();
if (props != null) {
tween.animator.setValues(
props.toArray(new PropertyValuesHolder[props.size()]));
}
else {
sTweens.remove(tween);
}
}
}
}
}

View File

@ -1,22 +0,0 @@
package net.sebastianopoggi.ui.GlowPadBackport.util;
import android.os.Build;
/**
* Class
* <p/>
* Author: Sebastiano Poggi
* Created on: 1/28/13 Time: 3:57 PM
* File version: 1.0
* <p/>
* Changelog:
* Version 1.0
* * Initial revision
*/
public class Const {
public static final boolean IS_ECLAIR = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR;
public static final boolean IS_FROYO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
public static final boolean IS_ICS = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
public static final boolean IS_JB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
public static final boolean IS_JB_MR1 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
}

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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 net.sebastianopoggi.ui.GlowPadBackport.util;
import android.view.animation.Interpolator;
/**
* A time interpolator defines the rate of change of an animation. This allows animations
* to have non-linear motion, such as acceleration and deceleration.
*/
public interface TimeInterpolator extends Interpolator {
/**
* Maps a value representing the elapsed fraction of an animation to a value that represents
* the interpolated fraction. This interpolated value is then multiplied by the change in
* value of an animation to derive the animated value at the current elapsed animation time.
*
* @param input A value between 0 and 1.0 indicating our current point
* in the animation where 0 represents the start and 1.0 represents
* the end
* @return The interpolation value. This value can be more than 1.0 for
* interpolators which overshoot their targets, or less than 0 for
* interpolators that undershoot their targets.
*/
float getInterpolation(float input);
}

View File

@ -1,100 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="LinearLayout">
<attr name="gravity" />
</declare-styleable>
<!-- =============================== -->
<!-- GlowPadView class attributes -->
<!-- =============================== -->
<eat-comment />
<declare-styleable name="GlowPadView">
<!-- Reference to an array resource that be shown as targets around a circle. -->
<attr name="targetDrawables" format="reference"/>
<!-- Reference to an array resource that be used as description for the targets around the circle. -->
<attr name="targetDescriptions" format="reference"/>
<!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
<attr name="directionDescriptions" format="reference"/>
<!-- Sets a drawable as the center. -->
<attr name="handleDrawable" format="reference"/>
<!-- Drawable to use for wave ripple animation. -->
<attr name="outerRingDrawable" format="reference"/>
<!-- Drawble used for drawing points -->
<attr name="pointDrawable" format="reference" />
<!-- Inner radius of glow area. -->
<attr name="innerRadius" format="dimension"/>
<!-- Outer radius of glow area. Target icons will be drawn on this circle. -->
<attr name="outerRadius" format="dimension"/>
<!-- Radius of glow under finger. -->
<attr name="glowRadius" format="dimension" />
<!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
<attr name="vibrationDuration" format="integer"/>
<!-- How close we need to be before snapping to a target. -->
<attr name="snapMargin" format="dimension"/>
<!-- Number of waves/chevrons to show in animation. -->
<attr name="feedbackCount" format="integer"/>
<!-- Used when the handle shouldn't wait to be hit before following the finger -->
<attr name="alwaysTrackFinger" format="boolean"/>
<!-- Location along the circle of the first item, in degrees.-->
<attr name="firstItemOffset" format="float" />
<!-- Causes targets to snap to the finger location on activation. -->
<attr name="magneticTargets" format="boolean" />
<attr name="gravity"/>
<!-- Determine whether the glow pad is allowed to scale to fit the bounds indicated
by its parent. If this is set to false, no scaling will occur. If this is set to true
scaling will occur to fit for any axis in which gravity is set to center. -->
<attr name="allowScaling" format="boolean" />
</declare-styleable>
<!-- Specifies how to place the content of an object, both
on the x and y axis, within the object itself. -->
<attr name="gravity">
<!-- Push object to the top of its container, not changing its size. -->
<flag name="top" value="0x30" />
<!-- Push object to the bottom of its container, not changing its size. -->
<flag name="bottom" value="0x50" />
<!-- Push object to the left of its container, not changing its size. -->
<flag name="left" value="0x03" />
<!-- Push object to the right of its container, not changing its size. -->
<flag name="right" value="0x05" />
<!-- Place object in the vertical center of its container, not changing its size. -->
<flag name="center_vertical" value="0x10" />
<!-- Grow the vertical size of the object if needed so it completely fills its container. -->
<flag name="fill_vertical" value="0x70" />
<!-- Place object in the horizontal center of its container, not changing its size. -->
<flag name="center_horizontal" value="0x01" />
<!-- Grow the horizontal size of the object if needed so it completely fills its container. -->
<flag name="fill_horizontal" value="0x07" />
<!-- Place the object in the center of its container in both the vertical and horizontal axis, not changing its size. -->
<flag name="center" value="0x11" />
<!-- Grow the horizontal and vertical size of the object if needed so it completely fills its container. -->
<flag name="fill" value="0x77" />
<!-- Additional option that can be set to have the top and/or bottom edges of
the child clipped to its container's bounds.
The clip will be based on the vertical gravity: a top gravity will clip the bottom
edge, a bottom gravity will clip the top edge, and neither will clip both edges. -->
<flag name="clip_vertical" value="0x80" />
<!-- Additional option that can be set to have the left and/or right edges of
the child clipped to its container's bounds.
The clip will be based on the horizontal gravity: a left gravity will clip the right
edge, a right gravity will clip the left edge, and neither will clip both edges. -->
<flag name="clip_horizontal" value="0x08" />
</attr>
</resources>