├── .gitattributes
├── .gitignore
├── Aladdin
├── .classpath
├── .project
├── .settings
│ └── org.eclipse.core.resources.prefs
├── AndroidManifest.xml
├── lint.xml
├── proguard-project.txt
├── project.properties
├── res
│ ├── drawable-ldpi
│ │ ├── bg_small.png
│ │ └── pic.png
│ ├── layout
│ │ ├── aladdin_view.xml
│ │ ├── custom_layout.xml
│ │ └── float_window_layout.xml
│ └── values
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
└── src
│ └── com
│ └── tochange
│ └── yang
│ └── floatladdin
│ ├── LauncherActivity.java
│ ├── aladdin
│ ├── AbstractDrawGrid.java
│ ├── AladdinAnimation.java
│ ├── AladdinDrawGrid.java
│ ├── MainView.java
│ └── SettingLayoutActivity.java
│ └── floatwindow
│ ├── FloatWindowCustomView.java
│ ├── FloatWindowManager.java
│ └── FloatWindowService.java
├── FloatWindowAladdin.apk
├── NoActivityAladdin
└── Aladdin
│ ├── .classpath
│ ├── .project
│ ├── .settings
│ └── org.eclipse.core.resources.prefs
│ ├── AndroidManifest.xml
│ ├── lint.xml
│ ├── proguard-project.txt
│ ├── project.properties
│ ├── res
│ ├── drawable-ldpi
│ │ ├── bg_small.png
│ │ └── pic.png
│ ├── layout
│ │ ├── aladdin_view.xml
│ │ ├── custom_layout.xml
│ │ └── float_window_layout.xml
│ └── values
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── src
│ └── com
│ └── tochange
│ └── yang
│ └── floatladdin
│ ├── LauncherActivity.java
│ ├── aladdin
│ ├── AbstractDrawGrid.java
│ ├── AladdinAnimation.java
│ ├── AladdinDrawGrid.java
│ └── MainView.java
│ └── floatwindow
│ ├── FloatWindowCustomView.java
│ ├── FloatWindowManager.java
│ └── FloatWindowService.java
├── README.md
├── aa.gif
└── mac.jpg
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows image file caches
2 | Thumbs.db
3 | ehthumbs.db
4 |
5 | # Folder config file
6 | Desktop.ini
7 |
8 | # Recycle Bin used on file shares
9 | $RECYCLE.BIN/
10 |
11 | # Windows Installer files
12 | *.cab
13 | *.msi
14 | *.msm
15 | *.msp
16 |
17 | # =========================
18 | # Operating System Files
19 | # =========================
20 |
21 | # OSX
22 | # =========================
23 |
24 | .DS_Store
25 | .AppleDouble
26 | .LSOverride
27 |
28 | # Icon must ends with two \r.
29 | Icon
30 |
31 | # Thumbnails
32 | ._*
33 |
34 | # Files that might appear on external disk
35 | .Spotlight-V100
36 | .Trashes
37 |
--------------------------------------------------------------------------------
/Aladdin/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Aladdin/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | FloatWindowAladdin
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Aladdin/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | #Wed May 28 15:12:38 CST 2014
2 | eclipse.preferences.version=1
3 | encoding/=UTF-8
4 |
--------------------------------------------------------------------------------
/Aladdin/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Aladdin/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Aladdin/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/Aladdin/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-8
15 | android.library.reference.1=../../../Savigation/trunk/lib
16 |
--------------------------------------------------------------------------------
/Aladdin/res/drawable-ldpi/bg_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tochange/Aladdin/51c2708874aa4b66be596e2bfde966d79897c997/Aladdin/res/drawable-ldpi/bg_small.png
--------------------------------------------------------------------------------
/Aladdin/res/drawable-ldpi/pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tochange/Aladdin/51c2708874aa4b66be596e2bfde966d79897c997/Aladdin/res/drawable-ldpi/pic.png
--------------------------------------------------------------------------------
/Aladdin/res/layout/aladdin_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
17 |
18 |
25 |
26 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Aladdin/res/layout/custom_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
21 |
22 |
30 |
31 |
39 |
40 |
46 |
47 |
48 |
55 |
56 |
61 |
62 |
71 |
72 |
73 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/Aladdin/res/layout/float_window_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Aladdin/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/Aladdin/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Aladdin
5 | Settings
6 | Hello world!
7 | 沿此动画
8 |
9 |
--------------------------------------------------------------------------------
/Aladdin/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
24 |
25 |
31 |
32 |
--------------------------------------------------------------------------------
/Aladdin/src/com/tochange/yang/floatladdin/LauncherActivity.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 |
7 | import com.tochange.yang.floatladdin.floatwindow.FloatWindowService;
8 | import com.tochange.yang.lib.Utils;
9 | import com.tochange.yang.lib.ui.ScreenLib;
10 |
11 | public class LauncherActivity extends Activity {
12 |
13 | public static boolean IS_TABLTE = false;//not final type!
14 | public static final boolean DEBUG_MODE = false;
15 | public static final String KEY_X = "x";
16 | public static final String KEY_Y = "y";
17 | public static final String KEY_IMAGE = "image";
18 | public static final int MAGIC_VERTICAL = 15;
19 | public static final int ANIMATION_TIME_SHORT = 600;
20 | public static final int ANIMATION_TIME_LONG = 2000;
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | Intent intent = new Intent(LauncherActivity.this, FloatWindowService.class);
26 | startService(intent);
27 | if(ScreenLib.isTabletDevice(this)){
28 | IS_TABLTE = true;
29 | }
30 | finish();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Aladdin/src/com/tochange/yang/floatladdin/aladdin/AbstractDrawGrid.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.aladdin;
2 |
3 | //import com.tochange.yang.lib.log;
4 |
5 | public abstract class AbstractDrawGrid
6 | {
7 |
8 | public static final int VERTICAL_OFFSET = 15;
9 |
10 | protected int mHorizontalSplit;
11 |
12 | protected int mVerticalSplit;
13 |
14 | protected int mBmpWidth = -1;
15 |
16 | protected int mBmpHeight = -1;
17 |
18 | protected final float[] mVertices;
19 |
20 | public AbstractDrawGrid(int width, int height)
21 | {
22 | mHorizontalSplit = width;
23 | mVerticalSplit = height;
24 | mVertices = new float[(mHorizontalSplit + 1) * (mVerticalSplit + 1) * 2];
25 | }
26 |
27 | public float[] getVertices()
28 | {
29 | return mVertices;
30 | }
31 |
32 | public int getWidth()
33 | {
34 | return mHorizontalSplit;
35 | }
36 |
37 | public int getHeight()
38 | {
39 | return mVerticalSplit;
40 | }
41 |
42 | public static void setXY(float[] array, int index, float x, float y)
43 | {
44 | array[index * 2 + 0] = x;
45 | array[index * 2 + 1] = y;
46 | }
47 |
48 | public void setBitmapSize(int w, int h)
49 | {
50 | mBmpWidth = w;
51 | mBmpHeight = h;
52 | }
53 |
54 | public abstract void buildPaths(float endX, float endY);
55 |
56 | public abstract void buildMeshes(int index);
57 |
58 | public void buildMeshes(float w, float h)
59 | {
60 | int index = 0;
61 | for (int y = 0; y <= mVerticalSplit; y++)
62 | {
63 | float fy = y * h / mVerticalSplit + VERTICAL_OFFSET;
64 | for (int x = 0; x <= mHorizontalSplit; x++)
65 | {
66 | float fx = x * w / mHorizontalSplit;
67 | setXY(mVertices, index, fx, fy);
68 | index++;
69 | }
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/Aladdin/src/com/tochange/yang/floatladdin/aladdin/AladdinAnimation.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.aladdin;
2 |
3 | import com.tochange.yang.lib.log;
4 |
5 | import android.view.animation.Animation;
6 | import android.view.animation.Interpolator;
7 | import android.view.animation.Transformation;
8 |
9 | public class AladdinAnimation extends Animation
10 | {
11 |
12 | public interface IAnimationUpdateListener
13 | {
14 | public void onAnimUpdate(int index);
15 | }
16 |
17 | private int mFromIndex;
18 |
19 | private int mEndIndex;
20 |
21 | private boolean mReverse;
22 |
23 | private IAnimationUpdateListener mListener;
24 |
25 | public AladdinAnimation(int fromIndex, int endIndex, boolean reverse,
26 | IAnimationUpdateListener listener)
27 | {
28 | mFromIndex = fromIndex;
29 | mEndIndex = endIndex;
30 | mReverse = reverse;
31 | mListener = listener;
32 | }
33 |
34 | public boolean getTransformation(long currentTime,
35 | Transformation outTransformation)
36 | {
37 | return super.getTransformation(currentTime, outTransformation);
38 | }
39 |
40 | int lastTimeIndex;
41 |
42 | @Override
43 | protected void applyTransformation(float interpolatedTime, Transformation t)
44 | {
45 | Interpolator interpolator = this.getInterpolator();
46 | if (null != interpolator)
47 | {
48 | float value = interpolator.getInterpolation(interpolatedTime);
49 | interpolatedTime = value;
50 | }
51 | // log.e(""+(mReverse = true));
52 | if (mReverse)
53 | interpolatedTime = 1.0f - interpolatedTime;
54 |
55 | int currentIndex = (int) (mFromIndex + (mEndIndex - mFromIndex)
56 | * interpolatedTime);
57 | if (currentIndex == lastTimeIndex)
58 | return;
59 | lastTimeIndex = currentIndex;
60 |
61 | if (null != mListener)
62 | mListener.onAnimUpdate(currentIndex);
63 | }
64 | }
--------------------------------------------------------------------------------
/Aladdin/src/com/tochange/yang/floatladdin/aladdin/AladdinDrawGrid.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.aladdin;
2 |
3 | import com.tochange.yang.lib.log;
4 |
5 | import android.graphics.Path;
6 | import android.graphics.PathMeasure;
7 |
8 | public class AladdinDrawGrid extends AbstractDrawGrid
9 | {
10 | private Path mFirstPath;
11 |
12 | private Path mSecondPath;
13 |
14 | private PathMeasure mFirstPathMeasure;
15 |
16 | private PathMeasure mSecondPathMeasure;
17 |
18 | public AladdinDrawGrid(int width, int height)
19 | {
20 | super(width, height);
21 | // log.e("");
22 | mFirstPath = new Path();
23 | mSecondPath = new Path();
24 | mFirstPathMeasure = new PathMeasure();
25 | mSecondPathMeasure = new PathMeasure();
26 | }
27 |
28 | @Override
29 | public void buildPaths(float endX, float endY)
30 | {
31 |
32 | if (mBmpWidth <= 0 || mBmpHeight <= 0)
33 | {
34 | throw new IllegalArgumentException(
35 | "Bitmap size must be > 0, did you call setBitmapSize(int, int) method?");
36 | }
37 | mFirstPathMeasure.setPath(mFirstPath, false);
38 | mSecondPathMeasure.setPath(mSecondPath, false);
39 |
40 | float w = mBmpWidth;
41 | float h = mBmpHeight;
42 |
43 | mFirstPath.reset();
44 | mSecondPath.reset();
45 |
46 | mFirstPath.moveTo(0, VERTICAL_OFFSET);// start point of bezier
47 | mSecondPath.moveTo(w, VERTICAL_OFFSET);
48 | // mFirstPath.lineTo(0, h + VERTICAL_OFFSET);//line to the position
49 | // mSecondPath.lineTo(w, h + VERTICAL_OFFSET);
50 |
51 | mFirstPath.cubicTo(0, 6 * (endY + VERTICAL_OFFSET) / 12, endX / 2 + 30,
52 | 5 * (endY + VERTICAL_OFFSET) / 12, endX - 30, endY);
53 | mSecondPath.cubicTo(endX / 2, (endY + VERTICAL_OFFSET) / 4, endX,
54 | 2 * (endY + VERTICAL_OFFSET) / 3, endX - 10, endY);
55 | }
56 |
57 | @Override
58 | public void buildMeshes(int timeIndex)
59 | {
60 |
61 | if (mBmpWidth <= 0 || mBmpHeight <= 0)
62 | {
63 | throw new IllegalArgumentException(
64 | "Bitmap size must be > 0, did you call setBitmapSize(int, int) method?");
65 | }
66 | mFirstPathMeasure.setPath(mFirstPath, false);
67 | mSecondPathMeasure.setPath(mSecondPath, false);
68 |
69 | int index = 0;
70 | float[] pos1 = { 0.0f, 0.0f };
71 | float[] pos2 = { 0.0f, 0.0f };
72 |
73 | // all length of the curve
74 | float firstLen = mFirstPathMeasure.getLength();
75 | float secondLen = mSecondPathMeasure.getLength();
76 |
77 | float len1 = firstLen / mVerticalSplit;
78 | float len2 = secondLen / mVerticalSplit;
79 |
80 | float firstPointDist = timeIndex * len1;
81 | float secondPointDist = timeIndex * len2;
82 | float height = mBmpHeight;
83 |
84 | mFirstPathMeasure.getPosTan(firstPointDist, pos1, null);
85 | mFirstPathMeasure.getPosTan(firstPointDist + height, pos2, null);
86 |
87 | float x1 = pos1[0];
88 | float x2 = pos2[0];
89 | float y1 = pos1[1];
90 | float y2 = pos2[1];
91 | float firstDist = (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2)
92 | * (y1 - y2));
93 | float firstSplitDist = firstDist / mVerticalSplit;
94 |
95 | mSecondPathMeasure.getPosTan(secondPointDist, pos1, null);
96 | mSecondPathMeasure.getPosTan(secondPointDist + height, pos2, null);
97 | x1 = pos1[0];
98 | x2 = pos2[0];
99 | y1 = pos1[1];
100 | y2 = pos2[1];
101 |
102 | float secondDist = (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2)
103 | * (y1 - y2));
104 | float secondSplitDist = secondDist / mVerticalSplit;
105 |
106 | for (int y = 0; y <= mVerticalSplit; y++)
107 | {
108 | mFirstPathMeasure.getPosTan(y * firstSplitDist + firstPointDist,
109 | pos1, null);
110 | mSecondPathMeasure.getPosTan(y * secondSplitDist + secondPointDist,
111 | pos2, null);
112 |
113 | float fx1 = pos1[0];
114 | float fx2 = pos2[0];
115 | float fy1 = pos1[1];
116 | float fy2 = pos2[1];
117 |
118 | float dy = fy2 - fy1;
119 | float dx = fx2 - fx1;
120 |
121 | // horizon,mHorizontalSplit pixels
122 | for (int x = 0; x <= mHorizontalSplit; x++, index++)
123 | {
124 | float fx = dx * x / mHorizontalSplit;
125 | float fy = dy * x / mHorizontalSplit;
126 | mVertices[index * 2 + 0] = fx + fx1;
127 | mVertices[index * 2 + 1] = fy + fy1;
128 | }
129 | }
130 | }
131 |
132 | public Path[] getPaths()
133 | {
134 | return new Path[] { mFirstPath, mSecondPath };
135 | }
136 | }
--------------------------------------------------------------------------------
/Aladdin/src/com/tochange/yang/floatladdin/aladdin/MainView.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.aladdin;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.Path;
9 | import android.graphics.PorterDuff;
10 | import android.graphics.PorterDuff.Mode;
11 | import android.graphics.PorterDuffXfermode;
12 | import android.util.AttributeSet;
13 | import android.view.MotionEvent;
14 | import android.view.View;
15 | import android.view.animation.Animation;
16 | import android.view.animation.Animation.AnimationListener;
17 |
18 | import com.tochange.yang.floatladdin.aladdin.AladdinDrawGrid;
19 | import com.tochange.yang.floatladdin.LauncherActivity;
20 | import com.tochange.yang.floatladdin.R;
21 | import com.tochange.yang.lib.log;
22 |
23 | public class MainView extends View
24 | {
25 |
26 | private static final int HORIZONTAL_SPLIT = 40;
27 |
28 | private static final int VERTICAL_SPLIT = 40;
29 |
30 | private Bitmap mBitmap;
31 |
32 | private Paint mPaint;
33 |
34 | private float[] mInhalePoint;
35 |
36 | private SettingLayoutActivity mMainActivity;
37 |
38 | private boolean clearCanvas = true;
39 |
40 | private AladdinDrawGrid mAladdinDrawGrid;
41 |
42 | public MainView(Context context, AttributeSet attrs)
43 | {
44 | super(context, attrs);
45 | mPaint = new Paint();
46 | mInhalePoint = new float[] { 0, 0 };
47 | mAladdinDrawGrid = new AladdinDrawGrid(HORIZONTAL_SPLIT, VERTICAL_SPLIT);
48 | }
49 |
50 | @Override
51 | public boolean onTouchEvent(MotionEvent event)
52 | {
53 | return true;
54 | }
55 |
56 | @Override
57 | protected void onSizeChanged(int w, int h, int oldw, int oldh)
58 | {
59 | super.onSizeChanged(w, h, oldw, oldh);
60 | log.e("");
61 | buildPaths(w, h);
62 | // not need original image,yangxj@20140723
63 | // float bitmapWidth = mBitmap.getWidth();
64 | // float bitmapHeight = mBitmap.getHeight();
65 | // mAladdinDrawGrid.buildMeshes(bitmapWidth, bitmapHeight);
66 | }
67 |
68 | private void buildPaths(float endX, float endY)
69 | {
70 | mInhalePoint[0] = endX;
71 | mInhalePoint[1] = endY;
72 | mAladdinDrawGrid.buildPaths(endX, endY);
73 | }
74 |
75 | private boolean clearCanvas(Canvas canvas)
76 | {
77 | Paint paint = new Paint();
78 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
79 | canvas.drawPaint(paint);
80 | paint.setXfermode(new PorterDuffXfermode(Mode.SRC));
81 | log.e("clearing canvas");
82 | return true;
83 | }
84 |
85 | public boolean startAnimation(boolean reverse,
86 | SettingLayoutActivity mainActivity)
87 | {
88 | if (mainActivity != null)
89 | mMainActivity = mainActivity;
90 | log.e("will clear canvas");
91 | clearCanvas = true;
92 | startAnimationImp(reverse);
93 | return true;
94 | }
95 |
96 | private void startAnimationImp(boolean reverse)
97 | {
98 | Animation anim = this.getAnimation();
99 | if (null != anim && !anim.hasEnded())
100 | return;
101 | final AladdinAnimation animation = new AladdinAnimation(0,
102 | VERTICAL_SPLIT + 1, reverse,
103 | new AladdinAnimation.IAnimationUpdateListener() {
104 | @Override
105 | public void onAnimUpdate(int index)
106 | {
107 | log.e("build-" + (index) + "");
108 | mAladdinDrawGrid.buildMeshes(index);
109 | invalidate();
110 | }
111 | });
112 |
113 | if (null != animation)
114 | {
115 | setAnimationTimeAndListener(animation);
116 | startAnimation(animation);
117 | }
118 | }
119 |
120 | @Override
121 | protected void onDraw(Canvas canvas)
122 | {
123 | if (clearCanvas && clearCanvas(canvas))
124 | {
125 | clearCanvas = false;
126 | return;
127 | }
128 | log.e("");
129 | canvas.drawBitmapMesh(mBitmap, mAladdinDrawGrid.getWidth(),
130 | mAladdinDrawGrid.getHeight(), mAladdinDrawGrid.getVertices(),
131 | 0, null, 0, mPaint);
132 |
133 | if (LauncherActivity.DEBUG_MODE)
134 | {
135 | setTextAndPointPaint(mPaint);
136 | canvas.drawTextOnPath(
137 | this.getResources().getString(R.string.path_words),
138 | mAladdinDrawGrid.getPaths()[1], 0, 0, mPaint);
139 | canvas.drawPoints(mAladdinDrawGrid.getVertices(), mPaint);
140 |
141 | setPathPaint(mPaint);
142 | Path[] paths = mAladdinDrawGrid.getPaths();
143 | for (Path path : paths)
144 | canvas.drawPath(path, mPaint);
145 | }
146 | }
147 |
148 | private void setPathPaint(Paint mPaint2)
149 | {
150 | mPaint.setColor(Color.CYAN);
151 | mPaint.setStrokeWidth(1);
152 | mPaint.setAntiAlias(true);
153 | mPaint.setStyle(Paint.Style.STROKE);
154 |
155 | }
156 |
157 | private void setTextAndPointPaint(Paint mPaint)
158 | {
159 | mPaint.setColor(Color.MAGENTA);
160 | mPaint.setStyle(Paint.Style.FILL);
161 | mPaint.setTextAlign(Paint.Align.CENTER);
162 | mPaint.setTextSize(25);
163 |
164 | }
165 |
166 | public void setBitmap(Bitmap bitmap)
167 | {
168 | if (bitmap != null)
169 | {
170 | mBitmap = bitmap;
171 | mAladdinDrawGrid.setBitmapSize(mBitmap.getWidth(),
172 | mBitmap.getHeight());
173 | }
174 | }
175 |
176 | private void setAnimationTimeAndListener(AladdinAnimation animation)
177 | {
178 | animation
179 | .setDuration(LauncherActivity.DEBUG_MODE ? LauncherActivity.ANIMATION_TIME_LONG
180 | : LauncherActivity.ANIMATION_TIME_SHORT);
181 | animation.setAnimationListener(new AnimationListener() {
182 |
183 | @Override
184 | public void onAnimationStart(Animation animation)
185 | {
186 | }
187 |
188 | @Override
189 | public void onAnimationRepeat(Animation animation)
190 | {
191 | }
192 |
193 | @Override
194 | public void onAnimationEnd(Animation animation)
195 | {
196 | if (mMainActivity != null)
197 | mMainActivity.finish();
198 | }
199 | });
200 | }
201 | }
--------------------------------------------------------------------------------
/Aladdin/src/com/tochange/yang/floatladdin/aladdin/SettingLayoutActivity.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.aladdin;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.graphics.Bitmap;
6 | import android.os.Bundle;
7 | import android.widget.LinearLayout.LayoutParams;
8 | import android.widget.TextView;
9 |
10 | import com.tochange.yang.floatladdin.LauncherActivity;
11 | import com.tochange.yang.floatladdin.R;
12 |
13 | public class SettingLayoutActivity extends Activity
14 | {
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState)
18 | {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.aladdin_view);
21 |
22 | final MainView mainView = (MainView) findViewById(R.id.view);
23 | setParameter(mainView);
24 | mainView.startAnimation(false, this);
25 | }
26 |
27 | private void setParameter(MainView mainView)
28 | {
29 | Intent i = getIntent();
30 |
31 | setLeftMargin(i.getIntExtra(LauncherActivity.KEY_X, -1));
32 | setTopMargin(mainView, i.getIntExtra(LauncherActivity.KEY_Y, -1));
33 | mainView.setBitmap((Bitmap) (i
34 | .getParcelableExtra(LauncherActivity.KEY_IMAGE)));
35 | }
36 |
37 | private void setTopMargin(MainView mainView, int y)
38 | {
39 | LayoutParams lp = (LayoutParams) mainView.getLayoutParams();
40 | // lp.leftMargin = x;
41 | lp.topMargin = y - LauncherActivity.MAGIC_VERTICAL;
42 | mainView.setLayoutParams(lp);
43 |
44 | }
45 |
46 | private void setLeftMargin(int x)
47 | {
48 | TextView tv = (TextView) findViewById(R.id.space_h);
49 | LayoutParams lpp = (LayoutParams) tv.getLayoutParams();
50 | lpp.width = x;
51 | lpp.height = 1;
52 | tv.setLayoutParams(lpp);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Aladdin/src/com/tochange/yang/floatladdin/floatwindow/FloatWindowCustomView.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.floatwindow;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.graphics.Color;
6 | import android.view.LayoutInflater;
7 | import android.view.MotionEvent;
8 | import android.view.View;
9 | import android.view.WindowManager;
10 | import android.view.animation.Animation;
11 | import android.view.animation.ScaleAnimation;
12 | import android.widget.EditText;
13 | import android.widget.ImageView;
14 | import android.widget.LinearLayout;
15 | import android.widget.TextView;
16 | import android.widget.Toast;
17 |
18 | import com.tochange.yang.floatladdin.LauncherActivity;
19 | import com.tochange.yang.floatladdin.R;
20 | import com.tochange.yang.floatladdin.aladdin.SettingLayoutActivity;
21 | import com.tochange.yang.lib.ui.BadgeView;
22 | import com.tochange.yang.lib.ui.Graphics;
23 | import com.tochange.yang.lib.ui.ScreenLib;
24 | import com.tochange.yang.lib.Utils;
25 | import com.tochange.yang.lib.log;
26 |
27 | public class FloatWindowCustomView extends LinearLayout
28 | {
29 | public static int windowViewWidth;
30 |
31 | public static int windowViewHeight;
32 |
33 | private WindowManager windowManager;
34 |
35 | private LinearLayout customWindowLayout;
36 |
37 | private WindowManager.LayoutParams mParams;
38 |
39 | private float xInScreen;
40 |
41 | private float yInScreen;
42 |
43 | private float xInView;
44 |
45 | private float yInView;
46 |
47 | private Context mContext;
48 |
49 | private OnClickListener mGetFocusClickListenrt = new OnClickListener() {
50 |
51 | @Override
52 | public void onClick(View v)
53 | {
54 | v.setFocusable(true);
55 | v.setFocusableInTouchMode(true);
56 | }
57 | };
58 |
59 | public FloatWindowCustomView(final Context context)
60 | {
61 | super(context);
62 | mContext = context;
63 | windowManager = (WindowManager) context
64 | .getSystemService(Context.WINDOW_SERVICE);
65 | LayoutInflater.from(context)
66 | .inflate(R.layout.float_window_layout, this);
67 | customWindowLayout = (LinearLayout) findViewById(R.id.custom_layout);
68 | windowViewWidth = customWindowLayout.getLayoutParams().width;
69 | windowViewHeight = customWindowLayout.getLayoutParams().height;
70 |
71 | final int[] wh = getCustomWindowLayoutWidthAndHeight(customWindowLayout);
72 | setBadgeView(context, wh);
73 | setPercentView(context);
74 | setEditText(context);
75 | }
76 |
77 | private void setEditText(final Context context)
78 | {
79 | final EditText et = (EditText) findViewById(R.id.edittext);
80 | et.setOnFocusChangeListener(new OnFocusChangeListener() {
81 |
82 | @Override
83 | public void onFocusChange(View v, boolean hasFocus)
84 | {
85 | android.view.WindowManager.LayoutParams lp = (android.view.WindowManager.LayoutParams) FloatWindowCustomView.this
86 | .getLayoutParams();
87 | String m;
88 | if (hasFocus)
89 | {
90 | m = "can";
91 | lp.flags = 32;
92 | }
93 | else
94 | {
95 | m = "cann't";
96 | lp.flags = 32 | 8;
97 | }
98 | FloatWindowCustomView.this.setLayoutParams(lp);
99 | Toast.makeText(context, m + " input.", 5000).show();
100 | windowManager.updateViewLayout(FloatWindowCustomView.this, mParams);
101 | }
102 | });
103 | et.setOnClickListener(mGetFocusClickListenrt);
104 | }
105 |
106 | private void setPercentView(Context context)
107 | {
108 | final TextView percentView = (TextView) findViewById(R.id.percent);
109 | percentView.setText(FloatWindowManager.getUsedPercentValue(context));
110 | percentView.setOnClickListener(mGetFocusClickListenrt);
111 | }
112 |
113 | private void setBadgeView(final Context context, final int[] wh)
114 | {
115 | final ImageView view = (ImageView) findViewById(R.id.close);
116 | final BadgeView badge = new BadgeView(context, view);
117 | badge.setBadgePosition(wh[0] - view.getMeasuredHeight(), 0, 0, 0)
118 | .setBadgeBackgroundShape(BadgeView.BACKGROUND_SHAPE_RECTANGLE)
119 | .setText(" × ");
120 | badge.setTextSize(25);
121 | badge.setOnClickListener(new View.OnClickListener() {
122 | public void onClick(View v)
123 | {
124 | Intent i = new Intent(context, SettingLayoutActivity.class);
125 | i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
126 |
127 | int[] position = getPosition(wh);
128 | i.putExtra(LauncherActivity.KEY_X, position[0]);
129 | i.putExtra(LauncherActivity.KEY_Y, position[1]);
130 | i.putExtra(LauncherActivity.KEY_IMAGE,
131 | Graphics.getBitmapFromView(FloatWindowCustomView.this));
132 | setButtonPressedEffect(badge);
133 | context.startActivity(i);
134 | }
135 |
136 | private void setButtonPressedEffect(BadgeView badge)
137 | {
138 | Animation a = new ScaleAnimation(1, 1.2F, 1, 1.2F,
139 | Animation.RELATIVE_TO_SELF, 0.8f,
140 | Animation.RELATIVE_TO_SELF, 0.8f);
141 | a.setDuration(100);
142 | badge.setBackgroundColor(Color.parseColor("#c00000"));
143 | badge.startAnimation(a);
144 | // if (!LauncherActivity.DEBUG_MODE)
145 | // Utils.vibrate(context);
146 | }
147 |
148 | private int[] getPosition(int[] wh)
149 | {
150 | int maxX = windowManager.getDefaultDisplay().getWidth() - wh[0];
151 | int x = mParams.x > maxX ? maxX : mParams.x;
152 |
153 | int maxY = windowManager.getDefaultDisplay().getHeight()
154 | - wh[1];
155 | int magic = LauncherActivity.IS_TABLTE ? 0 : 2;
156 | int y = mParams.y > maxY ? maxY - magic
157 | * LauncherActivity.MAGIC_VERTICAL : mParams.y;
158 | y = y > 0 ? y : 0;
159 |
160 | int[] ret = { x, y };
161 | return ret;
162 | }
163 | });
164 | badge.show();
165 |
166 | }
167 |
168 | private int[] getCustomWindowLayoutWidthAndHeight(
169 | LinearLayout customWindowLayout2)
170 | {
171 | int widthMeasureSpec, heightMeasureSpec;
172 | widthMeasureSpec = heightMeasureSpec = View.MeasureSpec
173 | .makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
174 | customWindowLayout.measure(widthMeasureSpec, heightMeasureSpec);
175 | int w = customWindowLayout.getMeasuredWidth();
176 | int h = customWindowLayout.getMeasuredHeight();
177 | int[] ret = { w, h };
178 | return ret;
179 | }
180 |
181 | @Override
182 | public boolean onTouchEvent(MotionEvent event)
183 | {
184 | switch (event.getAction())
185 | {
186 |
187 | case MotionEvent.ACTION_DOWN:
188 | xInView = event.getX();
189 | yInView = event.getY();
190 | break;
191 | case MotionEvent.ACTION_MOVE:
192 | xInScreen = event.getRawX();
193 | // if pad,then status bar will be in the bottom,can not minus
194 | // status bar height,but pad not ensure status bar in the bottom
195 | yInScreen = LauncherActivity.IS_TABLTE ? event.getRawY()
196 | : event.getRawY() - ScreenLib.getStatusBarHeight(mContext);
197 | updateViewStatus();
198 | updateViewPosition();
199 | break;
200 | case MotionEvent.ACTION_UP:
201 | break;
202 | default:
203 | break;
204 | }
205 | return true;
206 | }
207 |
208 | public void setParams(WindowManager.LayoutParams params)
209 | {
210 | mParams = params;
211 | }
212 |
213 | private void updateViewPosition()
214 | {
215 | mParams.x = (int) (xInScreen - xInView);
216 | mParams.y = (int) (yInScreen - yInView);
217 | windowManager.updateViewLayout(this, mParams);
218 | }
219 |
220 | private void updateViewStatus()
221 | {
222 | mParams.width = windowViewWidth;
223 | mParams.height = windowViewHeight;
224 | windowManager.updateViewLayout(this, mParams);
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/Aladdin/src/com/tochange/yang/floatladdin/floatwindow/FloatWindowManager.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.floatwindow;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.FileReader;
5 | import java.io.IOException;
6 |
7 | import com.tochange.yang.floatladdin.R;
8 | import com.tochange.yang.lib.log;
9 |
10 |
11 | import android.app.ActivityManager;
12 | import android.content.Context;
13 | import android.graphics.PixelFormat;
14 | import android.view.Gravity;
15 | import android.view.WindowManager;
16 | import android.view.WindowManager.LayoutParams;
17 | import android.widget.TextView;
18 |
19 | public class FloatWindowManager {
20 |
21 | private static LayoutParams customWindowParams;
22 | private static FloatWindowCustomView customWindow;
23 | private static WindowManager mWindowManager;
24 | private static ActivityManager mActivityManager;
25 |
26 | public static void createCustomWindow(Context context) {
27 | WindowManager windowManager = getWindowManager(context);
28 | int screenWidth = windowManager.getDefaultDisplay().getWidth();
29 | int screenHeight = windowManager.getDefaultDisplay().getHeight();
30 | if (customWindow == null) {
31 | customWindow = new FloatWindowCustomView(context);
32 | if (customWindowParams == null) {
33 | customWindowParams = new LayoutParams();
34 | customWindowParams.type = LayoutParams.TYPE_SYSTEM_ALERT;
35 | customWindowParams.format = PixelFormat.RGBA_8888;
36 | customWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
37 | | LayoutParams.FLAG_NOT_FOCUSABLE;
38 | customWindowParams.gravity = Gravity.LEFT | Gravity.TOP;
39 | customWindowParams.width = FloatWindowCustomView.windowViewWidth;
40 | customWindowParams.height = FloatWindowCustomView.windowViewHeight;
41 | customWindowParams.x = screenWidth / 4;
42 | customWindowParams.y = screenHeight / 3;
43 | }
44 | customWindow.setParams(customWindowParams);
45 | windowManager.addView(customWindow, customWindowParams);
46 | }
47 | }
48 |
49 | public static void removeCustomWindow(Context context) {
50 | if (customWindow != null) {
51 | WindowManager windowManager = getWindowManager(context);
52 | windowManager.removeView(customWindow);
53 | customWindow = null;
54 | }
55 | }
56 |
57 | public static void updateUsedPercent(Context context) {
58 | if (customWindow != null) {
59 | TextView percentView = (TextView) customWindow
60 | .findViewById(R.id.percent);
61 | percentView.setText(getUsedPercentValue(context));
62 | }
63 | }
64 |
65 | public static boolean isWindowShowing() {
66 | return customWindow != null;
67 | }
68 |
69 | private static WindowManager getWindowManager(Context context) {
70 | if (mWindowManager == null) {
71 | mWindowManager = (WindowManager) context
72 | .getSystemService(Context.WINDOW_SERVICE);
73 | }
74 | return mWindowManager;
75 | }
76 |
77 | private static ActivityManager getActivityManager(Context context) {
78 | if (mActivityManager == null) {
79 | mActivityManager = (ActivityManager) context
80 | .getSystemService(Context.ACTIVITY_SERVICE);
81 | }
82 | return mActivityManager;
83 | }
84 |
85 | public static String getUsedPercentValue(Context context) {
86 | String dir = "/proc/meminfo";
87 | try {
88 | FileReader fr = new FileReader(dir);
89 | BufferedReader br = new BufferedReader(fr, 2048);
90 | String memoryLine = br.readLine();
91 | String subMemoryLine = memoryLine.substring(memoryLine
92 | .indexOf("MemTotal:"));
93 | br.close();
94 | long totalMemorySize = Integer.parseInt(subMemoryLine.replaceAll(
95 | "\\D+", ""));
96 | long availableSize = getAvailableMemory(context) / 1024;
97 | int percent = (int) ((totalMemorySize - availableSize)
98 | / (float) totalMemorySize * 100);
99 | return percent + "%";
100 | } catch (IOException e) {
101 | e.printStackTrace();
102 | }
103 | return "floating windows";
104 | }
105 |
106 | private static long getAvailableMemory(Context context) {
107 | ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
108 | getActivityManager(context).getMemoryInfo(mi);
109 | return mi.availMem;
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/Aladdin/src/com/tochange/yang/floatladdin/floatwindow/FloatWindowService.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.floatwindow;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Timer;
6 | import java.util.TimerTask;
7 |
8 | import android.app.ActivityManager;
9 | import android.app.ActivityManager.RunningTaskInfo;
10 | import android.app.Service;
11 | import android.content.Context;
12 | import android.content.Intent;
13 | import android.content.pm.PackageManager;
14 | import android.content.pm.ResolveInfo;
15 | import android.os.Handler;
16 | import android.os.IBinder;
17 |
18 | public class FloatWindowService extends Service {
19 |
20 | private Handler handler = new Handler();
21 | private Timer timer;
22 |
23 | @Override
24 | public IBinder onBind(Intent intent) {
25 | return null;
26 | }
27 |
28 | @Override
29 | public int onStartCommand(Intent intent, int flags, int startId) {
30 | // 开启定时器,每隔0.5秒刷新一次
31 | if (timer == null) {
32 | timer = new Timer();
33 | timer.scheduleAtFixedRate(new RefreshTask(), 0, 500);
34 | }
35 | return super.onStartCommand(intent, flags, startId);
36 | }
37 |
38 | @Override
39 | public void onDestroy() {
40 | super.onDestroy();
41 | timer.cancel();
42 | timer = null;
43 | }
44 |
45 | class RefreshTask extends TimerTask {
46 |
47 | @Override
48 | public void run() {
49 | // 当前界面是桌面,且没有悬浮窗显示,则创建悬浮窗。
50 | if (isHome() && !FloatWindowManager.isWindowShowing()) {
51 | handler.post(new Runnable() {
52 | @Override
53 | public void run() {
54 | FloatWindowManager.createCustomWindow(getApplicationContext());
55 | }
56 | });
57 | }
58 | // 当前界面不是桌面,且有悬浮窗显示,则移除悬浮窗。
59 | else if (!isHome() && FloatWindowManager.isWindowShowing()) {
60 | handler.post(new Runnable() {
61 | @Override
62 | public void run() {
63 | FloatWindowManager.removeCustomWindow(getApplicationContext());
64 | }
65 | });
66 | }
67 | // 当前界面是桌面,且有悬浮窗显示,则更新内存数据。
68 | else if (isHome() && FloatWindowManager.isWindowShowing()) {
69 | handler.post(new Runnable() {
70 | @Override
71 | public void run() {
72 | FloatWindowManager.updateUsedPercent(getApplicationContext());
73 | }
74 | });
75 | }
76 | }
77 |
78 | }
79 |
80 | /**
81 | * 判断当前界面是否是桌面
82 | */
83 | private boolean isHome() {
84 | ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
85 | List rti = mActivityManager.getRunningTasks(1);
86 | return getHomes().contains(rti.get(0).topActivity.getPackageName());
87 | }
88 |
89 | /**
90 | * 获得属于桌面的应用的应用包名称
91 | *
92 | * @return 返回包含所有包名的字符串列表
93 | */
94 | private List getHomes() {
95 | List names = new ArrayList();
96 | PackageManager packageManager = this.getPackageManager();
97 | Intent intent = new Intent(Intent.ACTION_MAIN);
98 | intent.addCategory(Intent.CATEGORY_HOME);
99 | List resolveInfo = packageManager.queryIntentActivities(intent,
100 | PackageManager.MATCH_DEFAULT_ONLY);
101 | for (ResolveInfo ri : resolveInfo) {
102 | names.add(ri.activityInfo.packageName);
103 | }
104 | return names;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/FloatWindowAladdin.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tochange/Aladdin/51c2708874aa4b66be596e2bfde966d79897c997/FloatWindowAladdin.apk
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | NotActivityFloatWindowAladdin
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | #Wed May 28 15:12:38 CST 2014
2 | eclipse.preferences.version=1
3 | encoding/=UTF-8
4 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-8
15 | android.library.reference.1=../../../../lib/lib.git/trunk
16 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/res/drawable-ldpi/bg_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tochange/Aladdin/51c2708874aa4b66be596e2bfde966d79897c997/NoActivityAladdin/Aladdin/res/drawable-ldpi/bg_small.png
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/res/drawable-ldpi/pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tochange/Aladdin/51c2708874aa4b66be596e2bfde966d79897c997/NoActivityAladdin/Aladdin/res/drawable-ldpi/pic.png
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/res/layout/aladdin_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
17 |
18 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/res/layout/custom_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
21 |
22 |
29 |
30 |
39 |
40 |
45 |
46 |
47 |
55 |
56 |
63 |
64 |
73 |
74 |
75 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/res/layout/float_window_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Aladdin
5 | Settings
6 | Hello world!
7 | 沿此动画
8 |
9 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/src/com/tochange/yang/floatladdin/LauncherActivity.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 |
7 | import com.tochange.yang.floatladdin.floatwindow.FloatWindowService;
8 | import com.tochange.yang.lib.ui.ScreenLib;
9 |
10 | public class LauncherActivity extends Activity {
11 |
12 | public static final String KEY_X = "x";
13 | public static final String KEY_Y = "y";
14 | public static final String KEY_IMAGE = "image";
15 | public static final String DELETED_BUTTON_TEXT_CONTENT = " × ";
16 | public static final int DELETED_BUTTON_TEXT_SIZE = 25 ;
17 | public static final int VERTICAL_OFFSET = 15;
18 | public static final int ANIMATION_TIME_SHORT = 600;//600
19 | public static final int ANIMATION_TIME_LONG = 5000;//2000
20 | public static final int ANIMATION_SPLIT_HORIZONTAL = 40;
21 | public static final int ANIMATION_SPLIT_VERTICAL = 40;
22 | public static final int BASE_SCREEN_WIDTH = 480;
23 | public static final float BASE_SCREEN_DENSITY = 1.5F;
24 |
25 | public static boolean DEBUG_MODE;
26 | public static boolean IS_TABLTE;
27 | public static int ANIMATION_TIME;
28 | public static int SCREEN_WIDTH;
29 | public static int SCREEN_HEIGHT;
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | Intent intent = new Intent(LauncherActivity.this, FloatWindowService.class);
35 | startService(intent);
36 | if(ScreenLib.isTabletDevice(this)){
37 | IS_TABLTE = true;
38 | }
39 | ANIMATION_TIME = DEBUG_MODE?ANIMATION_TIME_LONG:ANIMATION_TIME_SHORT;
40 | finish();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/src/com/tochange/yang/floatladdin/aladdin/AbstractDrawGrid.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.aladdin;
2 |
3 | import com.tochange.yang.floatladdin.LauncherActivity;
4 |
5 | //import com.tochange.yang.lib.log;
6 |
7 | public abstract class AbstractDrawGrid
8 | {
9 |
10 | protected int mHorizontalSplit;
11 |
12 | protected int mVerticalSplit;
13 |
14 | protected int mBmpWidth = -1;
15 |
16 | protected int mBmpHeight = -1;
17 |
18 | protected final float[] mVertices;
19 |
20 | public AbstractDrawGrid(int width, int height)
21 | {
22 | mHorizontalSplit = width;
23 | mVerticalSplit = height;
24 | mVertices = new float[(mHorizontalSplit + 1) * (mVerticalSplit + 1) * 2];
25 | }
26 |
27 | public float[] getVertices()
28 | {
29 | return mVertices;
30 | }
31 |
32 | public int getWidth()
33 | {
34 | return mHorizontalSplit;
35 | }
36 |
37 | public int getHeight()
38 | {
39 | return mVerticalSplit;
40 | }
41 |
42 | public static void setXY(float[] array, int index, float x, float y)
43 | {
44 | array[index * 2 + 0] = x;
45 | array[index * 2 + 1] = y;
46 | }
47 |
48 | public void setBitmapSize(int w, int h)
49 | {
50 | mBmpWidth = w;
51 | mBmpHeight = h;
52 | }
53 |
54 | public abstract void buildPaths(float endX, float endY);
55 |
56 | public abstract void buildMeshes(int index);
57 |
58 | public void buildMeshes(float w, float h)
59 | {
60 | int index = 0;
61 | for (int y = 0; y <= mVerticalSplit; y++)
62 | {
63 | float fy = y * h / mVerticalSplit + LauncherActivity.VERTICAL_OFFSET;
64 | for (int x = 0; x <= mHorizontalSplit; x++)
65 | {
66 | float fx = x * w / mHorizontalSplit;
67 | setXY(mVertices, index, fx, fy);
68 | index++;
69 | }
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/src/com/tochange/yang/floatladdin/aladdin/AladdinAnimation.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.aladdin;
2 |
3 | import com.tochange.yang.lib.log;
4 |
5 | import android.view.animation.Animation;
6 | import android.view.animation.Interpolator;
7 | import android.view.animation.Transformation;
8 |
9 | public class AladdinAnimation extends Animation
10 | {
11 |
12 | public interface IAnimationUpdateListener
13 | {
14 | public void onAnimUpdate(int index);
15 | }
16 |
17 | private int mFromIndex;
18 |
19 | private int mEndIndex;
20 |
21 | private boolean mReverse;
22 |
23 | private IAnimationUpdateListener mListener;
24 |
25 | public AladdinAnimation(int fromIndex, int endIndex, boolean reverse,
26 | IAnimationUpdateListener listener)
27 | {
28 | mFromIndex = fromIndex;
29 | mEndIndex = endIndex;
30 | mReverse = reverse;
31 | mListener = listener;
32 | }
33 |
34 | public boolean getTransformation(long currentTime,
35 | Transformation outTransformation)
36 | {
37 | return super.getTransformation(currentTime, outTransformation);
38 | }
39 |
40 | // not -1 but 0,because it will generate plenty of 0.
41 | int lastTimeIndex = 0;
42 |
43 | @Override
44 | protected void applyTransformation(float interpolatedTime, Transformation t)
45 | {
46 | Interpolator interpolator = this.getInterpolator();
47 | if (null != interpolator)
48 | {
49 | float value = interpolator.getInterpolation(interpolatedTime);
50 | interpolatedTime = value;
51 | }
52 |
53 | if (mReverse)
54 | interpolatedTime = 1.0f - interpolatedTime;
55 |
56 | int currentIndex = (int) (mFromIndex + (mEndIndex - mFromIndex)
57 | * interpolatedTime);
58 | if (currentIndex == lastTimeIndex)
59 | return;
60 | lastTimeIndex = currentIndex;
61 |
62 | if (null != mListener)
63 | mListener.onAnimUpdate(currentIndex);
64 | }
65 | }
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/src/com/tochange/yang/floatladdin/aladdin/AladdinDrawGrid.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.aladdin;
2 |
3 | import com.tochange.yang.floatladdin.LauncherActivity;
4 | import com.tochange.yang.lib.log;
5 |
6 | import android.graphics.Path;
7 | import android.graphics.PathMeasure;
8 |
9 | public class AladdinDrawGrid extends AbstractDrawGrid
10 | {
11 | private Path mFirstPath;
12 |
13 | private Path mSecondPath;
14 |
15 | private PathMeasure mFirstPathMeasure;
16 |
17 | private PathMeasure mSecondPathMeasure;
18 |
19 | public AladdinDrawGrid(int width, int height)
20 | {
21 | super(width, height);
22 | // log.e("");
23 | mFirstPath = new Path();
24 | mSecondPath = new Path();
25 | mFirstPathMeasure = new PathMeasure();
26 | mSecondPathMeasure = new PathMeasure();
27 | }
28 |
29 | @Override
30 | public void buildPaths(float endX, float endY)
31 | {
32 |
33 | if (mBmpWidth <= 0 || mBmpHeight <= 0)
34 | {
35 | throw new IllegalArgumentException(
36 | "Bitmap size must be > 0, did you call setBitmapSize(int, int) method?");
37 | }
38 | mFirstPathMeasure.setPath(mFirstPath, false);
39 | mSecondPathMeasure.setPath(mSecondPath, false);
40 |
41 | float w = mBmpWidth;
42 | float h = mBmpHeight;
43 |
44 | mFirstPath.reset();
45 | mSecondPath.reset();
46 |
47 | mFirstPath.moveTo(0, LauncherActivity.VERTICAL_OFFSET);// start point of bezier
48 | mSecondPath.moveTo(w, LauncherActivity.VERTICAL_OFFSET);
49 | // mFirstPath.lineTo(0, h + VERTICAL_OFFSET);//line to the position
50 | // mSecondPath.lineTo(w, h + VERTICAL_OFFSET);
51 |
52 | mFirstPath.cubicTo(0, 6 * (endY + LauncherActivity.VERTICAL_OFFSET) / 12, endX / 2 + 30,
53 | 5 * (endY + LauncherActivity.VERTICAL_OFFSET) / 12, endX - 30, endY);
54 | mSecondPath.cubicTo(endX / 2, (endY + LauncherActivity.VERTICAL_OFFSET) / 4, endX,
55 | 2 * (endY + LauncherActivity.VERTICAL_OFFSET) / 3, endX - 10, endY);
56 | }
57 |
58 | @Override
59 | public void buildMeshes(int timeIndex)
60 | {
61 |
62 | if (mBmpWidth <= 0 || mBmpHeight <= 0)
63 | {
64 | throw new IllegalArgumentException(
65 | "Bitmap size must be > 0, did you call setBitmapSize(int, int) method?");
66 | }
67 | mFirstPathMeasure.setPath(mFirstPath, false);
68 | mSecondPathMeasure.setPath(mSecondPath, false);
69 |
70 | int index = 0;
71 | float[] pos1 = { 0.0f, 0.0f };
72 | float[] pos2 = { 0.0f, 0.0f };
73 |
74 | // all length of the curve
75 | float firstLen = mFirstPathMeasure.getLength();
76 | float secondLen = mSecondPathMeasure.getLength();
77 |
78 | float len1 = firstLen / mVerticalSplit;
79 | float len2 = secondLen / mVerticalSplit;
80 |
81 | float firstPointDist = timeIndex * len1;
82 | float secondPointDist = timeIndex * len2;
83 | float height = mBmpHeight;
84 |
85 | mFirstPathMeasure.getPosTan(firstPointDist, pos1, null);
86 | mFirstPathMeasure.getPosTan(firstPointDist + height, pos2, null);
87 |
88 | float x1 = pos1[0];
89 | float x2 = pos2[0];
90 | float y1 = pos1[1];
91 | float y2 = pos2[1];
92 | float firstDist = (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2)
93 | * (y1 - y2));
94 | float firstSplitDist = firstDist / mVerticalSplit;
95 |
96 | mSecondPathMeasure.getPosTan(secondPointDist, pos1, null);
97 | mSecondPathMeasure.getPosTan(secondPointDist + height, pos2, null);
98 | x1 = pos1[0];
99 | x2 = pos2[0];
100 | y1 = pos1[1];
101 | y2 = pos2[1];
102 |
103 | float secondDist = (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2)
104 | * (y1 - y2));
105 | float secondSplitDist = secondDist / mVerticalSplit;
106 |
107 | for (int y = 0; y <= mVerticalSplit; y++)
108 | {
109 | mFirstPathMeasure.getPosTan(y * firstSplitDist + firstPointDist,
110 | pos1, null);
111 | mSecondPathMeasure.getPosTan(y * secondSplitDist + secondPointDist,
112 | pos2, null);
113 |
114 | float fx1 = pos1[0];
115 | float fx2 = pos2[0];
116 | float fy1 = pos1[1];
117 | float fy2 = pos2[1];
118 |
119 | float dy = fy2 - fy1;
120 | float dx = fx2 - fx1;
121 |
122 | // horizon,mHorizontalSplit pixels
123 | for (int x = 0; x <= mHorizontalSplit; x++, index++)
124 | {
125 | float fx = dx * x / mHorizontalSplit;
126 | float fy = dy * x / mHorizontalSplit;
127 | mVertices[index * 2 + 0] = fx + fx1;
128 | mVertices[index * 2 + 1] = fy + fy1;
129 | }
130 | }
131 | }
132 |
133 | public Path[] getPaths()
134 | {
135 | return new Path[] { mFirstPath, mSecondPath };
136 | }
137 | }
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/src/com/tochange/yang/floatladdin/aladdin/MainView.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.aladdin;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.Path;
9 | import android.graphics.PorterDuff;
10 | import android.graphics.PorterDuff.Mode;
11 | import android.graphics.PorterDuffXfermode;
12 | import android.util.AttributeSet;
13 | import android.view.MotionEvent;
14 | import android.view.View;
15 | import android.view.animation.AlphaAnimation;
16 | import android.view.animation.Animation;
17 | import android.view.animation.Animation.AnimationListener;
18 | import android.view.animation.AnimationSet;
19 |
20 | import com.tochange.yang.floatladdin.LauncherActivity;
21 | import com.tochange.yang.floatladdin.R;
22 | import com.tochange.yang.floatladdin.floatwindow.FloatWindowService;
23 | import com.tochange.yang.lib.log;
24 |
25 | public class MainView extends View {
26 |
27 | private Bitmap mBitmap;
28 |
29 | private Paint mPaint;
30 |
31 | private float[] mInhalePoint;
32 |
33 | private boolean clearCanvas = true;
34 |
35 | private AladdinDrawGrid mAladdinDrawGrid;
36 |
37 | public MainView(Context context, AttributeSet attrs) {
38 | super(context, attrs);
39 | mPaint = new Paint();
40 | mInhalePoint = new float[] { 0, 0 };
41 | mAladdinDrawGrid = new AladdinDrawGrid(LauncherActivity.ANIMATION_SPLIT_HORIZONTAL, LauncherActivity.ANIMATION_SPLIT_VERTICAL);
42 | }
43 |
44 | @Override
45 | public boolean onTouchEvent(MotionEvent event) {
46 | return true;
47 | }
48 |
49 | @Override
50 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
51 | super.onSizeChanged(w, h, oldw, oldh);
52 | log.d("");
53 | buildPaths(w, h);
54 | // not need to draw the original image,yangxj@20140723
55 | // float bitmapWidth = mBitmap.getWidth();
56 | // float bitmapHeight = mBitmap.getHeight();
57 | // mAladdinDrawGrid.buildMeshes(bitmapWidth, bitmapHeight);
58 | }
59 |
60 | private void buildPaths(float endX, float endY) {
61 | mInhalePoint[0] = endX;
62 | mInhalePoint[1] = endY;
63 | mAladdinDrawGrid.buildPaths(endX, endY);
64 | }
65 |
66 | private boolean clearCanvas(Canvas canvas) {
67 | log.d("clearing canvas.");
68 | Paint paint = new Paint();
69 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
70 | canvas.drawPaint(paint);
71 | paint.setXfermode(new PorterDuffXfermode(Mode.SRC));
72 | return true;
73 | }
74 |
75 | public boolean startAnimation(boolean reverse) {
76 | log.d("will clear canvas.");
77 | clearCanvas = true;
78 | invalidate();// add
79 | startAnimationImp(reverse);
80 | return true;
81 | }
82 |
83 | private void startAnimationImp(boolean reverse) {
84 | Animation anim = this.getAnimation();
85 | if (null != anim && !anim.hasEnded())
86 | return;
87 | AnimationSet animationSet = new AnimationSet(getContext(), null);
88 |
89 | final AladdinAnimation animation = new AladdinAnimation(0,
90 | LauncherActivity.ANIMATION_SPLIT_VERTICAL + 1, reverse,
91 | new AladdinAnimation.IAnimationUpdateListener() {
92 | @Override
93 | public void onAnimUpdate(int index) {
94 | // log.e("build-" + (index) + "");
95 | mAladdinDrawGrid.buildMeshes(index);
96 | invalidate();
97 | }
98 | });
99 |
100 | if (null != animation) {
101 | setAnimationTimeAndListener(animation);
102 | animationSet.addAnimation(getAlphaAnimation());
103 | animationSet.addAnimation(animation);
104 | startAnimation(animationSet);
105 | }
106 | }
107 |
108 | private Animation getAlphaAnimation() {
109 | Animation alphaAnimation = new AlphaAnimation(0, 1);
110 | alphaAnimation.setDuration(LauncherActivity.ANIMATION_TIME / 2);
111 | return alphaAnimation;
112 | }
113 |
114 | @Override
115 | protected void onDraw(Canvas canvas) {
116 | if (clearCanvas && clearCanvas(canvas)) {
117 | clearCanvas = false;
118 | return;
119 | }
120 | if (mBitmap == null && clearCanvas(canvas)) {
121 | return;
122 | }
123 | // log.e("");
124 | if (LauncherActivity.DEBUG_MODE) {
125 | setTextAndPointPaint(mPaint);
126 | canvas.drawTextOnPath(
127 | this.getResources().getString(R.string.path_words),
128 | mAladdinDrawGrid.getPaths()[1], 0, 0, mPaint);
129 | canvas.drawPoints(mAladdinDrawGrid.getVertices(), mPaint);
130 |
131 | setPathPaint(mPaint);
132 | Path[] paths = mAladdinDrawGrid.getPaths();
133 | for (Path path : paths)
134 | canvas.drawPath(path, mPaint);
135 | }
136 | canvas.drawBitmapMesh(mBitmap, mAladdinDrawGrid.getWidth(),
137 | mAladdinDrawGrid.getHeight(), mAladdinDrawGrid.getVertices(),
138 | 0, null, 0, mPaint);
139 | }
140 |
141 | private void setPathPaint(Paint mPaint2) {
142 | mPaint.setColor(Color.CYAN);
143 | mPaint.setStrokeWidth(1);
144 | mPaint.setAntiAlias(true);
145 | mPaint.setStyle(Paint.Style.STROKE);
146 |
147 | }
148 |
149 | private void setTextAndPointPaint(Paint mPaint) {
150 | mPaint.setColor(Color.MAGENTA);
151 | mPaint.setStyle(Paint.Style.FILL);
152 | mPaint.setTextAlign(Paint.Align.CENTER);
153 | mPaint.setTextSize(25);
154 |
155 | }
156 |
157 | public void setBitmap(Bitmap bitmap) {
158 | if (bitmap != null) {
159 | mBitmap = bitmap;
160 | mAladdinDrawGrid.setBitmapSize(mBitmap.getWidth(),
161 | mBitmap.getHeight());
162 | }
163 | }
164 |
165 | private void setAnimationTimeAndListener(AladdinAnimation animation) {
166 | animation
167 | .setDuration(LauncherActivity.DEBUG_MODE ? LauncherActivity.ANIMATION_TIME_LONG
168 | : LauncherActivity.ANIMATION_TIME_SHORT);
169 | animation.setAnimationListener(new AnimationListener() {
170 |
171 | @Override
172 | public void onAnimationStart(Animation animation) {
173 | }
174 |
175 | @Override
176 | public void onAnimationRepeat(Animation animation) {
177 | }
178 |
179 | @Override
180 | public void onAnimationEnd(Animation animation) {
181 | FloatWindowService.mFloatWindowService.onDestroy();
182 | System.exit(0);
183 | }
184 | });
185 | }
186 | }
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/src/com/tochange/yang/floatladdin/floatwindow/FloatWindowCustomView.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.floatwindow;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Color;
6 | import android.util.DisplayMetrics;
7 | import android.view.LayoutInflater;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 | import android.view.WindowManager;
11 | import android.view.animation.AlphaAnimation;
12 | import android.view.animation.Animation;
13 | import android.view.animation.Animation.AnimationListener;
14 | import android.view.animation.ScaleAnimation;
15 | import android.widget.ImageView;
16 | import android.widget.LinearLayout;
17 | import android.widget.TextView;
18 | import android.widget.Toast;
19 |
20 | import com.tochange.yang.floatladdin.LauncherActivity;
21 | import com.tochange.yang.floatladdin.R;
22 | import com.tochange.yang.floatladdin.aladdin.MainView;
23 | import com.tochange.yang.lib.ui.BadgeView;
24 | import com.tochange.yang.lib.ui.ClearEditText;
25 | import com.tochange.yang.lib.ui.ScreenLib;
26 | import com.tochange.yang.lib.ui.Graphics;
27 | import com.tochange.yang.lib.Utils;
28 | import com.tochange.yang.lib.log;
29 |
30 | public class FloatWindowCustomView extends LinearLayout
31 | {
32 | private WindowManager windowManager;
33 |
34 | private LinearLayout mCustomWindowLayout;
35 |
36 | private WindowManager.LayoutParams mParams;
37 |
38 | private float xInScreen;
39 |
40 | private float yInScreen;
41 |
42 | private float xInView;
43 |
44 | private float yInView;
45 |
46 | private ClearEditText mClearEditText;
47 |
48 | private Context mContext;
49 |
50 | private OnClickListener mGetFocusClickListenr = new OnClickListener() {
51 |
52 | @Override
53 | public void onClick(View v)
54 | {
55 | v.setFocusable(true);
56 | v.setFocusableInTouchMode(true);
57 | if (v.getId() == R.id.percent)
58 | {
59 | if (mClearEditText.getText().toString().trim().equals(""))
60 | mClearEditText.startAnimation(mClearEditText
61 | .getShakeAnimation(5));
62 | LauncherActivity.DEBUG_MODE = !LauncherActivity.DEBUG_MODE;
63 | }
64 | }
65 | };
66 |
67 | AnimationListener mAnimationListener = new AnimationListener() {
68 |
69 | @Override
70 | public void onAnimationStart(Animation animation)
71 | {
72 | }
73 |
74 | @Override
75 | public void onAnimationRepeat(Animation animation)
76 | {
77 | }
78 |
79 | @Override
80 | public void onAnimationEnd(Animation animation)
81 | {
82 | FloatWindowCustomView.this.removeAllViews();
83 | }
84 | };
85 |
86 | public FloatWindowCustomView(final Context context)
87 | {
88 | super(context);
89 | mContext = context;
90 | windowManager = (WindowManager) context
91 | .getSystemService(Context.WINDOW_SERVICE);
92 | LayoutInflater.from(context)
93 | .inflate(R.layout.float_window_layout, this);
94 | mCustomWindowLayout = (LinearLayout) findViewById(R.id.custom_layout);
95 | final int[] wh = getCustomWindowLayoutWidthAndHeight(mCustomWindowLayout);
96 | setBadgeView(context, wh);
97 | setPercentView(context);
98 | setEditText(context);
99 | }
100 |
101 | private void setEditText(final Context context)
102 | {
103 | mClearEditText = (ClearEditText) findViewById(R.id.edittext);
104 | mClearEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
105 |
106 | @Override
107 | public void onFocusChange(View v, boolean hasFocus)
108 | {
109 | android.view.WindowManager.LayoutParams lp = (android.view.WindowManager.LayoutParams) FloatWindowCustomView.this
110 | .getLayoutParams();
111 | String m;
112 | if (hasFocus)
113 | {
114 | m = "can";
115 | /*
116 | * LayoutParams.FLAG_NOT_TOUCH_MODAL |
117 | * LayoutParams.FLAG_NOT_FOCUSABLE |
118 | */
119 | lp.flags = 32 | 262144;
120 | }
121 | else
122 | {
123 | m = "cann't";
124 | /*
125 | * LayoutParams.FLAG_NOT_TOUCH_MODAL |
126 | * LayoutParams.FLAG_NOT_FOCUSABLE |
127 | * LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
128 | */
129 | lp.flags = 32 | 8 | 262144;
130 | }
131 | FloatWindowCustomView.this.setLayoutParams(lp);
132 | Toast.makeText(context, m + " input.", Toast.LENGTH_LONG)
133 | .show();
134 | windowManager.updateViewLayout(FloatWindowCustomView.this,
135 | mParams);
136 | mClearEditText.setOnFocusChangeListenerCallBack(v, hasFocus);
137 | }
138 | });
139 | mClearEditText.setOnClickListener(mGetFocusClickListenr);
140 | }
141 |
142 | private void setPercentView(Context context)
143 | {
144 | final TextView percentView = (TextView) findViewById(R.id.percent);
145 | percentView.setText(FloatWindowManager.getUsedPercentValue(context));
146 | percentView.setOnClickListener(mGetFocusClickListenr);
147 | }
148 |
149 | private void setBadgeView(final Context context, final int[] wh)
150 | {
151 | final ImageView view = (ImageView) findViewById(R.id.close);
152 | final BadgeView badge = new BadgeView(context, view);
153 | badge.setBadgePosition(wh[0] - view.getMeasuredHeight(), 0, 0, 0)
154 | .setBadgeBackgroundShape(BadgeView.BACKGROUND_SHAPE_RECTANGLE)
155 | .setText(LauncherActivity.DELETED_BUTTON_TEXT_CONTENT);
156 | badge.setTextSize(LauncherActivity.DELETED_BUTTON_TEXT_SIZE);
157 | badge.setOnClickListener(new View.OnClickListener() {
158 | public void onClick(View v)
159 | {
160 | setButtonPressedEffect(badge);
161 | View rootView = LayoutInflater.from(context).inflate(
162 | R.layout.aladdin_view, null);
163 | View child = FloatWindowCustomView.this.getFocusedChild();
164 | child.startAnimation(getAlphaAnimation(LauncherActivity.ANIMATION_TIME / 2));
165 | Bitmap b = Graphics.getBitmapFromView(child);
166 | int[] position = getPosition(wh);
167 | MainView mainView = (MainView) rootView.findViewById(R.id.view);
168 | setParameter(mainView, position, b, rootView);
169 | windowManager.addView(rootView, mParams);
170 | mainView.startAnimation(false);
171 | }
172 |
173 | private Animation getAlphaAnimation(int i)
174 | {
175 | Animation alphaAnimation = new AlphaAnimation(1, 0);
176 | alphaAnimation.setDuration(i);
177 | alphaAnimation.setAnimationListener(mAnimationListener);
178 | return alphaAnimation;
179 | }
180 |
181 | private void setParameter(MainView mainView, int[] position,
182 | Bitmap bitmap, View rootView)
183 | {
184 | setLeftMargin(position, rootView);
185 | setTopMargin(mainView, position);
186 | mainView.setBitmap(bitmap);
187 | }
188 |
189 | private void setTopMargin(MainView mainView, int[] position)
190 | {
191 | LayoutParams lp = (LayoutParams) mainView.getLayoutParams();
192 | // lp.leftMargin = position[0];
193 | lp.topMargin = position[1] - LauncherActivity.VERTICAL_OFFSET;
194 | mainView.setLayoutParams(lp);
195 |
196 | }
197 |
198 | private void setLeftMargin(int[] position, View rootView)
199 | {
200 | TextView tv = (TextView) rootView.findViewById(R.id.space_h);
201 | LayoutParams lpp = (LayoutParams) tv.getLayoutParams();
202 | // log.e("position[0]=" + position[0]);
203 | float magic = LauncherActivity.SCREEN_WIDTH
204 | - (float) (getDensity() / LauncherActivity.BASE_SCREEN_DENSITY)
205 | * LauncherActivity.BASE_SCREEN_WIDTH;
206 | lpp.width = (int) (position[0] - magic);
207 | // lpp.height = position[1];
208 | tv.setLayoutParams(lpp);
209 | }
210 |
211 | private double getDensity()
212 | {
213 | DisplayMetrics m = new DisplayMetrics();
214 | windowManager.getDefaultDisplay().getMetrics(m);
215 | return m.density;
216 | }
217 |
218 | private void setButtonPressedEffect(BadgeView badge)
219 | {
220 | Animation a = new ScaleAnimation(1, 1.2F, 1, 1.2F,
221 | Animation.RELATIVE_TO_SELF, 0.8f,
222 | Animation.RELATIVE_TO_SELF, 0.8f);
223 | a.setDuration(100);
224 | badge.setBackgroundColor(Color.parseColor("#c00000"));
225 | badge.startAnimation(a);
226 | if (!LauncherActivity.DEBUG_MODE)
227 | Utils.vibrate(context);
228 | }
229 |
230 | private int[] getPosition(int[] wh)
231 | {
232 | log.d("wh[0]=" + wh[0] + " wh[1]=" + wh[1]);
233 | int maxX = LauncherActivity.SCREEN_WIDTH - wh[0];
234 | int x = mParams.x > maxX ? maxX : mParams.x;
235 | x = x > 0 ? x : 0;
236 |
237 | int maxY = LauncherActivity.SCREEN_HEIGHT - wh[1];
238 | int magic = LauncherActivity.IS_TABLTE ? 0 : 2;
239 | int y = mParams.y > maxY ? maxY - magic
240 | * LauncherActivity.VERTICAL_OFFSET : mParams.y;
241 | y = y > 0 ? y : 0;
242 |
243 | log.d("mParams.x=" + mParams.x + " mParams.y=" + mParams.y
244 | + " x=" + x + " y=" + y);
245 | int[] ret = { x, y };
246 | return ret;
247 | }
248 | });
249 | badge.show();
250 |
251 | }
252 |
253 | private int[] getCustomWindowLayoutWidthAndHeight(
254 | LinearLayout customWindowLayout2)
255 | {
256 | int widthMeasureSpec, heightMeasureSpec;
257 | widthMeasureSpec = heightMeasureSpec = View.MeasureSpec
258 | .makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
259 | mCustomWindowLayout.measure(widthMeasureSpec, heightMeasureSpec);
260 | int w = mCustomWindowLayout.getMeasuredWidth();
261 | int h = mCustomWindowLayout.getMeasuredHeight();
262 | log.d("w=" + w + " h=" + h);
263 | int[] ret = { w, h };
264 | return ret;
265 | }
266 |
267 | @Override
268 | public boolean onTouchEvent(MotionEvent event)
269 | {
270 | switch (event.getAction())
271 | {
272 |
273 | case MotionEvent.ACTION_DOWN:
274 | xInView = event.getX();
275 | yInView = event.getY();
276 | break;
277 | case MotionEvent.ACTION_MOVE:
278 | xInScreen = event.getRawX();
279 | // if pad,then status bar will be in the bottom,can not minus
280 | // status bar height,but pad not ensure status bar in the bottom
281 | yInScreen = LauncherActivity.IS_TABLTE ? event.getRawY()
282 | : event.getRawY()
283 | - ScreenLib.getStatusBarHeight(mContext);
284 | updateViewPosition();
285 | break;
286 | case MotionEvent.ACTION_UP:
287 | break;
288 | default:
289 | break;
290 | }
291 | return true;
292 | }
293 |
294 | public void setParams(WindowManager.LayoutParams params)
295 | {
296 | mParams = params;
297 | }
298 |
299 | private void updateViewPosition()
300 | {
301 | mParams.x = (int) (xInScreen - xInView) > 0 ? (int) (xInScreen - xInView)
302 | : 0;
303 | mParams.y = (int) (yInScreen - yInView);
304 | // log.e("x=" + mParams.x + " y=" + mParams.y);
305 | windowManager.updateViewLayout(this, mParams);
306 | }
307 | }
308 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/src/com/tochange/yang/floatladdin/floatwindow/FloatWindowManager.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.floatwindow;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.FileReader;
5 | import java.io.IOException;
6 |
7 | import com.tochange.yang.floatladdin.LauncherActivity;
8 | import com.tochange.yang.floatladdin.R;
9 | import com.tochange.yang.lib.log;
10 |
11 | import android.app.ActivityManager;
12 | import android.content.Context;
13 | import android.graphics.PixelFormat;
14 | import android.view.Gravity;
15 | import android.view.WindowManager;
16 | import android.view.WindowManager.LayoutParams;
17 | import android.widget.TextView;
18 |
19 | public class FloatWindowManager
20 | {
21 |
22 | private static LayoutParams customWindowParams;
23 |
24 | private static FloatWindowCustomView customWindow;
25 |
26 | private static WindowManager mWindowManager;
27 |
28 | private static ActivityManager mActivityManager;
29 |
30 | public static void createCustomWindow(Context context)
31 | {
32 | if (customWindow == null)
33 | {
34 | WindowManager windowManager = getWindowManager(context);
35 | customWindow = new FloatWindowCustomView(context);
36 | if (customWindowParams == null)
37 | {
38 | customWindowParams = new LayoutParams();
39 | customWindowParams.type = LayoutParams.TYPE_SYSTEM_ALERT;
40 | customWindowParams.format = PixelFormat.RGBA_8888;
41 | customWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
42 | | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
43 | | LayoutParams.FLAG_NOT_FOCUSABLE;
44 | customWindowParams.gravity = Gravity.LEFT | Gravity.TOP;
45 | customWindowParams.width = LayoutParams.WRAP_CONTENT;
46 | customWindowParams.height = LayoutParams.WRAP_CONTENT;
47 | LauncherActivity.SCREEN_WIDTH = windowManager
48 | .getDefaultDisplay().getWidth();
49 | LauncherActivity.SCREEN_HEIGHT = windowManager
50 | .getDefaultDisplay().getHeight();
51 | customWindowParams.x = LauncherActivity.SCREEN_WIDTH / 4;
52 | customWindowParams.y = LauncherActivity.SCREEN_HEIGHT * 2 / 3;
53 | }
54 | customWindow.setParams(customWindowParams);
55 | windowManager.addView(customWindow, customWindowParams);
56 | }
57 | }
58 |
59 | public static void removeCustomWindow(Context context)
60 | {
61 | if (customWindow != null)
62 | {
63 | WindowManager windowManager = getWindowManager(context);
64 | windowManager.removeView(customWindow);
65 | customWindow = null;
66 | }
67 | }
68 |
69 | public static void updateUsedPercent(Context context)
70 | {
71 | if (customWindow != null)
72 | {
73 | TextView percentView = (TextView) customWindow
74 | .findViewById(R.id.percent);
75 | if (percentView != null)
76 | percentView.setText(getUsedPercentValue(context));
77 | }
78 | }
79 |
80 | public static boolean isWindowShowing()
81 | {
82 | return customWindow != null;
83 | }
84 |
85 | private static WindowManager getWindowManager(Context context)
86 | {
87 | if (mWindowManager == null)
88 | {
89 | mWindowManager = (WindowManager) context
90 | .getSystemService(Context.WINDOW_SERVICE);
91 | }
92 | return mWindowManager;
93 | }
94 |
95 | private static ActivityManager getActivityManager(Context context)
96 | {
97 | if (mActivityManager == null)
98 | {
99 | mActivityManager = (ActivityManager) context
100 | .getSystemService(Context.ACTIVITY_SERVICE);
101 | }
102 | return mActivityManager;
103 | }
104 |
105 | public static String getUsedPercentValue(Context context)
106 | {
107 | String dir = "/proc/meminfo";
108 | try
109 | {
110 | FileReader fr = new FileReader(dir);
111 | BufferedReader br = new BufferedReader(fr, 2048);
112 | String memoryLine = br.readLine();
113 | String subMemoryLine = memoryLine.substring(memoryLine
114 | .indexOf("MemTotal:"));
115 | br.close();
116 | long totalMemorySize = Integer.parseInt(subMemoryLine.replaceAll(
117 | "\\D+", ""));
118 | long availableSize = getAvailableMemory(context) / 1024;
119 | int percent = (int) ((totalMemorySize - availableSize)
120 | / (float) totalMemorySize * 100);
121 | return percent + "%";
122 | }
123 | catch (IOException e)
124 | {
125 | log.e(e.toString());
126 | }
127 | return "floating windows";
128 | }
129 |
130 | private static long getAvailableMemory(Context context)
131 | {
132 | ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
133 | getActivityManager(context).getMemoryInfo(mi);
134 | return mi.availMem;
135 | }
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/NoActivityAladdin/Aladdin/src/com/tochange/yang/floatladdin/floatwindow/FloatWindowService.java:
--------------------------------------------------------------------------------
1 | package com.tochange.yang.floatladdin.floatwindow;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Timer;
6 | import java.util.TimerTask;
7 |
8 | import com.tochange.yang.lib.log;
9 |
10 | import android.app.ActivityManager;
11 | import android.app.ActivityManager.RunningTaskInfo;
12 | import android.app.Service;
13 | import android.content.Context;
14 | import android.content.Intent;
15 | import android.content.pm.PackageManager;
16 | import android.content.pm.ResolveInfo;
17 | import android.os.Handler;
18 | import android.os.IBinder;
19 |
20 | public class FloatWindowService extends Service {
21 | public static FloatWindowService mFloatWindowService;
22 | private Handler handler = new Handler();
23 | private Timer timer;
24 |
25 | @Override
26 | public IBinder onBind(Intent intent) {
27 | return null;
28 | }
29 |
30 | @Override
31 | public int onStartCommand(Intent intent, int flags, int startId) {
32 | // 开启定时器,每隔0.5秒刷新一次
33 | // log.e("");
34 | if (timer == null) {
35 | timer = new Timer();
36 | timer.scheduleAtFixedRate(new RefreshTask(), 0, 500);
37 | }
38 | mFloatWindowService = this;
39 | return super.onStartCommand(intent, flags, startId);
40 | }
41 |
42 | @Override
43 | public void onDestroy() {
44 | // log.e("");
45 | FloatWindowManager.removeCustomWindow(getApplicationContext());
46 | super.onDestroy();
47 | timer.cancel();
48 | timer = null;
49 | }
50 |
51 | class RefreshTask extends TimerTask {
52 |
53 | @Override
54 | public void run() {
55 | // 当前界面是桌面,且没有悬浮窗显示,则创建悬浮窗。
56 | if (isHome() && !FloatWindowManager.isWindowShowing()) {
57 | handler.post(new Runnable() {
58 | @Override
59 | public void run() {
60 | FloatWindowManager.createCustomWindow(getApplicationContext());
61 | }
62 | });
63 | }
64 | // 当前界面不是桌面,且有悬浮窗显示,则移除悬浮窗。
65 | else if (!isHome() && FloatWindowManager.isWindowShowing()) {
66 | handler.post(new Runnable() {
67 | @Override
68 | public void run() {
69 | // FloatWindowManager.removeCustomWindow(getApplicationContext());
70 | }
71 | });
72 | }
73 | // 当前界面是桌面,且有悬浮窗显示,则更新内存数据。
74 | else if (isHome() && FloatWindowManager.isWindowShowing()) {
75 | handler.post(new Runnable() {
76 | @Override
77 | public void run() {
78 | FloatWindowManager.updateUsedPercent(getApplicationContext());
79 | }
80 | });
81 | }
82 | }
83 |
84 | }
85 |
86 | /**
87 | * 判断当前界面是否是桌面
88 | */
89 | private boolean isHome() {
90 | ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
91 | List rti = mActivityManager.getRunningTasks(1);
92 | return getHomes().contains(rti.get(0).topActivity.getPackageName());
93 | }
94 |
95 | /**
96 | * 获得属于桌面的应用的应用包名称
97 | *
98 | * @return 返回包含所有包名的字符串列表
99 | */
100 | private List getHomes() {
101 | List names = new ArrayList();
102 | PackageManager packageManager = this.getPackageManager();
103 | Intent intent = new Intent(Intent.ACTION_MAIN);
104 | intent.addCategory(Intent.CATEGORY_HOME);
105 | List resolveInfo = packageManager.queryIntentActivities(intent,
106 | PackageManager.MATCH_DEFAULT_ONLY);
107 | for (ResolveInfo ri : resolveInfo) {
108 | names.add(ri.activityInfo.packageName);
109 | }
110 | return names;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tochange/Aladdin/51c2708874aa4b66be596e2bfde966d79897c997/README.md
--------------------------------------------------------------------------------
/aa.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tochange/Aladdin/51c2708874aa4b66be596e2bfde966d79897c997/aa.gif
--------------------------------------------------------------------------------
/mac.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tochange/Aladdin/51c2708874aa4b66be596e2bfde966d79897c997/mac.jpg
--------------------------------------------------------------------------------