├── .gitattributes
├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── dictionaries
│ └── Administrator.xml
├── encodings.xml
├── gradle.xml
├── libraries
│ ├── appcompat_v7_20_0_0.xml
│ ├── nineoldandroids_lib.xml
│ ├── support_annotations_20_0_0.xml
│ └── support_v4_20_0_0.xml
├── misc.xml
├── modules.xml
├── scopes
│ └── scope_settings.xml
└── vcs.xml
├── CanvasView-master.iml
├── README.md
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── libs
│ └── nineoldandroids-lib.jar
├── proguard-rules.txt
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-web.png
│ ├── java
│ └── com
│ │ └── etong
│ │ └── canvasview_master
│ │ └── app
│ │ ├── AnimUtil.java
│ │ ├── ArcTranslateAnimation.java
│ │ ├── Circle.java
│ │ ├── CircleCanvasDemo1.java
│ │ ├── CircleCanvasLayout.java
│ │ ├── CircleCanvasView.java
│ │ ├── CircleDrawable.java
│ │ ├── MainActivity.java
│ │ ├── MeteorActivity.java
│ │ └── MyCircle.java
│ └── res
│ ├── anim
│ └── slide_out_bottom.xml
│ ├── drawable-hdpi
│ ├── add.png
│ └── ic_launcher.png
│ ├── drawable-mdpi
│ ├── add.png
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ ├── add.png
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ ├── add.png
│ └── ic_launcher.png
│ ├── drawable
│ └── circle_background.xml
│ ├── layout
│ ├── activity_circle_canvas_demo1.xml
│ ├── activity_main.xml
│ └── activity_meteor.xml
│ ├── menu
│ ├── circle_canvas_demo1.xml
│ └── main.xml
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── build
└── intermediates
│ └── dex-cache
│ └── cache.xml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots
├── canvasLayout.gif
└── canvasLayout1.gif
└── settings.gradle
/.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 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | CanvasView-master
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/dictionaries/Administrator.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/libraries/appcompat_v7_20_0_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/nineoldandroids_lib.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/libraries/support_annotations_20_0_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/libraries/support_v4_20_0_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/CanvasView-master.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | CanvasView-master
2 | =================
3 |
4 | 画个圈圈诅咒你
5 | 仿android L其中一种动画特效。
6 |
7 | 效果图
8 |
9 | 
10 |
11 | 效果图2
12 |
13 | 
14 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'android'
2 |
3 | android {
4 | compileSdkVersion 20
5 | buildToolsVersion '20'
6 |
7 | defaultConfig {
8 | minSdkVersion 20
9 | targetSdkVersion 20
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | runProguard false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile 'com.android.support:appcompat-v7:20+'
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | compile files('libs/nineoldandroids-lib.jar')
25 | }
26 |
--------------------------------------------------------------------------------
/app/libs/nineoldandroids-lib.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/app/libs/nineoldandroids-lib.jar
--------------------------------------------------------------------------------
/app/proguard-rules.txt:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:/Program Files (x86)/Android/android-studio19/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the ProGuard
5 | # include property in project.properties.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/app/src/main/java/com/etong/canvasview_master/app/AnimUtil.java:
--------------------------------------------------------------------------------
1 | package com.etong.canvasview_master.app;
2 |
3 | /**
4 | * Created by Administrator on 14-8-8.
5 | */
6 | public class AnimUtil {
7 |
8 | public static long calcBezier(float interpolatedTime, float p0, float p1, float p2) {
9 | return Math.round((Math.pow((1 - interpolatedTime), 2) * p0)
10 | + (2 * (1 - interpolatedTime) * interpolatedTime * p1)
11 | + (Math.pow(interpolatedTime, 2) * p2));
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/etong/canvasview_master/app/ArcTranslateAnimation.java:
--------------------------------------------------------------------------------
1 | package com.etong.canvasview_master.app;
2 |
3 | /**
4 | * Created by Administrator on 14-8-7.
5 | */
6 | import android.graphics.PointF;
7 | import android.util.Log;
8 | import android.view.animation.Animation;
9 | import android.view.animation.Transformation;
10 |
11 | // http://www.math.ubc.ca/~cass/gfx/bezier.html
12 |
13 | public class ArcTranslateAnimation extends Animation {
14 | private int mFromXType = ABSOLUTE;
15 | private int mToXType = ABSOLUTE;
16 |
17 | private int mFromYType = ABSOLUTE;
18 | private int mToYType = ABSOLUTE;
19 |
20 | private float mFromXValue = 0.0f;
21 | private float mToXValue = 0.0f;
22 |
23 | private float mFromYValue = 0.0f;
24 | private float mToYValue = 0.0f;
25 |
26 | private float mFromXDelta;
27 | private float mToXDelta;
28 | private float mFromYDelta;
29 | private float mToYDelta;
30 |
31 | private PointF mStart;
32 | private PointF mControl;
33 | private PointF mEnd;
34 |
35 | private float dx;
36 | private float dy;
37 |
38 | private float interpolatorTime;
39 |
40 | /**
41 | * Constructor to use when building a ArcTranslateAnimation from code
42 | *
43 | * @param fromXDelta
44 | * Change in X coordinate to apply at the start of the animation
45 | * @param toXDelta
46 | * Change in X coordinate to apply at the end of the animation
47 | * @param fromYDelta
48 | * Change in Y coordinate to apply at the start of the animation
49 | * @param toYDelta
50 | * Change in Y coordinate to apply at the end of the animation
51 | */
52 | public ArcTranslateAnimation(float fromXDelta, float toXDelta,
53 | float fromYDelta, float toYDelta) {
54 | mFromXValue = fromXDelta;
55 | mToXValue = toXDelta;
56 | mFromYValue = fromYDelta;
57 | mToYValue = toYDelta;
58 |
59 | mFromXType = ABSOLUTE;
60 | mToXType = ABSOLUTE;
61 | mFromYType = ABSOLUTE;
62 | mToYType = ABSOLUTE;
63 | }
64 |
65 | /**
66 | * Constructor to use when building a ArcTranslateAnimation from code
67 | *
68 | * @param fromXType
69 | * Specifies how fromXValue should be interpreted. One of
70 | * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
71 | * Animation.RELATIVE_TO_PARENT.
72 | * @param fromXValue
73 | * Change in X coordinate to apply at the start of the animation.
74 | * This value can either be an absolute number if fromXType is
75 | * ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
76 | * @param toXType
77 | * Specifies how toXValue should be interpreted. One of
78 | * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
79 | * Animation.RELATIVE_TO_PARENT.
80 | * @param toXValue
81 | * Change in X coordinate to apply at the end of the animation.
82 | * This value can either be an absolute number if toXType is
83 | * ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
84 | * @param fromYType
85 | * Specifies how fromYValue should be interpreted. One of
86 | * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
87 | * Animation.RELATIVE_TO_PARENT.
88 | * @param fromYValue
89 | * Change in Y coordinate to apply at the start of the animation.
90 | * This value can either be an absolute number if fromYType is
91 | * ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
92 | * @param toYType
93 | * Specifies how toYValue should be interpreted. One of
94 | * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
95 | * Animation.RELATIVE_TO_PARENT.
96 | * @param toYValue
97 | * Change in Y coordinate to apply at the end of the animation.
98 | * This value can either be an absolute number if toYType is
99 | * ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
100 | */
101 | public ArcTranslateAnimation(int fromXType, float fromXValue, int toXType,
102 | float toXValue, int fromYType, float fromYValue, int toYType,
103 | float toYValue) {
104 |
105 | mFromXValue = fromXValue;
106 | mToXValue = toXValue;
107 | mFromYValue = fromYValue;
108 | mToYValue = toYValue;
109 |
110 | mFromXType = fromXType;
111 | mToXType = toXType;
112 | mFromYType = fromYType;
113 | mToYType = toYType;
114 | }
115 |
116 | @Override
117 | public void applyTransformation(float interpolatedTime, Transformation t) {
118 |
119 | Log.i("etong","inter: "+interpolatedTime);
120 | interpolatorTime = interpolatedTime;
121 | this.dx = calcBezier(interpolatedTime, mStart.x, mControl.x, mEnd.x);
122 | this.dy = calcBezier(interpolatedTime, mStart.y, mControl.y, mEnd.y);
123 |
124 | t.getMatrix().setTranslate(dx, dy);
125 | }
126 |
127 | @Override
128 | public void initialize(int width, int height, int parentWidth,
129 | int parentHeight) {
130 | super.initialize(width, height, parentWidth, parentHeight);
131 | mFromXDelta = resolveSize(mFromXType, mFromXValue, width, parentWidth);
132 | mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth);
133 | mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight);
134 | mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight);
135 |
136 | mStart = new PointF(mFromXDelta, mFromYDelta);
137 | mEnd = new PointF(mToXDelta, mToYDelta);
138 | mControl = new PointF(mFromXDelta, mToYDelta); // How to choose the
139 | // Control point(we can
140 | // use the cross of the
141 | // two tangents from p0,
142 | // p1)
143 | }
144 |
145 | /**
146 | * Calculate the position on a quadratic bezier curve by given three points
147 | * and the percentage of time passed.
148 | *
149 | * from http://en.wikipedia.org/wiki/B%C3%A9zier_curve
150 | *
151 | * @param interpolatedTime
152 | * the fraction of the duration that has passed where 0 <= time
153 | * <= 1
154 | * @param p0
155 | * a single dimension of the starting point
156 | * @param p1
157 | * a single dimension of the control point
158 | * @param p2
159 | * a single dimension of the ending point
160 | */
161 | private long calcBezier(float interpolatedTime, float p0, float p1, float p2) {
162 | return Math.round((Math.pow((1 - interpolatedTime), 2) * p0)
163 | + (2 * (1 - interpolatedTime) * interpolatedTime * p1)
164 | + (Math.pow(interpolatedTime, 2) * p2));
165 | }
166 |
167 | public float getDx(){
168 | return dx;
169 | }
170 |
171 | public float getDy(){
172 | return dy;
173 | }
174 |
175 | public float getInterpolatorTime(){
176 | return interpolatorTime;
177 | }
178 |
179 | }
180 |
--------------------------------------------------------------------------------
/app/src/main/java/com/etong/canvasview_master/app/Circle.java:
--------------------------------------------------------------------------------
1 | package com.etong.canvasview_master.app;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.PointF;
7 | import android.util.Log;
8 | import android.view.View;
9 |
10 | /**
11 | * Created by Administrator on 14-8-8.
12 | */
13 | public class Circle {
14 |
15 |
16 | private float cx;
17 |
18 | private float cy;
19 |
20 | private float radius;
21 |
22 | private Paint paint;
23 |
24 | public Circle(float cx, float cy, float radius, Paint paint) {
25 | this.cx = cx;
26 | this.cy = cy;
27 | this.radius = radius;
28 | this.paint = paint;
29 | }
30 |
31 | public void draw(Canvas canvas) {
32 | canvas.drawCircle(cx, cy, radius, paint);
33 | }
34 |
35 | public void moveTo(float interpolatedTime, float startX, float endX, float startY, float endY) {
36 | this.cx = AnimUtil.calcBezier(interpolatedTime, startX, startX, endX);
37 | this.cy = AnimUtil.calcBezier(interpolatedTime, startY, endY, endY);
38 | }
39 |
40 | public void Zoom(float fromR,float toR,float time) {
41 | float increase = Math.abs(toR-fromR)/time;
42 | this.radius = radius + increase;
43 | }
44 |
45 | public void Zoom(float radius) {
46 | this.radius = radius;
47 | }
48 |
49 | public float getCx() {
50 | return cx;
51 | }
52 |
53 | public void setCx(float cx) {
54 | this.cx = cx;
55 | }
56 |
57 | public float getCy() {
58 | return cy;
59 | }
60 |
61 | public void setCy(float cy) {
62 | this.cy = cy;
63 | }
64 |
65 | public float getRadius() {
66 | return radius;
67 | }
68 |
69 | public void setRadius(float radius) {
70 | this.radius = radius;
71 | }
72 |
73 | public Paint getPaint() {
74 | return paint;
75 | }
76 |
77 | public void setPaint(Paint paint) {
78 | this.paint = paint;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/com/etong/canvasview_master/app/CircleCanvasDemo1.java:
--------------------------------------------------------------------------------
1 | package com.etong.canvasview_master.app;
2 |
3 | import android.app.Activity;
4 | import android.support.v7.app.ActionBarActivity;
5 | import android.os.Bundle;
6 | import android.view.Menu;
7 | import android.view.MenuItem;
8 | import android.view.View;
9 | import android.widget.Button;
10 |
11 | public class CircleCanvasDemo1 extends Activity implements View.OnClickListener{
12 |
13 |
14 | private CircleCanvasLayout circleCanvasLayout;
15 |
16 | private Button btn,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btn10,backBtn;
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.activity_circle_canvas_demo1);
22 |
23 | findAllView();
24 | setListener();
25 | }
26 |
27 | private void findAllView() {
28 | circleCanvasLayout = (CircleCanvasLayout) findViewById(R.id.view);
29 | btn = (Button) findViewById(R.id.button);
30 | btn2 = (Button) findViewById(R.id.button2);
31 | btn3 = (Button) findViewById(R.id.button3);
32 | btn4 = (Button) findViewById(R.id.button4);
33 | btn5 = (Button) findViewById(R.id.button5);
34 | btn6 = (Button) findViewById(R.id.button6);
35 | btn7 = (Button) findViewById(R.id.button7);
36 | btn8 = (Button) findViewById(R.id.button8);
37 | btn9 = (Button) findViewById(R.id.button9);
38 | btn10 = (Button) findViewById(R.id.button10);
39 | backBtn = (Button) findViewById(R.id.back_btn);
40 |
41 | }
42 |
43 | private void setListener(){
44 | btn.setOnClickListener(this);
45 | btn2.setOnClickListener(this);
46 | btn3.setOnClickListener(this);
47 | btn4.setOnClickListener(this);
48 | btn5.setOnClickListener(this);
49 | btn6.setOnClickListener(this);
50 | btn7.setOnClickListener(this);
51 | btn8.setOnClickListener(this);
52 | btn9.setOnClickListener(this);
53 | btn10.setOnClickListener(this);
54 | backBtn.setOnClickListener(this);
55 | }
56 |
57 |
58 | @Override
59 | public boolean onCreateOptionsMenu(Menu menu) {
60 |
61 | // Inflate the menu; this adds items to the action bar if it is present.
62 | getMenuInflater().inflate(R.menu.circle_canvas_demo1, menu);
63 | return true;
64 | }
65 |
66 | @Override
67 | public boolean onOptionsItemSelected(MenuItem item) {
68 | // Handle action bar item clicks here. The action bar will
69 | // automatically handle clicks on the Home/Up button, so long
70 | // as you specify a parent activity in AndroidManifest.xml.
71 | int id = item.getItemId();
72 | if (id == R.id.action_settings) {
73 | return true;
74 | }
75 | return super.onOptionsItemSelected(item);
76 | }
77 |
78 | @Override
79 | public void onClick(View view) {
80 | if(view == btn){
81 | circleCanvasLayout.ZoomIn();
82 | }else if(view ==btn2){
83 | circleCanvasLayout.setCirclePosition(CircleCanvasLayout.LEFT_TOP);
84 | }else if(view ==btn3){
85 | circleCanvasLayout.setCirclePosition(CircleCanvasLayout.LEFT_CENTER);
86 | }else if(view ==btn4){
87 | circleCanvasLayout.setCirclePosition(CircleCanvasLayout.LEFT_BOTTOM);
88 | }else if(view ==btn5){
89 | circleCanvasLayout.setCirclePosition(CircleCanvasLayout.CENTER_TOP);
90 | }else if(view ==btn6){
91 | circleCanvasLayout.setCirclePosition(CircleCanvasLayout.CENTER);
92 | }else if(view ==btn7){
93 | circleCanvasLayout.setCirclePosition(CircleCanvasLayout.CENTER_BOTTOM);
94 | }else if(view ==btn8){
95 | circleCanvasLayout.setCirclePosition(CircleCanvasLayout.RIGHT_TOP);
96 | }else if(view ==btn9){
97 | circleCanvasLayout.setCirclePosition(CircleCanvasLayout.RIGHT_CENTER);
98 | }else if(view ==btn10){
99 | circleCanvasLayout.setCirclePosition(CircleCanvasLayout.RIGHT_BOTTOM);
100 | }else if(view ==backBtn){
101 | circleCanvasLayout.ZoomOut();
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/com/etong/canvasview_master/app/CircleCanvasLayout.java:
--------------------------------------------------------------------------------
1 | package com.etong.canvasview_master.app;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.util.AttributeSet;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.view.animation.AccelerateDecelerateInterpolator;
11 | import android.widget.RelativeLayout;
12 |
13 | import com.nineoldandroids.animation.ValueAnimator;
14 |
15 | /**
16 | * Created by Administrator on 14-8-11.
17 | */
18 | public class CircleCanvasLayout extends RelativeLayout {
19 |
20 | /**
21 | * 画笔
22 | */
23 | private Paint paint;
24 |
25 | /**
26 | * 颜色black
27 | */
28 | public final static int black = 0x70000000;//黑色
29 |
30 | /**
31 | * 颜色white
32 | */
33 | public final static int white = 0xddffffff;//白色
34 |
35 | public final static int LEFT_TOP = 1;
36 |
37 | public final static int CENTER_TOP = 2;
38 |
39 | public final static int RIGHT_TOP = 3;
40 |
41 | public final static int LEFT_CENTER = 4;
42 |
43 | public final static int CENTER = 5;
44 |
45 | public final static int RIGHT_CENTER = 6;
46 |
47 | public final static int LEFT_BOTTOM = 7;
48 |
49 | public final static int CENTER_BOTTOM = 8;
50 |
51 | public final static int RIGHT_BOTTOM = 9;
52 |
53 | private int circlePosition;
54 |
55 | public final static int DF_DURATION = 800;
56 |
57 | public int paintColor;
58 |
59 | /**
60 | * 颜色orange
61 | */
62 | public int orange;
63 |
64 | /**
65 | * 圆圈初始半径
66 | */
67 | private int minRadius;
68 |
69 | private float maxRadius;
70 |
71 | /**
72 | * 圆圈半径
73 | */
74 | private float radius;
75 |
76 | /**
77 | * 圈圈圆心x轴坐标
78 | */
79 | private float cx;
80 |
81 | /**
82 | * 圈圈圆心y轴坐标
83 | */
84 | private float cy;
85 |
86 | /**
87 | * 扩散量单位
88 | */
89 | public float increase;
90 |
91 | /**
92 | * 动画是否可以启用
93 | */
94 | private boolean animAble = false;
95 |
96 | /**
97 | * 屏幕分辨率密度比
98 | */
99 | private float density;
100 |
101 | /**
102 | * 缩小动画的时间
103 | */
104 | private long outDuration = 300;
105 |
106 | /**
107 | * 放大动画执行时间
108 | */
109 | private long inDuration = 500;
110 |
111 | public final static int refreshTime = 20;
112 |
113 | public float getCx() {
114 | return cx;
115 | }
116 |
117 | public float getCy() {
118 | return cy;
119 | }
120 |
121 | public void setCx(float cx) {
122 | this.cx = cx;
123 | }
124 |
125 | public void setCy(float cy) {
126 | this.cy = cy;
127 | }
128 |
129 | public long getOutDuration() {
130 | return outDuration;
131 | }
132 |
133 | public void setOutDuration(long outDuration) {
134 | this.outDuration = outDuration;
135 | }
136 |
137 | public long getInDuration() {
138 | return inDuration;
139 | }
140 |
141 | public void setInDuration(long inDuration) {
142 | this.inDuration = inDuration;
143 | }
144 |
145 | public CircleCanvasLayout(Context context) {
146 | super(context);
147 | init();
148 | }
149 |
150 | public CircleCanvasLayout(Context context, AttributeSet attrs) {
151 | super(context, attrs);
152 |
153 | TypedArray typeArray = context.obtainStyledAttributes(attrs,
154 | R.styleable.CircleCanvasLayout);
155 | maxRadius = typeArray.getDimension(R.styleable.CircleCanvasLayout_maxRadius, 0);
156 | cx = typeArray.getDimension(R.styleable.CircleCanvasLayout_cx, 0);
157 | cy = typeArray.getDimension(R.styleable.CircleCanvasLayout_cy, 0);
158 | circlePosition = typeArray.getInteger(R.styleable.CircleCanvasLayout_circlePosition, 1);
159 | paintColor = typeArray.getColor(R.styleable.CircleCanvasLayout_circleColor, white);
160 | init();
161 | }
162 |
163 | public CircleCanvasLayout(Context context, AttributeSet attrs, int defStyle) {
164 | super(context, attrs, defStyle);
165 | init();
166 | }
167 |
168 |
169 | private void init() {
170 |
171 | setWillNotDraw(false);
172 |
173 | density = getResources().getDisplayMetrics().density;
174 |
175 | paint = new Paint();
176 | paint.setColor(paintColor);
177 | paint.setAntiAlias(true);//抗锯齿
178 |
179 | }
180 |
181 | public void setCirclePosition(int position) {
182 | this.circlePosition = position;
183 | setCenterPosition();
184 | }
185 |
186 | public void setPosition(int x, int y) {
187 | this.cx = x;
188 | this.cy = y;
189 | }
190 |
191 | /**
192 | * 设置画笔颜色
193 | *
194 | * @param color
195 | */
196 | public void setPaintColor(int color) {
197 | paint.setColor(color);
198 | }
199 |
200 | /**
201 | * 获取画笔颜色
202 | *
203 | * @return
204 | */
205 | public int getPaintColor() {
206 | return paint.getColor();
207 | }
208 |
209 | private void setCenterPosition(){
210 | //设置圈圈圆心位置
211 | switch (circlePosition) {
212 | case LEFT_TOP:
213 | cx = 0;
214 | cy = 0;
215 | break;
216 | case CENTER_TOP:
217 | cx = getWidth() / 2;
218 | cy = 0;
219 | break;
220 | case RIGHT_TOP:
221 | cx = getWidth();
222 | cy = 0;
223 | break;
224 | case LEFT_CENTER:
225 | cx = 0;
226 | cy = getHeight() / 2;
227 | break;
228 | case CENTER:
229 | cx = getWidth() / 2;
230 | cy = getHeight() / 2;
231 | break;
232 | case RIGHT_CENTER:
233 | cx = getWidth();
234 | cy = getHeight() / 2;
235 | break;
236 | case LEFT_BOTTOM:
237 | cx = 0;
238 | cy = getHeight();
239 | break;
240 | case CENTER_BOTTOM:
241 | cx = getWidth() / 2;
242 | cy = getHeight();
243 | break;
244 | case RIGHT_BOTTOM:
245 | cx = getWidth();
246 | cy = getHeight();
247 | break;
248 | }
249 | }
250 |
251 | @Override
252 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
253 | super.onLayout(changed, l, t, r, b);
254 |
255 | //设置圈圈最大半径
256 | maxRadius = getDiagonal();
257 | setCenterPosition();
258 | //确保view必须数据初始化完成,然后才开始动画
259 | animAble = true;
260 | }
261 |
262 | @Override
263 | protected void onDraw(Canvas canvas) {
264 | super.onDraw(canvas);
265 | //为了UI编辑界面拖动的控件可以看,xml编辑模式下,此部分代码不执行。
266 | if (!isInEditMode()) {
267 | canvas.drawCircle(cx, cy, radius, paint);
268 | }
269 | }
270 |
271 | /**
272 | * 随机产生圆点x轴坐标
273 | *
274 | * @return
275 | */
276 | private int randomCx() {
277 | return randomCenter(getWidth());
278 | }
279 |
280 | /**
281 | * 随机产生圆点x轴坐标
282 | *
283 | * @return
284 | */
285 | private int randomCy() {
286 | return randomCenter(getHeight());
287 | }
288 |
289 | /**
290 | * 随机产生圆点坐标
291 | *
292 | * @return
293 | */
294 | private int randomCenter(int scope) {
295 | return (int) (Math.random() * scope);
296 | }
297 |
298 | /**
299 | * 放大
300 | */
301 | public void ZoomIn() {
302 | ValueAnimator valueAnimator = ValueAnimator.ofInt(minRadius, (int) maxRadius);
303 | valueAnimator.setDuration(inDuration);
304 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
305 | @Override
306 | public void onAnimationUpdate(ValueAnimator valueAnimator) {
307 | Integer value = (Integer) valueAnimator.getAnimatedValue();
308 | radius = minRadius + value;
309 | invalidate();
310 | }
311 | });
312 | valueAnimator.start();
313 | }
314 |
315 | /**
316 | * 缩小
317 | */
318 | public void ZoomOut() {
319 | ValueAnimator valueAnimator = ValueAnimator.ofInt(minRadius, (int) maxRadius);
320 | valueAnimator.setDuration(outDuration);
321 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
322 | @Override
323 | public void onAnimationUpdate(ValueAnimator valueAnimator) {
324 | Integer value = (Integer) valueAnimator.getAnimatedValue();
325 | radius = maxRadius - value;
326 | invalidate();
327 | }
328 | });
329 | valueAnimator.start();
330 | }
331 |
332 | public void starFall() {
333 |
334 | }
335 |
336 | /**
337 | * 自定义圈圈半径
338 | *
339 | * @param radius
340 | */
341 | public void setMaxRadius(int radius) {
342 | this.maxRadius = radius;
343 | }
344 |
345 | /**
346 | * 获取圈圈最大半径
347 | *
348 | * @return
349 | */
350 | public float getMaxRadius() {
351 | return maxRadius;
352 | }
353 |
354 | /**
355 | * 计算画布对角线长度
356 | *
357 | * @return
358 | */
359 | public float getDiagonal() {
360 | return (float) Math.sqrt(Math.pow((double) getHeight(), 2) + Math.pow((double) getWidth(), 2));
361 | }
362 |
363 | }
364 |
--------------------------------------------------------------------------------
/app/src/main/java/com/etong/canvasview_master/app/CircleCanvasView.java:
--------------------------------------------------------------------------------
1 | package com.etong.canvasview_master.app;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.util.AttributeSet;
7 | import android.util.Log;
8 | import android.view.View;
9 | import android.view.animation.AccelerateDecelerateInterpolator;
10 | import android.view.animation.AccelerateInterpolator;
11 | import android.view.animation.Animation;
12 | import android.view.animation.AnticipateInterpolator;
13 | import android.view.animation.Interpolator;
14 | import android.view.animation.LinearInterpolator;
15 | import android.view.animation.Transformation;
16 | import android.widget.RelativeLayout;
17 |
18 | import com.nineoldandroids.animation.Animator;
19 | import com.nineoldandroids.animation.AnimatorSet;
20 | import com.nineoldandroids.animation.ObjectAnimator;
21 | import com.nineoldandroids.animation.ValueAnimator;
22 |
23 | /**
24 | * Created by Administrator on 14-8-7.
25 | */
26 | public class CircleCanvasView extends RelativeLayout implements Animation.AnimationListener {
27 |
28 | /**
29 | * 画笔
30 | */
31 | private Paint paint;
32 |
33 | /**
34 | * 颜色black
35 | */
36 | public final static int black = 0x70000000;//黑色
37 |
38 | /**
39 | * 颜色white
40 | */
41 | public final static int white = 0xddffffff;//白色
42 |
43 | /**
44 | * 颜色orange
45 | */
46 | public int orange;
47 |
48 | /**
49 | * 圆圈初始半径
50 | */
51 | private int minRadius;
52 |
53 | private int maxRadius;
54 |
55 |
56 | /**
57 | * 圆圈半径
58 | */
59 | private int radius;
60 |
61 | /**
62 | * 画布中心x轴坐标
63 | */
64 | private int cx;
65 |
66 | /**
67 | * 画布中心y轴坐标
68 | */
69 | private int cy;
70 |
71 | /**
72 | * 扩散量单位
73 | */
74 | public float increase;
75 |
76 | /**
77 | * 动画是否可以启用
78 | */
79 | private boolean animAble = false;
80 |
81 | /**
82 | * 屏幕分辨率密度比
83 | */
84 | private float density;
85 |
86 | /**
87 | * 流星
88 | */
89 | private View meteor;
90 |
91 | /**
92 | * 流星撞击点x轴坐标
93 | */
94 | private int kx;
95 |
96 | /**
97 | * 流星撞击点y轴坐标
98 | */
99 | private int ky;
100 |
101 | /**
102 | * 是否自定义流星撞击点
103 | */
104 | private boolean UseCustomPonit = false;
105 |
106 | /**
107 | * 贝塞尔曲线动画对象
108 | */
109 | private ArcTranslateAnimation arcAnim;
110 |
111 | /**
112 | * 流星数量
113 | */
114 | private int starNumber;
115 |
116 | private Circle mCircle;
117 |
118 |
119 | public final static int arcAnimTime = 300;
120 |
121 | public final static int refreshTime = 20;
122 |
123 | public long arcAnimStartTime;
124 |
125 | public AnimatorSet animatorSet;
126 |
127 |
128 | public CircleCanvasView(Context context) {
129 | super(context);
130 | init();
131 | }
132 |
133 | public CircleCanvasView(Context context, AttributeSet attrs) {
134 | super(context, attrs);
135 | init();
136 |
137 | }
138 |
139 | public CircleCanvasView(Context context, AttributeSet attrs, int defStyle) {
140 | super(context, attrs, defStyle);
141 | init();
142 | }
143 |
144 | public CircleCanvasView(Context context, View view) {
145 | super(context);
146 |
147 | this.meteor = view;
148 |
149 | init();
150 |
151 | initMeteorAnim();
152 |
153 | }
154 |
155 | /**
156 | * 设置流星
157 | *
158 | * @param view
159 | */
160 | public void setMeteor(View view) {
161 | this.meteor = view;
162 | }
163 |
164 | /**
165 | * 设置流星撞击点,相对画布的坐标
166 | *
167 | * @param kx
168 | * @param ky
169 | */
170 | public void setKnockPoint(int kx, int ky) {
171 | this.kx = kx;
172 | this.ky = ky;
173 | this.UseCustomPonit = true;
174 | }
175 |
176 | public float getMeteorCx() {
177 | return ((ArcTranslateAnimation) meteor.getAnimation()).getDx() + meteor.getLeft() - getLeft() + meteor.getWidth() / 2;
178 | }
179 |
180 | public float getMeteorCy() {
181 | return ((ArcTranslateAnimation) meteor.getAnimation()).getDy() + meteor.getTop() - getTop() + meteor.getHeight() / 2;
182 | }
183 |
184 | /**
185 | * 获得撞击点x轴坐标
186 | *
187 | * @return
188 | */
189 | public int getKnockPointX() {
190 | return UseCustomPonit ? kx : getCx();
191 | }
192 |
193 | /**
194 | * 获得撞击点y轴坐标
195 | *
196 | * @return
197 | */
198 | public int getKnockPointY() {
199 | return UseCustomPonit ? ky : getCy();
200 | }
201 |
202 | /**
203 | * @param number
204 | */
205 | public void setStarNumber(int number) {
206 | this.starNumber = number;
207 | }
208 |
209 |
210 | public float getMeteorStartX() {
211 | return (meteor.getRight() + meteor.getLeft()) / 2 - getLeft();
212 | }
213 |
214 | public float getMeteorStartY() {
215 | return (meteor.getTop() + meteor.getBottom()) / 2 - getTop();
216 | }
217 |
218 | /**
219 | * 获取流星x轴偏移量
220 | *
221 | * @return
222 | */
223 | private int getMeteorTranslateX() {
224 | return getMeteorTranslate(getKnockPointX() + getLeft(), meteor.getLeft(), meteor.getWidth());
225 | }
226 |
227 | /**
228 | * 获取流星y轴偏移量
229 | *
230 | * @return
231 | */
232 | private int getMeteorTranslateY() {
233 | return getMeteorTranslate(getKnockPointY() + getTop(), meteor.getTop(), meteor.getWidth());
234 | }
235 |
236 | /**
237 | * 计算流星偏移量
238 | *
239 | * @param end 结束坐标
240 | * @param start 初始坐标
241 | * @param dia 流星直径
242 | * @return
243 | */
244 | private int getMeteorTranslate(int end, int start, int dia) {
245 | return end - (start + dia / 2);
246 | }
247 |
248 |
249 | /**
250 | * 初始化流星的动画
251 | */
252 | private void initMeteorAnim() {
253 | minRadius = meteor.getWidth() / 2;
254 | maxRadius = UseCustomPonit ? getDiagonal() : getDiagonal() / 2;
255 | arcAnim = new ArcTranslateAnimation(0, getMeteorTranslateX(), 0, getMeteorTranslateY());
256 | arcAnim.setDuration(arcAnimTime);
257 | arcAnim.setAnimationListener(this);
258 |
259 | ObjectAnimator xAnim = ObjectAnimator.ofFloat(meteor,"translationX",getMeteorTranslateX());
260 | ObjectAnimator yAnim = ObjectAnimator.ofFloat(meteor,"translationY",getMeteorTranslateY());
261 | Log.i("etong","translation X: "+(-getMeteorTranslateX()));
262 | Log.i("etong","translation Y: "+(-getMeteorTranslateY()));
263 |
264 | animatorSet = new AnimatorSet();
265 | animatorSet.playTogether(xAnim,yAnim);
266 | animatorSet.addListener(new Animator.AnimatorListener() {
267 | @Override
268 | public void onAnimationStart(Animator animator) {
269 |
270 | }
271 |
272 | @Override
273 | public void onAnimationEnd(Animator animator) {
274 | ZoomIn();
275 | meteor.setVisibility(View.GONE);
276 | }
277 |
278 | @Override
279 | public void onAnimationCancel(Animator animator) {
280 |
281 | }
282 |
283 | @Override
284 | public void onAnimationRepeat(Animator animator) {
285 |
286 | }
287 | });
288 |
289 | }
290 |
291 | public void startMeteorAnim() {
292 | // meteor.startAnimation(arcAnim);
293 | animatorSet.start();
294 | }
295 |
296 |
297 | private void init() {
298 |
299 | orange = getResources().getColor(R.color.orange);
300 |
301 | setWillNotDraw(false);
302 |
303 | density = getResources().getDisplayMetrics().density;
304 |
305 | minRadius = 0;
306 |
307 | increase = (int) (8 * density);
308 |
309 | paint = new Paint();
310 | paint.setColor(orange);
311 | paint.setAntiAlias(true);//抗锯齿
312 |
313 | }
314 |
315 | /**
316 | * 设置画笔颜色
317 | *
318 | * @param color
319 | */
320 | public void setPaintColor(int color) {
321 | paint.setColor(color);
322 | }
323 |
324 | /**
325 | * 获取画笔颜色
326 | *
327 | * @return
328 | */
329 | public int getPaintColor() {
330 | return paint.getColor();
331 | }
332 |
333 | @Override
334 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
335 | super.onLayout(changed, l, t, r, b);
336 | //确保view的高宽和定位已经初始化完成,然后才开始动画
337 | animAble = true;
338 | if (!isInEditMode()) {
339 | initMeteorAnim();
340 | mCircle = new Circle(getMeteorStartX(), getMeteorStartY(), meteor.getWidth() / 2, paint);
341 | }
342 | }
343 |
344 | @Override
345 | protected void onDraw(Canvas canvas) {
346 | super.onDraw(canvas);
347 | //为了UI编辑界面拖动的控件可以看,xml编辑模式下,此部分代码不执行。
348 | if (!isInEditMode()) {
349 | if (starNumber < 2) {//画出单个圈圈的动画
350 | canvas.drawCircle(getKnockPointX(), getKnockPointY(), radius, paint);
351 | // mCircle.draw(canvas);
352 | } else {//画出多个圈圈的动画
353 | for (int i = 0; i < starNumber; i++) {
354 | canvas.drawCircle(randomCx(), randomCy(), radius, paint);
355 | }
356 | }
357 | }
358 | }
359 |
360 | /**
361 | * 随机产生圆点x轴坐标
362 | *
363 | * @return
364 | */
365 | private int randomCx() {
366 | return randomCenter(getWidth());
367 | }
368 |
369 | /**
370 | * 随机产生圆点x轴坐标
371 | *
372 | * @return
373 | */
374 | private int randomCy() {
375 | return randomCenter(getHeight());
376 | }
377 |
378 | /**
379 | * 随机产生圆点坐标
380 | *
381 | * @return
382 | */
383 | private int randomCenter(int scope) {
384 | return (int) (Math.random() * scope);
385 | }
386 |
387 | /**
388 | * 获取画布中心点x坐标
389 | *
390 | * @return
391 | */
392 | private int getCx() {
393 | return (getRight() - getLeft()) / 2;
394 | }
395 |
396 | /**
397 | * 获取画布中心点y坐标
398 | *
399 | * @return
400 | */
401 | private int getCy() {
402 | return (getBottom() - getTop()) / 2;
403 | }
404 |
405 | /**
406 | * 放大
407 | */
408 | public void ZoomIn() {
409 | ValueAnimator valueAnimator = ValueAnimator.ofInt(minRadius, maxRadius);
410 | valueAnimator.setDuration(500);
411 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
412 | @Override
413 | public void onAnimationUpdate(ValueAnimator valueAnimator) {
414 | Integer value = (Integer) valueAnimator.getAnimatedValue();
415 | radius = minRadius + value;
416 | invalidate();
417 | }
418 | });
419 | valueAnimator.start();
420 | }
421 |
422 | /**
423 | * 缩小
424 | */
425 | public void ZoomOut() {
426 | ValueAnimator valueAnimator = ValueAnimator.ofInt(minRadius, (int) maxRadius);
427 | valueAnimator.setDuration(300);
428 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
429 | @Override
430 | public void onAnimationUpdate(ValueAnimator valueAnimator) {
431 | Integer value = (Integer) valueAnimator.getAnimatedValue();
432 | radius = maxRadius - value;
433 | invalidate();
434 | }
435 | });
436 | valueAnimator.start();
437 | valueAnimator.addListener(new Animator.AnimatorListener() {
438 | @Override
439 | public void onAnimationStart(Animator animator) {
440 |
441 | }
442 |
443 | @Override
444 | public void onAnimationEnd(Animator animator) {
445 | Log.i("etong","translation X: "+(-getMeteorTranslateX()));
446 | Log.i("etong","translation Y: "+(-getMeteorTranslateY()));
447 | ObjectAnimator xAnim = ObjectAnimator.ofFloat(meteor,"translationX",0);
448 | ObjectAnimator yAnim = ObjectAnimator.ofFloat(meteor,"translationY",0);
449 |
450 | AnimatorSet animatorSet = new AnimatorSet();
451 | animatorSet.playTogether(xAnim,yAnim);
452 |
453 | meteor.setVisibility(View.VISIBLE);
454 |
455 | animatorSet.start();
456 | }
457 |
458 | @Override
459 | public void onAnimationCancel(Animator animator) {
460 |
461 | }
462 |
463 | @Override
464 | public void onAnimationRepeat(Animator animator) {
465 |
466 | }
467 | });
468 | }
469 |
470 | public void boom(){
471 | new Thread(new Runnable() {
472 | @Override
473 | public void run() {
474 |
475 | //如果View高宽位置未初始化完成,线程等待
476 | while (!animAble) {
477 | try {
478 | Thread.sleep(100);
479 | } catch (Exception e) {
480 | e.printStackTrace();
481 | }
482 | }
483 |
484 | float input = arcAnimTime/refreshTime;
485 | //开始动画
486 | for (int i = refreshTime; i < arcAnimTime; i = i + refreshTime) {
487 | try {
488 | increase = new AccelerateDecelerateInterpolator().getInterpolation(input);
489 | Thread.sleep(refreshTime);
490 | //执行circle放大动画
491 | mCircle.Zoom(increase);
492 | postInvalidate();
493 | } catch (Exception e) {
494 | e.printStackTrace();
495 | }
496 | }
497 |
498 | }
499 | }).start();
500 | }
501 |
502 | /**
503 | * 用线程改变圈圈大小,通知主线程画出圈圈
504 | */
505 | public void drawCircle() {
506 | new Thread(new Runnable() {
507 | @Override
508 | public void run() {
509 |
510 | //如果View高宽位置未初始化完成,线程等待
511 | while (!animAble) {
512 | try {
513 | Thread.sleep(100);
514 | } catch (Exception e) {
515 | e.printStackTrace();
516 | }
517 | }
518 |
519 | //开始动画
520 | for (int i = 80; i < arcAnimTime; i = i + refreshTime) {
521 | try {
522 | Thread.sleep(refreshTime);
523 |
524 | float interpolatedTime = (float)i / arcAnimTime;
525 | AccelerateDecelerateInterpolator interpolator = new AccelerateDecelerateInterpolator();
526 | interpolatedTime = interpolator.getInterpolation(interpolatedTime);
527 |
528 | float radius = maxRadius * interpolatedTime;
529 | //执行circle放大动画
530 | mCircle.Zoom(radius);
531 |
532 | // mCircle.moveTo(((ArcTranslateAnimation)(meteor.getAnimation())).getInterpolatorTime(), getMeteorStartX(), getKnockPointX(), getMeteorStartY(), getKnockPointY());
533 | mCircle.moveTo(interpolatedTime, getMeteorStartX(), getKnockPointX(), getMeteorStartY(), getKnockPointY());
534 | postInvalidate();
535 | } catch (Exception e) {
536 | e.printStackTrace();
537 | }
538 | }
539 |
540 | }
541 | }).start();
542 |
543 |
544 |
545 | }
546 |
547 |
548 | public void starFall() {
549 |
550 | }
551 |
552 | /**
553 | * 获取圈圈最大半径
554 | *
555 | * @return
556 | */
557 | public int getMaxRadius() {
558 | return maxRadius;
559 | }
560 |
561 | /**
562 | * 计算画布对角线长度
563 | *
564 | * @return
565 | */
566 | public int getDiagonal() {
567 | return (int) Math.sqrt(Math.pow((double) getHeight(), 2) + Math.pow((double) getWidth(), 2));
568 | }
569 |
570 |
571 | @Override
572 | public void onAnimationStart(Animation animation) {
573 | drawCircle();
574 | }
575 |
576 | @Override
577 | public void onAnimationEnd(Animation animation) {
578 | meteor.setVisibility(View.GONE);
579 | }
580 |
581 | @Override
582 | public void onAnimationRepeat(Animation animation) {
583 | }
584 | }
585 |
--------------------------------------------------------------------------------
/app/src/main/java/com/etong/canvasview_master/app/CircleDrawable.java:
--------------------------------------------------------------------------------
1 | package com.etong.canvasview_master.app;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.ColorFilter;
5 | import android.graphics.Paint;
6 | import android.graphics.drawable.Animatable;
7 | import android.graphics.drawable.Drawable;
8 |
9 | /**
10 | * Created by Administrator on 2014/8/27.
11 | */
12 | public class CircleDrawable extends Drawable implements Animatable {
13 |
14 | public int cx;
15 | public int cy;
16 | public int radius;
17 | public Paint paint;
18 |
19 | private boolean running = false;
20 |
21 |
22 | public CircleDrawable(){
23 |
24 | }
25 |
26 | @Override
27 | public void start() {
28 | running = true;
29 |
30 | }
31 |
32 | @Override
33 | public void stop() {
34 | running = false;
35 |
36 | }
37 |
38 | @Override
39 | public boolean isRunning() {
40 | return running;
41 | }
42 |
43 | @Override
44 | public void draw(Canvas canvas) {
45 | canvas.drawCircle(cx,cy,radius,paint);
46 | }
47 |
48 | @Override
49 | public void setAlpha(int i) {
50 |
51 | }
52 |
53 | @Override
54 | public void setColorFilter(ColorFilter colorFilter) {
55 |
56 | }
57 |
58 | @Override
59 | public int getOpacity() {
60 | return 0;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/etong/canvasview_master/app/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.etong.canvasview_master.app;
2 |
3 | import android.app.ListActivity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.view.Menu;
7 | import android.view.MenuItem;
8 | import android.view.View;
9 | import android.widget.ArrayAdapter;
10 | import android.widget.ListView;
11 |
12 |
13 | public class MainActivity extends ListActivity {
14 |
15 | private String [] str = {"CircleCanvasBase","CircleCanvas with ImageView"};
16 |
17 | public MainActivity getThis(){
18 | return MainActivity.this;
19 | }
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | setContentView(android.R.layout.list_content);
25 |
26 | ListView listView = getListView();
27 | listView.setAdapter(new ArrayAdapter(this,android.R.layout.simple_list_item_1,str));
28 | }
29 |
30 | @Override
31 | protected void onListItemClick(ListView l, View v, int position, long id) {
32 | switch (position){
33 |
34 | case 0:
35 | goToActivity(CircleCanvasDemo1.class);
36 | break;
37 | case 1:
38 | goToActivity(MeteorActivity.class);
39 | break;
40 | }
41 | }
42 |
43 | @Override
44 | public boolean onCreateOptionsMenu(Menu menu) {
45 |
46 | // Inflate the menu; this adds items to the action bar if it is present.
47 | getMenuInflater().inflate(R.menu.main, menu);
48 | return true;
49 | }
50 |
51 | @Override
52 | public boolean onOptionsItemSelected(MenuItem item) {
53 | // Handle action bar item clicks here. The action bar will
54 | // automatically handle clicks on the Home/Up button, so long
55 | // as you specify a parent activity in AndroidManifest.xml.
56 | int id = item.getItemId();
57 | if (id == R.id.action_settings) {
58 | return true;
59 | }
60 | return super.onOptionsItemSelected(item);
61 | }
62 |
63 | public void goToActivity(Class> c){
64 | Intent intent = new Intent(this,c);
65 | startActivity(intent);
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/java/com/etong/canvasview_master/app/MeteorActivity.java:
--------------------------------------------------------------------------------
1 | package com.etong.canvasview_master.app;
2 |
3 | import android.support.v7.app.ActionBarActivity;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.Menu;
7 | import android.view.MenuItem;
8 | import android.view.View;
9 | import android.view.animation.AnimationSet;
10 | import android.widget.Button;
11 | import android.widget.ImageButton;
12 | import android.widget.ImageView;
13 |
14 | import com.nineoldandroids.animation.Animator;
15 | import com.nineoldandroids.animation.AnimatorSet;
16 | import com.nineoldandroids.animation.ObjectAnimator;
17 |
18 | public class MeteorActivity extends ActionBarActivity implements View.OnClickListener {
19 |
20 | private CircleCanvasView circleCanvas;
21 |
22 | private ImageView rb;
23 |
24 | private ImageView imageView;
25 |
26 | private ImageButton imageButton;
27 |
28 | private ImageButton imageButton2;
29 |
30 | AnimatorSet animatorSet;
31 |
32 | @Override
33 | protected void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_meteor);
36 |
37 | findAllView();
38 |
39 | setupAnim();
40 |
41 | setAlllistener();
42 | }
43 |
44 | private void findAllView() {
45 |
46 | rb = (ImageView) findViewById(R.id.imageView2);
47 |
48 | imageView = (ImageView) findViewById(R.id.imageView);
49 |
50 | imageButton = (ImageButton) findViewById(R.id.imageButton);
51 | imageButton2 = (ImageButton) findViewById(R.id.imageButton2);
52 |
53 | circleCanvas = (CircleCanvasView) findViewById(R.id.view);
54 | circleCanvas.setMeteor(rb);
55 | // circleCanvas.setKnockPoint(200,100);
56 | // circleCanvas.setStarNumber(2);
57 | }
58 |
59 | private void setupAnim() {
60 | ObjectAnimator xAnimator = ObjectAnimator.ofFloat(rb, "translationX", -100f);
61 | ObjectAnimator yAnimator = ObjectAnimator.ofFloat(rb, "translationY", 100f);
62 |
63 | animatorSet = new AnimatorSet();
64 | animatorSet.setDuration(500);
65 | animatorSet.playTogether(xAnimator,yAnimator);
66 |
67 | }
68 |
69 | private void setAlllistener(){
70 | rb.setOnClickListener(this);
71 | }
72 |
73 |
74 | @Override
75 | public boolean onCreateOptionsMenu(Menu menu) {
76 |
77 | // Inflate the menu; this adds items to the action bar if it is present.
78 | getMenuInflater().inflate(R.menu.main, menu);
79 | return true;
80 | }
81 |
82 | @Override
83 | public boolean onOptionsItemSelected(MenuItem item) {
84 | // Handle action bar item clicks here. The action bar will
85 | // automatically handle clicks on the Home/Up button, so long
86 | // as you specify a parent activity in AndroidManifest.xml.
87 | int id = item.getItemId();
88 | if (id == R.id.action_settings) {
89 | circleCanvas.ZoomOut();
90 | return true;
91 | }
92 | return super.onOptionsItemSelected(item);
93 | }
94 |
95 | @Override
96 | public void onClick(View view) {
97 | if(view == rb){
98 | Log.i("etong","click");
99 | circleCanvas.startMeteorAnim();
100 | }
101 | }
102 |
103 | @Override
104 | public void onBackPressed() {
105 | // super.onBackPressed();
106 | circleCanvas.ZoomOut();
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/com/etong/canvasview_master/app/MyCircle.java:
--------------------------------------------------------------------------------
1 | package com.etong.canvasview_master.app;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.util.AttributeSet;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.RelativeLayout;
12 |
13 | /**
14 | * Created by Administrator on 14-8-5.
15 | */
16 | public class MyCircle extends RelativeLayout {
17 |
18 | private Paint paint;
19 |
20 | public final static int black = 0x70000000;//黑色
21 |
22 | public final static int white = 0xddffffff;//白色
23 |
24 | public int orange;
25 |
26 | private int minRadius;
27 |
28 | private int radius;
29 |
30 | private int cx;
31 |
32 | private int cy;
33 |
34 | public int increase;
35 |
36 | private boolean animAble = false;
37 |
38 | private boolean wtf = false;
39 |
40 | public MyCircle(Context context) {
41 | super(context);
42 | init();
43 | }
44 |
45 | public MyCircle(Context context, AttributeSet attrs) {
46 | super(context, attrs);
47 | init();
48 | }
49 |
50 | private void initAttrs(Context context, AttributeSet attrs) {
51 |
52 | }
53 |
54 | private void init() {
55 |
56 | orange = getResources().getColor(R.color.orange);
57 |
58 | setWillNotDraw(false);
59 |
60 | float density = getResources().getDisplayMetrics().density;
61 |
62 | minRadius = 0;
63 |
64 | increase = (int) (10 * density);
65 |
66 | paint = new Paint();
67 | paint.setColor(orange);
68 | paint.setAntiAlias(true);//抗锯齿
69 |
70 | }
71 |
72 | /**
73 | * 设置画笔颜色
74 | *
75 | * @param color
76 | */
77 | public void setColor(int color) {
78 | paint.setColor(color);
79 | }
80 |
81 | /**
82 | * 获取画笔颜色
83 | *
84 | * @return
85 | */
86 | public int getColor() {
87 | return paint.getColor();
88 | }
89 |
90 | @Override
91 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
92 | super.onLayout(changed, l, t, r, b);
93 | //确保view的高宽和定位已经初始化完成,然后才开始动画
94 | animAble = true;
95 | }
96 |
97 | @Override
98 | protected void onDraw(Canvas canvas) {
99 | super.onDraw(canvas);
100 | if (!isInEditMode()) {
101 | canvas.drawCircle(getCx(), getCy(), radius, paint);
102 | }
103 | }
104 |
105 | /**
106 | * 获取圈圈圆点x坐标
107 | *
108 | * @return
109 | */
110 | public int getCx() {
111 | return (getRight() - getLeft()) / 2;
112 | }
113 |
114 | /**
115 | * 获取圈圈圆点y坐标
116 | *
117 | * @return
118 | */
119 | public int getCy() {
120 | return (getBottom() - getTop()) / 2;
121 | }
122 |
123 | public void setCX(int cx) {
124 | this.cx = cx;
125 | }
126 |
127 | public void setCY(int cy) {
128 | this.cy = cy;
129 | }
130 |
131 |
132 | public void drawCircle() {
133 | new Thread(new Runnable() {
134 | @Override
135 | public void run() {
136 |
137 | //如果View高宽位置未初始化完成,线程等待
138 | while (!animAble) {
139 | try {
140 | Thread.sleep(200);
141 | } catch (Exception e) {
142 | e.printStackTrace();
143 | }
144 | }
145 |
146 | //开始动画
147 | for (int i = minRadius; i < getDiagonal(); i = i + increase) {
148 | try {
149 | Thread.sleep(20);
150 | radius = i;
151 | // paint.setColor(getResources().getColor(android.R.color.transparent));
152 | postInvalidate();
153 | } catch (Exception e) {
154 | e.printStackTrace();
155 | }
156 | }
157 |
158 | }
159 | }).start();
160 | }
161 |
162 | /**
163 | * 获取对角线粗略估算
164 | *
165 | * @return
166 | */
167 | public int getDiagonal() {
168 | return (getHeight() + getWidth()) / 2;
169 | }
170 |
171 | }
172 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_out_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/app/src/main/res/drawable-hdpi/add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/app/src/main/res/drawable-mdpi/add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/app/src/main/res/drawable-xhdpi/add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/app/src/main/res/drawable-xxhdpi/add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circle_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_circle_canvas_demo1.xml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
21 |
22 |
29 |
30 |
37 |
38 |
46 |
47 |
55 |
56 |
63 |
64 |
71 |
72 |
79 |
80 |
87 |
88 |
95 |
96 |
103 |
104 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_meteor.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
16 |
17 |
24 |
25 |
33 |
34 |
42 |
43 |
51 |
52 |
53 |
54 |
55 |
67 |
68 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/circle_canvas_demo1.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #e8520f
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CanvasView-master
5 | Hello world!
6 | Settings
7 | CircleCanvasDemo1
8 | MainActivity
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:0.12.+'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | mavenCentral()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/build/intermediates/dex-cache/cache.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
16 |
22 |
28 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Aug 12 09:42:40 CST 2014
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/screenshots/canvasLayout.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/screenshots/canvasLayout.gif
--------------------------------------------------------------------------------
/screenshots/canvasLayout1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RoyWallace/CanvasView-master/345e809de1647d6517b799eea1274773a8f63de1/screenshots/canvasLayout1.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------