├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ ├── ic_brush_black_24dp.png
│ │ │ │ ├── ic_clear_black_24dp.png
│ │ │ │ ├── ic_edit_black_24dp.png
│ │ │ │ ├── ic_palette_black_24dp.png
│ │ │ │ ├── ic_rudder_black_24dp.png
│ │ │ │ ├── ic_left_revoke_black_24dp.png
│ │ │ │ └── ic_right_revoke_black_24dp.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── drawable-mdpi
│ │ │ │ ├── ic_brush_black_24dp.png
│ │ │ │ ├── ic_clear_black_24dp.png
│ │ │ │ ├── ic_edit_black_24dp.png
│ │ │ │ ├── ic_rudder_black_24dp.png
│ │ │ │ ├── ic_palette_black_24dp.png
│ │ │ │ ├── ic_left_revoke_black_24dp.png
│ │ │ │ └── ic_right_revoke_black_24dp.png
│ │ │ ├── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── drawables.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── strings.xml
│ │ │ ├── layout
│ │ │ │ ├── menu_control_bar.xml
│ │ │ │ ├── content_drawing_broad.xml
│ │ │ │ ├── activity_drawing_broad.xml
│ │ │ │ ├── app_bar_drawing_broad.xml
│ │ │ │ ├── nav_header_drawing_broad.xml
│ │ │ │ └── activity_main.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── drawable
│ │ │ │ ├── side_nav_bar.xml
│ │ │ │ └── ic_launcher_background.xml
│ │ │ ├── drawable-v21
│ │ │ │ ├── ic_menu_send.xml
│ │ │ │ ├── ic_menu_slideshow.xml
│ │ │ │ ├── ic_menu_gallery.xml
│ │ │ │ ├── ic_menu_manage.xml
│ │ │ │ ├── ic_menu_camera.xml
│ │ │ │ └── ic_menu_share.xml
│ │ │ ├── menu
│ │ │ │ ├── drawing_broad.xml
│ │ │ │ └── activity_drawing_broad_drawer.xml
│ │ │ └── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── zdc
│ │ │ │ └── broad
│ │ │ │ ├── comm
│ │ │ │ ├── PaintViewCallBack.java
│ │ │ │ ├── CommUndo.java
│ │ │ │ ├── CommHandwriting.java
│ │ │ │ ├── CommCanvas.java
│ │ │ │ └── PaintConstants.java
│ │ │ │ ├── pens
│ │ │ │ ├── ShapesInterface.java
│ │ │ │ ├── FirstCurrentPosition.java
│ │ │ │ ├── Shapable.java
│ │ │ │ ├── PlainPen.java
│ │ │ │ ├── BlurPen.java
│ │ │ │ ├── EmbossPen.java
│ │ │ │ ├── ClearAll.java
│ │ │ │ ├── Eraser.java
│ │ │ │ └── PenAbstract.java
│ │ │ │ ├── shapes
│ │ │ │ ├── Curv.java
│ │ │ │ ├── Line.java
│ │ │ │ ├── Rectangle.java
│ │ │ │ ├── Oval.java
│ │ │ │ ├── Circle.java
│ │ │ │ ├── Square.java
│ │ │ │ └── ShapeAbstract.java
│ │ │ │ ├── tools
│ │ │ │ └── BitmapUtils.java
│ │ │ │ ├── widget
│ │ │ │ ├── ColorView.java
│ │ │ │ └── ColorPickerDialog.java
│ │ │ │ ├── simple
│ │ │ │ └── MainActivity.java
│ │ │ │ └── Drawing.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── tst
│ │ │ └── drawbroad
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── tst
│ │ └── drawbroad
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── screenshot
├── one.png
└── two.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .idea
├── encodings.xml
├── vcs.xml
├── misc.xml
├── runConfigurations.xml
└── gradle.xml
├── .gitignore
├── gradle.properties
├── gradlew.bat
├── README.md
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/screenshot/one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/screenshot/one.png
--------------------------------------------------------------------------------
/screenshot/two.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/screenshot/two.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_brush_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-mdpi/ic_brush_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_clear_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-mdpi/ic_clear_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_edit_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-mdpi/ic_edit_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_brush_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/drawable-mdpi/ic_brush_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_clear_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/drawable-mdpi/ic_clear_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_edit_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/drawable-mdpi/ic_edit_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_rudder_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/drawable-mdpi/ic_rudder_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_palette_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-mdpi/ic_palette_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_rudder_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-mdpi/ic_rudder_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_palette_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/drawable-mdpi/ic_palette_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_left_revoke_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/drawable-mdpi/ic_left_revoke_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_left_revoke_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-mdpi/ic_left_revoke_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_right_revoke_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/mipmap-mdpi/ic_right_revoke_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_right_revoke_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zdc939023/DrawingBoard/HEAD/app/src/main/res/drawable-mdpi/ic_right_revoke_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/comm/PaintViewCallBack.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.comm;
2 |
3 | public interface PaintViewCallBack {
4 | void onHasDraw();
5 | void onTouchDown();
6 | }
7 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/comm/CommUndo.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.comm;
2 |
3 | public interface CommUndo {
4 | void undo();
5 | void redo();
6 | boolean canUndo();
7 | boolean canRedo();
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/pens/ShapesInterface.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.pens;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | public interface ShapesInterface {
7 | void draw(Canvas canvas, Paint paint);
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/pens/FirstCurrentPosition.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.pens;
2 |
3 | public class FirstCurrentPosition {
4 | public float firstX = 0;
5 | public float firstY = 0;
6 | public float currentX = 0;
7 | public float currentY = 0;
8 | }
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jun 05 14:35:32 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/pens/Shapable.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.pens;
2 |
3 | import android.graphics.Path;
4 |
5 | public interface Shapable {
6 | public Path getPath();
7 |
8 | public FirstCurrentPosition getFirstLastPoint();
9 |
10 | void setShap(ShapesInterface shape);
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 | #00000000
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/menu_control_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/side_nav_bar.xml:
--------------------------------------------------------------------------------
1 |
3 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/comm/CommHandwriting.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.comm;
2 | import android.graphics.Canvas;
3 |
4 | public interface CommHandwriting {
5 | void draw(Canvas canvas);
6 |
7 | void touchDown(float x, float y);
8 |
9 | void touchMove(float x, float y);
10 |
11 | void touchUp(float x, float y);
12 |
13 | boolean hasDraw();
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_send.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 8dp
6 | 176dp
7 | 16dp
8 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/drawing_broad.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/comm/CommCanvas.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.comm;
2 |
3 | import android.graphics.Canvas;
4 |
5 | public class CommCanvas extends Canvas implements Cloneable {
6 | public CommCanvas clone() {
7 | CommCanvas o = null;
8 | try {
9 | o = (CommCanvas) super.clone();
10 | } catch (CloneNotSupportedException e) {
11 | e.printStackTrace();
12 | }
13 | return o;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/test/java/com/tst/drawbroad/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.tst.drawbroad;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_slideshow.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_gallery.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_manage.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/shapes/Curv.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.shapes;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.zdc.broad.pens.Shapable;
7 |
8 | public class Curv extends ShapeAbstract {
9 |
10 | public Curv(Shapable paintTool) {
11 | super(paintTool);
12 | }
13 |
14 | @Override
15 | public void draw(Canvas canvas, Paint paint) {
16 | super.draw(canvas, paint);
17 | canvas.drawPath(mPath, paint);
18 | }
19 |
20 | @Override
21 | public String toString() {
22 | return "curv";
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/shapes/Line.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.shapes;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.zdc.broad.pens.Shapable;
7 |
8 |
9 | public class Line extends ShapeAbstract {
10 |
11 | public Line(Shapable paintTool) {
12 | super(paintTool);
13 | }
14 |
15 | @Override
16 | public void draw(Canvas canvas,Paint paint) {
17 | super.draw(canvas, paint);
18 | canvas.drawLine(x1, y1, x2, y2, paint);
19 | }
20 |
21 | @Override
22 | public String toString() {
23 | return " line";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/shapes/Rectangle.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.shapes;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.zdc.broad.pens.Shapable;
7 |
8 |
9 | public class Rectangle extends ShapeAbstract {
10 |
11 | public Rectangle (Shapable paintTool) {
12 | super(paintTool);
13 | }
14 |
15 | @Override
16 | public void draw(Canvas canvas, Paint paint) {
17 | super.draw(canvas, paint);
18 | canvas.drawRect(x1, y1, x2, y2, paint);
19 | }
20 |
21 | @Override
22 | public String toString() {
23 | return "rectangle";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_drawing_broad.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/drawables.xml:
--------------------------------------------------------------------------------
1 |
2 | - @android:drawable/ic_menu_camera
3 | - @android:drawable/ic_menu_gallery
4 | - @android:drawable/ic_menu_slideshow
5 | - @android:drawable/ic_menu_manage
6 | - @android:drawable/ic_menu_share
7 | - @android:drawable/ic_menu_send
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_camera.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/pens/PlainPen.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.pens;
2 |
3 | import android.graphics.Paint;
4 |
5 | import com.zdc.broad.comm.CommHandwriting;
6 |
7 |
8 | //普通画笔
9 | public class PlainPen extends PenAbstract implements CommHandwriting {
10 | public PlainPen(int size, int penColor) {
11 | this(size,penColor,Paint.Style.STROKE);
12 | }
13 |
14 | public PlainPen(int size, int penColor,Paint.Style style ) {
15 | super(size, penColor,style);
16 | }
17 |
18 | @Override
19 | public String toString() {
20 | return "\tplainPen: " + "\tshap: " + currentShape + "\thasDraw: "
21 | + hasDraw() + "\tsize: " + penSize + "\tstyle:" +style;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/shapes/Oval.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.shapes;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.graphics.RectF;
6 |
7 | import com.zdc.broad.pens.Shapable;
8 |
9 |
10 | public class Oval extends ShapeAbstract {
11 |
12 | RectF mRectF;
13 | public Oval(Shapable paintTool) {
14 | super(paintTool);
15 | mRectF = new RectF();
16 | }
17 |
18 | @Override
19 | public void draw(Canvas canvas, Paint paint) {
20 | super.draw(canvas, paint);
21 | mRectF.set(x1, y1, x2, y2);
22 | canvas.drawOval(mRectF, paint);
23 | }
24 |
25 | @Override
26 | public String toString() {
27 | return " oval";
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_share.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/shapes/Circle.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.shapes;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.zdc.broad.pens.Shapable;
7 |
8 |
9 | public class Circle extends ShapeAbstract {
10 |
11 | public Circle(Shapable paintTool) {
12 | super(paintTool);
13 | }
14 |
15 | @Override
16 | public void draw(Canvas canvas, Paint paint) {
17 | if (canvas==null || paint == null) {
18 | return;
19 | }
20 | super.draw(canvas, paint);
21 | float cx = (x1 + x2)/2;
22 | float cy = (y1+y2)/2;
23 | float radius = (float) Math.sqrt(Math.pow(x1 - x2, 2)
24 | + Math.pow(y1 - y2, 2))/2;
25 | canvas.drawCircle(cx, cy, radius, paint);
26 | }
27 |
28 | @Override
29 | public String toString() {
30 | return " circle";
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/pens/BlurPen.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.pens;
2 |
3 | import android.graphics.BlurMaskFilter;
4 | import android.graphics.MaskFilter;
5 | import android.graphics.Paint;
6 |
7 | public class BlurPen extends PenAbstract {
8 |
9 | private MaskFilter mBlur;
10 |
11 | public BlurPen(int penSize, int penColor) {
12 | this(penSize, penColor, Paint.Style.STROKE);
13 | }
14 |
15 | public BlurPen(int size, int penColor, Paint.Style style) {
16 | super(size, penColor, style);
17 | mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
18 | mPenPaint.setMaskFilter(mBlur);
19 | }
20 |
21 | @Override
22 | public String toString() {
23 | return "type:blurPen: " + "\tshap: " + currentShape + "\thasDraw: "
24 | + hasDraw() + "\tsize: " + penSize + "\tstyle:" + style;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/pens/EmbossPen.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.pens;
2 |
3 | import android.graphics.EmbossMaskFilter;
4 | import android.graphics.MaskFilter;
5 | import android.graphics.Paint;
6 |
7 | public class EmbossPen extends PenAbstract {
8 | private MaskFilter mEmboss;
9 |
10 | public EmbossPen(int penSize, int penColor) {
11 | this(penSize, penColor, Paint.Style.STROKE);
12 | }
13 |
14 | public EmbossPen(int size, int penColor, Paint.Style style) {
15 | super(size, penColor, style);
16 | mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);
17 | mPenPaint.setMaskFilter(mEmboss);
18 | }
19 |
20 | @Override
21 | public String toString() {
22 | return "\tEmboss: " + "\tshap: " + currentShape + "\thasDraw: "
23 | + hasDraw() + "\tsize: " + penSize + "\tstyle:" + style;
24 | }
25 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/tst/drawbroad/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.tst.drawbroad;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.tst.drawbroad", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | DrawBroad
3 | DrawingBroadActivity
4 | Open navigation drawer
5 | Close navigation drawer
6 | Android Studio
7 | android.studio@android.com
8 | Navigation header
9 | Settings
10 |
11 | Home
12 | Gallery
13 | Slideshow
14 | Tools
15 | Share
16 | Send
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/shapes/Square.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.shapes;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.zdc.broad.pens.Shapable;
7 |
8 |
9 | public class Square extends ShapeAbstract {
10 |
11 | public Square(Shapable paintTool) {
12 | super(paintTool);
13 | }
14 |
15 | @Override
16 | public void draw(Canvas canvas, Paint paint) {
17 | super.draw(canvas, paint);
18 | if ((y2 > y1 && x2 > x1) || (y2 < y1 && x2 < x1)) {
19 | if (Math.abs(x2 - x1) > Math.abs(y2 - y1)) {
20 | canvas.drawRect(x1, y1, x1 + y2 - y1, y2, paint);
21 | } else {
22 | canvas.drawRect(x1, y1, x2, y1 + x2 - x1, paint);
23 | }
24 | } else {
25 | if (Math.abs(x2 - x1) > Math.abs(y2 - y1)) {
26 | canvas.drawRect(x1, y1, x1 + y1 - y2, y2, paint);
27 | } else {
28 | canvas.drawRect(x1, y1, x2, y1 + x1 - x2, paint);
29 | }
30 | }
31 | }
32 |
33 | @Override
34 | public String toString() {
35 | return "Square";
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/pens/ClearAll.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.pens;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.graphics.PorterDuff;
6 | import android.graphics.PorterDuffXfermode;
7 |
8 | import com.zdc.broad.comm.CommHandwriting;
9 |
10 | public class ClearAll implements CommHandwriting {
11 | private Paint mPaint = new Paint();
12 | private boolean mHasDraw = false;
13 |
14 | public ClearAll() {
15 | }
16 |
17 | @Override
18 | public void draw(Canvas canvas) {
19 | if (null != canvas) {
20 | mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
21 | canvas.drawPaint(mPaint);
22 | }
23 | }
24 |
25 | @Override
26 | public void touchDown(float x, float y) {
27 |
28 | }
29 |
30 | @Override
31 | public void touchMove(float x, float y) {
32 |
33 | }
34 |
35 | @Override
36 | public void touchUp(float x, float y) {
37 |
38 | }
39 |
40 | @Override
41 | public boolean hasDraw() {
42 | return mHasDraw;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/tools/BitmapUtils.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.tools;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.graphics.Rect;
6 |
7 | public class BitmapUtils {
8 |
9 | public static Bitmap duplicateBitmap(Bitmap bmpSrc) {
10 | if (null == bmpSrc) {
11 | return null;
12 | }
13 |
14 | int bmpSrcWidth = bmpSrc.getWidth();
15 | int bmpSrcHeight = bmpSrc.getHeight();
16 |
17 | Bitmap bmpDest = Bitmap.createBitmap(bmpSrcWidth, bmpSrcHeight,
18 | Bitmap.Config.ARGB_8888);
19 | if (null != bmpDest) {
20 | Canvas canvas = new Canvas(bmpDest);
21 | final Rect rect = new Rect(0, 0, bmpSrcWidth, bmpSrcHeight);
22 | canvas.drawBitmap(bmpSrc, rect, rect, null);
23 | }
24 | return bmpDest;
25 | }
26 |
27 | public static void destroyBitmap(Bitmap bitmap){
28 | if (bitmap!=null&&!bitmap.isRecycled()){
29 | bitmap.recycle();
30 | bitmap=null;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/shapes/ShapeAbstract.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.shapes;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.graphics.Path;
6 |
7 | import com.zdc.broad.pens.FirstCurrentPosition;
8 | import com.zdc.broad.pens.Shapable;
9 | import com.zdc.broad.pens.ShapesInterface;
10 |
11 | /**
12 | * 提供shape子类的默认实现
13 | */
14 | public class ShapeAbstract implements ShapesInterface {
15 |
16 | protected Shapable paintTool = null;
17 | protected FirstCurrentPosition firstCurrentPos;
18 | Path mPath;
19 | protected float x1 = 0;
20 | protected float y1 = 0;
21 | protected float x2 = 0;
22 | protected float y2 = 0;
23 |
24 | ShapeAbstract(Shapable paintTool) {
25 | assert(paintTool!=null);
26 | this.paintTool = paintTool;
27 | }
28 |
29 | @Override
30 | public void draw(Canvas canvas, Paint paint) {
31 | firstCurrentPos = paintTool.getFirstLastPoint();
32 | mPath = paintTool.getPath();
33 | x1 = firstCurrentPos.firstX;
34 | y1 = firstCurrentPos.firstY;
35 | x2 = firstCurrentPos.currentX;
36 | y2 = firstCurrentPos.currentY;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_drawing_broad.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | android {
4 | compileSdkVersion 28
5 | defaultConfig {
6 | // applicationId "com.zdc.broad"
7 | minSdkVersion 19
8 | targetSdkVersion 28
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(dir: 'libs', include: ['*.jar'])
23 | implementation 'com.android.support:appcompat-v7:28.0.0'
24 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
25 | implementation 'com.android.support:support-v4:28.0.0'
26 | implementation 'com.android.support:design:28.0.0'
27 | testImplementation 'junit:junit:4.12'
28 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
29 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/activity_drawing_broad_drawer.xml:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/app_bar_drawing_broad.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nav_header_drawing_broad.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
22 |
23 |
29 |
30 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/comm/PaintConstants.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.comm;
2 |
3 | import android.graphics.Color;
4 |
5 | public class PaintConstants {
6 |
7 | private PaintConstants() {
8 |
9 | }
10 |
11 | public static final class ERASER_SIZE {
12 | public static final int SIZE_1 = 60;
13 | }
14 |
15 | public static final class PEN_SIZE {
16 | public static final int SIZE_1 = 2;
17 | public static final int SIZE_2 = 5;
18 | }
19 |
20 | public static final class SHAP {
21 | public static final int CURV = 1;
22 | public static final int LINE = 2;
23 | public static final int RECT = 3;
24 | public static final int CIRCLE = 4;
25 | public static final int OVAL = 5;
26 | public static final int SQUARE = 6;
27 | }
28 |
29 | public static final class PATH {
30 | public static final String SAVE_PATH = "/sdcard/paintPad";
31 | }
32 |
33 | public static final class PEN_TYPE {
34 | public static final int PLAIN_PEN = 1;
35 | public static final int ERASER = 2;
36 | public static final int BLUR = 3;
37 | public static final int EMBOSS = 4;
38 | }
39 |
40 |
41 | public static final class DEFAULT{
42 | public static final int PEN_COLOR = Color.BLACK;
43 | public static final int BACKGROUND_COLOR = Color.parseColor("#AEDEE4");
44 | }
45 |
46 |
47 | public static final int UNDO_STACK_SIZE = 10;
48 |
49 | public static final int COLOR_VIEW_SIZE = 80;
50 |
51 | public static final int LOAD_ACTIVITY = 1;
52 |
53 | public static final int COLOR1 = Color.argb(255, 44, 152, 140);
54 | public static final int COLOR2 = Color.argb(255, 48, 115, 170);
55 | public static final int COLOR3 = Color.argb(255, 139, 26, 99);
56 | public static final int COLOR4 = Color.argb(255, 112, 101, 89);
57 | public static final int COLOR5 = Color.argb(255, 40, 36, 37);
58 | public static final int COLOR6 = Color.argb(255, 226, 226, 226);
59 | public static final int COLOR7 = Color.argb(255, 219, 88, 50);
60 | public static final int COLOR8 = Color.argb(255, 129, 184, 69);
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/widget/ColorView.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.widget;
2 |
3 |
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.graphics.Canvas;
7 | import android.graphics.Color;
8 | import android.graphics.Paint;
9 | import android.graphics.Rect;
10 |
11 | public class ColorView extends android.support.v7.widget.AppCompatRadioButton {
12 |
13 | private static final int STROKE_WIDTH_GRAY = 5;
14 | private static final int STROKE_WIDTH_WITE = 10;
15 | private static final int VIEW_WIDTH = 75;
16 | private static final int VIEW_HEIGHT = 75;
17 |
18 |
19 | private int color = 0;
20 | private Paint mPaint = null;
21 | private Paint mBitmapPaint = null;
22 |
23 | private Rect mRect = null;
24 | private Bitmap mBitmap = null;
25 | private Canvas mCanvas = null;
26 |
27 |
28 | public ColorView(Context context, int color) {
29 | super(context);
30 | this.color = color;
31 | this.setMinimumHeight(VIEW_HEIGHT);
32 | this.setMinimumWidth(VIEW_WIDTH);
33 | mPaint = new Paint();
34 | setmPaint();
35 |
36 | mBitmapPaint = new Paint(Paint.DITHER_FLAG);
37 |
38 | mBitmap = Bitmap.createBitmap(VIEW_HEIGHT, VIEW_WIDTH, Bitmap.Config.ARGB_8888);
39 | mCanvas = new Canvas();
40 | mCanvas.setBitmap(mBitmap);
41 | mRect = new Rect(0, 0, VIEW_HEIGHT, VIEW_WIDTH);
42 | }
43 |
44 |
45 | private void setmPaint() {
46 | mPaint.setDither(true);
47 | mPaint.setAntiAlias(true);
48 | mPaint.setStyle(Paint.Style.STROKE);
49 | mPaint.setStrokeJoin(Paint.Join.ROUND);
50 | mPaint.setStrokeCap(Paint.Cap.ROUND);
51 | }
52 |
53 |
54 | public void setColor(int color) {
55 | this.color = color;
56 | drawCheckedBitmap();
57 | invalidate();
58 | }
59 |
60 | public int getColor() {
61 | return color;
62 | }
63 |
64 | @Override
65 | protected void onDraw(Canvas canvas) {
66 | if (isChecked()) {
67 | drawCheckedBitmap();
68 | } else if (!isChecked()) {
69 | drawUnCheckedBitmap();
70 | }
71 | canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
72 | }
73 |
74 | private void drawUnCheckedBitmap() {
75 | mCanvas.drawColor(color);
76 | }
77 |
78 | private void drawCheckedBitmap() {
79 | mCanvas.drawColor(color);
80 | mPaint.setColor(Color.WHITE);
81 | mPaint.setStrokeWidth(STROKE_WIDTH_WITE);
82 | drawRect();
83 | mPaint.setColor(Color.GRAY);
84 | mPaint.setStrokeWidth(STROKE_WIDTH_GRAY);
85 | drawRect();
86 | }
87 |
88 |
89 | private void drawRect() {
90 | mCanvas.drawRect(mRect, mPaint);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/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 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
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 Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/pens/Eraser.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.pens;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.Paint;
6 | import android.graphics.Path;
7 | import android.graphics.PorterDuff;
8 | import android.graphics.PorterDuffXfermode;
9 |
10 | import com.zdc.broad.comm.CommHandwriting;
11 |
12 | public class Eraser implements CommHandwriting {
13 | // 只有等移动距离超过这个值才会移动
14 | private static final float TOUCH_TOLERANCE = 4.0f;
15 |
16 | private float mCurrentX = 0.0f;
17 | private float mCurrentY = 0.0f;
18 | private Path mPath = new Path();
19 | private Paint mEraserPaint = new Paint();
20 | private boolean mHasDraw = false;
21 | private int eraserSize = 0;
22 |
23 | public Eraser(int eraserSize) {
24 | mEraserPaint.setStrokeWidth(eraserSize);
25 | this.eraserSize = eraserSize;
26 | setUp();
27 | }
28 |
29 | private void setUp() {
30 | // color并不中还要,混色的模式决定了eraser
31 | mEraserPaint.setColor(Color.BLACK);
32 | mEraserPaint.setDither(true);
33 | mEraserPaint.setAntiAlias(true);
34 | mEraserPaint.setStyle(Paint.Style.STROKE);
35 | mEraserPaint.setStrokeJoin(Paint.Join.ROUND);
36 | mEraserPaint.setStrokeCap(Paint.Cap.ROUND);
37 | mEraserPaint
38 | .setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
39 | }
40 |
41 | @Override
42 | public void draw(Canvas canvas) {
43 | if (null != canvas) {
44 | canvas.drawPath(mPath, mEraserPaint);
45 | }
46 | }
47 |
48 | @Override
49 | public void touchDown(float x, float y) {
50 | mPath.reset();
51 | mPath.moveTo(x, y);
52 | mCurrentX = x;
53 | mCurrentY = y;
54 | }
55 |
56 | @Override
57 | public void touchMove(float x, float y) {
58 | if (isMoved(x, y)) {
59 | drawBeziercurve(x, y);
60 | mCurrentX = x;
61 | mCurrentY = y;
62 | mHasDraw = true;
63 | }
64 |
65 | }
66 |
67 | @Override
68 | public void touchUp(float x, float y) {
69 | mPath.lineTo(x, y);
70 | }
71 |
72 | @Override
73 | public boolean hasDraw() {
74 | return mHasDraw;
75 | }
76 |
77 | // 判断是否移动
78 | private boolean isMoved(float x, float y) {
79 | float dx = Math.abs(x - mCurrentX);
80 | float dy = Math.abs(y - mCurrentX);
81 | boolean isMoved = ((dx >= TOUCH_TOLERANCE) || (dy >= TOUCH_TOLERANCE));
82 | return isMoved;
83 | }
84 |
85 | // 画出贝塞尔曲线
86 | private void drawBeziercurve(float x, float y) {
87 | mPath.quadTo(mCurrentX, mCurrentY, (x + mCurrentX) / 2,
88 | (y + mCurrentY) / 2);
89 | }
90 |
91 |
92 | @Override
93 | public String toString() {
94 | return "eraser:" + " size is"+ eraserSize;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Android画板
2 |
3 | 画板中支持 画笔类型,橡皮擦,颜色,撤销与反撤销,以及添加图片等功能
4 |
5 | 效果如下:
6 |
7 |
8 |
9 | 
10 |
11 | 使用方法:
12 |
13 | 第一步
14 |
15 | maven { url 'https://jitpack.io' }
16 |
17 | 第二步
18 |
19 | implementation 'com.gitee.zdcUser:DrawingBoard:1.0.0'
20 |
21 | 使用步骤:
22 |
23 | 由于本例子比较简单,所以就没有打包成一个库,仅提供demo,供需要的自行添加或修改完善,实现自己的需求
24 |
25 | + 1 在布局文件中添加引用
26 | ```
27 |
31 | ```
32 |
33 | + 2 在Activity中进行初始化,并添加撤销与反撤销的回调
34 | ```
35 | paintView=findViewById(R.id.paintView);
36 |
37 | paintView.setCallBack(new PaintViewCallBack() {
38 | @Override
39 | public void onHasDraw() {
40 |
41 | }
42 |
43 | @Override
44 | public void onTouchDown() {
45 |
46 | }
47 | });
48 | paintView.add();
49 | ```
50 | + 3 功能的实现
51 |
52 | ```
53 | @Override
54 | public void onClick(View v) {
55 | int id=v.getId();
56 | switch (id){
57 | case R.id.ib_pencil:
58 | // 设置为铅笔
59 | selectPenType(PENCIL);
60 | break;
61 | case R.id.ib_pen:
62 | //设置为钢笔
63 | selectPenType(PEN);
64 | break;
65 | case R.id.ib_rudder:
66 | //选择橡皮后进行擦除
67 | selectRudder();
68 | break;
69 | case R.id.ib_color:
70 | selectColors();
71 | break;
72 | case R.id.ib_left:
73 | revokeLeft();
74 | break;
75 | case R.id.ib_right:
76 | revokeRight();
77 | break;
78 | case R.id.ib_clear:
79 | clear();
80 | break;
81 | }
82 | }
83 |
84 | private void selectPenType(int penType){
85 | paintView.setPenSize(penType);
86 | paintView.setPenType(PaintConstants.PEN_TYPE.PLAIN_PEN);
87 | }
88 |
89 | private void selectRudder(){
90 | paintView.setPenType(PaintConstants.PEN_TYPE.ERASER);
91 | }
92 |
93 | private void selectColors(){
94 | colorPickerDialog=new ColorPickerDialog(this, new ColorPickerDialog.OnColorChangedListener() {
95 | @Override
96 | public void colorChanged(int color) {
97 | paintView.setPenColor(color);
98 | }
99 | }, Color.BLACK);
100 | colorPickerDialog.show();
101 | }
102 |
103 | private void revokeLeft(){
104 | paintView.undo();
105 | }
106 |
107 | private void revokeRight(){
108 | paintView.redo();
109 | }
110 |
111 | private void clear(){
112 | if (paintView.canRedo()||paintView.canUndo()){
113 | paintView.clearAll(true);
114 | paintView.onHasDraw();
115 | }
116 | }
117 | ```
118 | 简单的使用过程如上,如有不了解可以自己下载demo查看源码。
119 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/pens/PenAbstract.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.pens;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.graphics.Paint.Style;
6 | import android.graphics.Path;
7 |
8 | import com.zdc.broad.comm.CommHandwriting;
9 | import com.zdc.broad.shapes.Curv;
10 |
11 |
12 | /**
13 | * 抽象Pen类,提供Pen的默认实现
14 | */
15 | abstract public class PenAbstract implements CommHandwriting, Shapable {
16 |
17 | private static final float TOUCH_TOLERANCE = 4.0f;
18 | private float mCurrentX = 0.0f;
19 | private float mCurrentY = 0.0f;
20 | private Path mPath = null;
21 | protected Paint mPenPaint = null;
22 | private boolean mHasDraw = false;
23 | protected FirstCurrentPosition mFirstCurrentPosition = null;
24 | protected ShapesInterface currentShape = null;
25 | protected int penSize;
26 | protected Style style;
27 |
28 | public PenAbstract() {
29 | this(0, 0);
30 | }
31 |
32 | protected PenAbstract(int penSize, int penColor) {
33 | this(penSize, penColor, Style.STROKE);
34 | }
35 |
36 | protected PenAbstract(int penSize, int penColor, Style style) {
37 | super();
38 | initPaint(penSize, penColor, style);
39 | mFirstCurrentPosition = new FirstCurrentPosition();
40 | currentShape = new Curv(this);
41 | mPath = new Path();
42 | }
43 |
44 | /**
45 | * 设置Pen的大小
46 | */
47 | public void setPenSize(int width) {
48 | mPenPaint.setStrokeWidth(width);
49 | }
50 |
51 | /**
52 | * 设置PenColor
53 | */
54 | public void setPenColor(int color) {
55 | mPenPaint.setColor(color);
56 | }
57 |
58 | /**
59 | * 保存起始位置
60 | */
61 | private void saveDownPoint(float x, float y) {
62 | mFirstCurrentPosition.firstX = x;
63 | mFirstCurrentPosition.firstY = y;
64 | }
65 |
66 | @Override
67 | public void draw(Canvas canvas) {
68 | if (canvas != null) {
69 | mFirstCurrentPosition.currentX = mCurrentX;
70 | mFirstCurrentPosition.currentY = mCurrentY;
71 | currentShape.draw(canvas, mPenPaint);
72 | }
73 | }
74 |
75 | @Override
76 | public void touchDown(float x, float y) {
77 | saveDownPoint(x, y);
78 | // 每次down的时候都要将path清空,并且重新设置起点
79 | mPath.reset();
80 | // 重新设置起点
81 | mPath.moveTo(x, y);
82 | savePoint(x, y);
83 | }
84 |
85 | @Override
86 | public void touchMove(float x, float y) {
87 | if (isMoved(x, y)) {
88 | // 贝赛尔曲线
89 | drawBeziercurve(x, y);
90 | savePoint(x, y);
91 |
92 | mHasDraw = true;
93 | }
94 | }
95 |
96 | @Override
97 | public void touchUp(float x, float y) {
98 | mPath.lineTo(x, y);
99 | }
100 |
101 | @Override
102 | public boolean hasDraw() {
103 | return mHasDraw;
104 | }
105 |
106 | /**
107 | * 将当前的点保存起来
108 | */
109 | private void savePoint(float x, float y) {
110 | mCurrentX = x;
111 | mCurrentY = y;
112 | }
113 |
114 | private boolean isMoved(float x, float y) {
115 | float dx = Math.abs(x - mCurrentX);
116 | float dy = Math.abs(y - mCurrentY);
117 | boolean isMoved = dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE;
118 | return isMoved;
119 | }
120 |
121 | private void drawBeziercurve(float x, float y) {
122 | mPath.quadTo(mCurrentX, mCurrentY, (x + mCurrentX) / 2,
123 | (y + mCurrentY) / 2);
124 | }
125 |
126 | @Override
127 | public Path getPath() {
128 | return mPath;
129 | }
130 |
131 | @Override
132 | public FirstCurrentPosition getFirstLastPoint() {
133 | return mFirstCurrentPosition;
134 | }
135 |
136 | @Override
137 | public void setShap(ShapesInterface shape) {
138 | currentShape = shape;
139 | }
140 |
141 | protected void initPaint(int penSize, int penColor, Style style) {
142 | mPenPaint = new Paint();
143 | mPenPaint.setStrokeWidth(penSize);
144 | mPenPaint.setColor(penColor);
145 | this.penSize = penSize;
146 | this.style = style;
147 | mPenPaint.setDither(true);
148 | mPenPaint.setAntiAlias(true);
149 | mPenPaint.setStyle(style);
150 | mPenPaint.setStrokeJoin(Paint.Join.ROUND);
151 | mPenPaint.setStrokeCap(Paint.Cap.ROUND);
152 | }
153 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/simple/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.simple;
2 |
3 | import android.graphics.Color;
4 | import android.support.design.widget.FloatingActionButton;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.os.Bundle;
7 | import android.view.View;
8 | import android.widget.ImageButton;
9 |
10 | //import com.tst.drawbroad.R;
11 | import com.zdc.broad.Drawing;
12 | import com.zdc.broad.comm.PaintConstants;
13 | import com.zdc.broad.comm.PaintViewCallBack;
14 | import com.zdc.broad.widget.ColorPickerDialog;
15 |
16 | public class MainActivity extends AppCompatActivity implements View.OnClickListener{
17 | private String TAG=this.getClass().getSimpleName();
18 |
19 | private final int PEN=PaintConstants.PEN_SIZE.SIZE_2;
20 | private final int PENCIL=PaintConstants.PEN_SIZE.SIZE_1 ;
21 | Drawing paintView;
22 | ImageButton ib_pencil,ib_pen,ib_rudder,ib_color,ib_left,ib_right,ib_clear;
23 | ColorPickerDialog colorPickerDialog;
24 | FloatingActionButton fabAdd;
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | // setContentView(R.layout.activity_main);
29 | initView();
30 | }
31 |
32 | private void initView(){
33 | // paintView=findViewById(R.id.paintView);
34 | // ib_pencil=findViewById(R.id.ib_pencil);
35 | // ib_pencil.setOnClickListener(this);
36 | // ib_pen=findViewById(R.id.ib_pen);
37 | // ib_pen.setOnClickListener(this);
38 | // ib_rudder=findViewById(R.id.ib_rudder);
39 | // ib_rudder.setOnClickListener(this);
40 | // ib_color=findViewById(R.id.ib_color);
41 | // ib_color.setOnClickListener(this);
42 | // ib_left=findViewById(R.id.ib_left);
43 | // ib_left.setOnClickListener(this);
44 | // ib_right=findViewById(R.id.ib_right);
45 | // ib_right.setOnClickListener(this);
46 | // ib_clear=findViewById(R.id.ib_clear);
47 | // ib_clear.setOnClickListener(this);
48 | // fabAdd=findViewById(R.id.fab_add);
49 | // fabAdd.setOnClickListener(this);
50 | // paintView.setCallBack(new PaintViewCallBack() {
51 | // @Override
52 | // public void onHasDraw() {
53 | //
54 | // }
55 | //
56 | // @Override
57 | // public void onTouchDown() {
58 | //
59 | // }
60 | // });
61 | paintView.addNewDrawing();
62 | paintView.setBackground(null);
63 | }
64 |
65 | @Override
66 | public void onClick(View v) {
67 | int id=v.getId();
68 | // switch (id){
69 | // case R.id.ib_pencil:
70 | // selectPenType(PENCIL);
71 | // break;
72 | // case R.id.ib_pen:
73 | // selectPenType(PEN);
74 | // break;
75 | // case R.id.ib_rudder:
76 | // selectRudder();
77 | // break;
78 | // case R.id.ib_color:
79 | // selectColors();
80 | // break;
81 | // case R.id.ib_left:
82 | // revokeLeft();
83 | // break;
84 | // case R.id.ib_right:
85 | // revokeRight();
86 | // break;
87 | // case R.id.ib_clear:
88 | // clear();
89 | // break;
90 | // case R.id.fab_add:
91 | // addDraft();
92 | // break;
93 | // }
94 | }
95 |
96 | private void selectPenType(int penType){
97 | paintView.setPenSize(penType);
98 | paintView.setPenType(PaintConstants.PEN_TYPE.PLAIN_PEN);
99 | }
100 |
101 | private void selectRudder(){
102 | paintView.setPenType(PaintConstants.PEN_TYPE.ERASER);
103 | }
104 |
105 | private void selectColors(){
106 | colorPickerDialog=new ColorPickerDialog(this, new ColorPickerDialog.OnColorChangedListener() {
107 | @Override
108 | public void colorChanged(int color) {
109 | paintView.setPenColor(color);
110 | }
111 | }, Color.BLACK);
112 | colorPickerDialog.show();
113 | }
114 |
115 | private void revokeLeft(){
116 | paintView.undo();
117 | }
118 |
119 | private void revokeRight(){
120 | paintView.redo();
121 | }
122 |
123 | private void clear(){
124 | if (paintView.canRedo()||paintView.canUndo()){
125 | paintView.clearAll(true);
126 | paintView.onHasDraw();
127 | }
128 | }
129 |
130 | private void addDraft(){
131 | paintView.addNewDrawing();
132 | paintView.setBackground(null);
133 | paintView.onHasDraw();
134 |
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
13 |
19 |
22 |
31 |
40 |
49 |
58 |
67 |
76 |
87 |
88 |
89 |
90 |
91 |
98 |
105 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
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 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/widget/ColorPickerDialog.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad.widget;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.LinearGradient;
8 | import android.graphics.Paint;
9 | import android.graphics.RectF;
10 | import android.graphics.Shader;
11 | import android.graphics.SweepGradient;
12 | import android.os.Bundle;
13 | import android.view.MotionEvent;
14 | import android.view.View;
15 | import android.widget.LinearLayout;
16 |
17 | public class ColorPickerDialog extends Dialog {
18 |
19 | public interface OnColorChangedListener {
20 | void colorChanged(int color);
21 | }
22 |
23 | private OnColorChangedListener mListener;
24 | private int mInitialColor;
25 | private Context context;
26 |
27 | private static class ColorPickerView extends View {
28 | private Paint mPaint;
29 | private Paint mCenterPaint;
30 | private Paint mHSVPaint;
31 | private final int[] mColors;
32 | private int[] mHSVColors;
33 | private boolean mRedrawHSV;
34 | private OnColorChangedListener mListener;
35 |
36 | ColorPickerView(Context c, OnColorChangedListener l, int color) {
37 | super(c);
38 | mListener = l;
39 | mColors = new int[] { 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF,
40 | 0xFF00FFFF, 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000 };
41 | Shader s = new SweepGradient(0, 0, mColors, null);
42 |
43 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
44 | mPaint.setShader(s);
45 | mPaint.setStyle(Paint.Style.STROKE);
46 | mPaint.setStrokeWidth(80);
47 |
48 | mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
49 | mCenterPaint.setColor(color);
50 | mCenterPaint.setStrokeWidth(5);
51 |
52 | mHSVColors = new int[] { 0xFF000000, color, 0xFFFFFFFF };
53 |
54 | mHSVPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
55 | mHSVPaint.setStrokeWidth(10);
56 |
57 | mRedrawHSV = true;
58 |
59 | }
60 |
61 | private boolean mTrackingCenter;
62 | private boolean mHighlightCenter;
63 |
64 | @Override
65 | protected void onDraw(Canvas canvas) {
66 | float r = CENTER_X - mPaint.getStrokeWidth() * 0.5f;
67 |
68 | canvas.translate(CENTER_X, CENTER_X);
69 | int c = mCenterPaint.getColor();
70 |
71 | if (mRedrawHSV) {
72 | mHSVColors[1] = c;
73 | mHSVPaint.setShader(new LinearGradient(-100, 0, 100, 0,
74 | mHSVColors, null, Shader.TileMode.CLAMP));
75 | }
76 |
77 | canvas.drawOval(new RectF(-r, -r, r, r), mPaint);
78 | canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint);
79 | canvas.drawRect(new RectF(-150, 200, 150, 160), mHSVPaint);
80 |
81 | if (mTrackingCenter) {
82 | mCenterPaint.setStyle(Paint.Style.STROKE);
83 |
84 | if (mHighlightCenter) {
85 | mCenterPaint.setAlpha(0xFF);
86 | } else {
87 | mCenterPaint.setAlpha(0x80);
88 | }
89 | canvas.drawCircle(0, 0,
90 | CENTER_RADIUS + mCenterPaint.getStrokeWidth(),
91 | mCenterPaint);
92 |
93 | mCenterPaint.setStyle(Paint.Style.FILL);
94 | mCenterPaint.setColor(c);
95 | }
96 |
97 | mRedrawHSV = true;
98 | }
99 |
100 | @Override
101 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
102 | setMeasuredDimension(CENTER_X * 2, (CENTER_Y + 25) * 2);
103 | }
104 |
105 | private static final int CENTER_X = 150;
106 | private static final int CENTER_Y = 150;
107 | private static final int CENTER_RADIUS = 50;
108 |
109 | private int ave(int s, int d, float p) {
110 | return s + Math.round(p * (d - s));
111 | }
112 |
113 | private int interpColor(int colors[], float unit) {
114 | if (unit <= 0) {
115 | return colors[0];
116 | }
117 | if (unit >= 1) {
118 | return colors[colors.length - 1];
119 | }
120 |
121 | float p = unit * (colors.length - 1);
122 | int i = (int) p;
123 | p -= i;
124 |
125 | // now p is just the fractional part [0...1) and i is the index
126 | int c0 = colors[i];
127 | int c1 = colors[i + 1];
128 | int a = ave(Color.alpha(c0), Color.alpha(c1), p);
129 | int r = ave(Color.red(c0), Color.red(c1), p);
130 | int g = ave(Color.green(c0), Color.green(c1), p);
131 | int b = ave(Color.blue(c0), Color.blue(c1), p);
132 |
133 | return Color.argb(a, r, g, b);
134 | }
135 |
136 | private static final float PI = 3.1415926f;
137 |
138 | @Override
139 | public boolean onTouchEvent(MotionEvent event) {
140 | float x = event.getX() - CENTER_X;
141 | float y = event.getY() - CENTER_Y;
142 | boolean inCenter = Math.sqrt(x * x + y * y) <= CENTER_RADIUS;
143 |
144 | switch (event.getAction()) {
145 | case MotionEvent.ACTION_DOWN:
146 | mTrackingCenter = inCenter;
147 | if (inCenter) {
148 | mHighlightCenter = true;
149 | invalidate();
150 | break;
151 | }
152 | case MotionEvent.ACTION_MOVE:
153 | if (mTrackingCenter) {
154 | if (mHighlightCenter != inCenter) {
155 | mHighlightCenter = inCenter;
156 | invalidate();
157 | }
158 | } else if ((x >= -150 & x <= 150) && (y <= 200 && y >= 160))
159 | // see
160 | // if
161 | // we're
162 | // in
163 | // the
164 | // hsv
165 | // slider
166 | {
167 | int a, r, g, b, c0, c1;
168 | float p;
169 |
170 | // set the center paint to this color
171 | if (x < 0) {
172 | c0 = mHSVColors[0];
173 | c1 = mHSVColors[1];
174 | p = (x + 150) / 150;
175 | } else {
176 | c0 = mHSVColors[1];
177 | c1 = mHSVColors[2];
178 | p = x / 150;
179 | }
180 |
181 | a = ave(Color.alpha(c0), Color.alpha(c1), p);
182 | r = ave(Color.red(c0), Color.red(c1), p);
183 | g = ave(Color.green(c0), Color.green(c1), p);
184 | b = ave(Color.blue(c0), Color.blue(c1), p);
185 |
186 | mCenterPaint.setColor(Color.argb(a, r, g, b));
187 |
188 | mRedrawHSV = false;
189 | invalidate();
190 | }//确定是在选择的区域里
191 | else if ((Math.pow(x, 2) + Math.pow(y, 2)) < 150 * 150) {
192 | float angle = (float) Math.atan2(y, x);
193 | // need to turn angle [-PI ... PI] into unit [0....1]
194 | float unit = angle / (2 * PI);
195 | if (unit < 0) {
196 | unit += 1;
197 | }
198 | mCenterPaint.setColor(interpColor(mColors, unit));
199 | invalidate();
200 | }
201 | break;
202 | case MotionEvent.ACTION_UP:
203 | if (mTrackingCenter) {
204 | if (inCenter) {
205 | mListener.colorChanged(mCenterPaint.getColor());
206 | }
207 | mTrackingCenter = false; // so we draw w/o halo
208 | invalidate();
209 | }
210 | break;
211 | }
212 | return true;
213 | }
214 | }
215 |
216 | public ColorPickerDialog(Context context, OnColorChangedListener listener,int initialColor) {
217 | super(context);
218 | this.context = context;
219 | mListener = listener;
220 | mInitialColor = initialColor;
221 | }
222 |
223 | @Override
224 | protected void onCreate(Bundle savedInstanceState) {
225 | super.onCreate(savedInstanceState);
226 | // dialog是view的观察者
227 | OnColorChangedListener l = new OnColorChangedListener() {
228 | public void colorChanged(int color) {
229 | // 调用观察者的接口
230 | mListener.colorChanged(color);
231 | dismiss();
232 | }
233 | };
234 | LinearLayout layout = new LinearLayout(context);
235 | layout.addView(new ColorPickerView(getContext(), l, mInitialColor));
236 | layout.setPadding(30, 20, 20, 30);
237 | setContentView(layout);
238 | setCanceledOnTouchOutside(true);
239 | setTitle("选择一个颜色");
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zdc/broad/Drawing.java:
--------------------------------------------------------------------------------
1 | package com.zdc.broad;
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.support.annotation.Nullable;
9 | import android.util.AttributeSet;
10 | import android.util.Log;
11 | import android.view.MotionEvent;
12 | import android.view.View;
13 |
14 | import com.zdc.broad.comm.CommCanvas;
15 | import com.zdc.broad.comm.CommHandwriting;
16 | import com.zdc.broad.comm.CommUndo;
17 | import com.zdc.broad.comm.PaintConstants;
18 | import com.zdc.broad.comm.PaintViewCallBack;
19 | import com.zdc.broad.pens.BlurPen;
20 | import com.zdc.broad.pens.ClearAll;
21 | import com.zdc.broad.pens.EmbossPen;
22 | import com.zdc.broad.pens.Eraser;
23 | import com.zdc.broad.pens.PlainPen;
24 | import com.zdc.broad.pens.Shapable;
25 | import com.zdc.broad.pens.ShapesInterface;
26 | import com.zdc.broad.shapes.Circle;
27 | import com.zdc.broad.shapes.Curv;
28 | import com.zdc.broad.shapes.Line;
29 | import com.zdc.broad.shapes.Oval;
30 | import com.zdc.broad.shapes.Rectangle;
31 | import com.zdc.broad.shapes.Square;
32 | import com.zdc.broad.tools.BitmapUtils;
33 |
34 | import java.util.ArrayList;
35 |
36 | import static com.zdc.broad.comm.PaintConstants.UNDO_STACK_SIZE;
37 |
38 | public class Drawing extends View implements CommUndo,Cloneable {
39 |
40 | private static String TAG="Drawing";
41 |
42 | private CommCanvas commCanvas=null;
43 | /**
44 | * 橡皮擦
45 | */
46 | private Paint eraserPaint=null;
47 | private PaintPadUndoStack padUndoStack=null;
48 | /**
49 | * 画图
50 | */
51 | private Paint drawPaint=null;
52 |
53 | private CommHandwriting handwriting=null;
54 | /**
55 | * 画笔类型
56 | */
57 | private ShapesInterface mCurrentShape=null;
58 |
59 | /**
60 | * 绘制操作的bitmap
61 | */
62 | private Bitmap drawBitmap=null;
63 | /**
64 | * 原图
65 | */
66 | private Bitmap originalBitmap=null;
67 |
68 | /**
69 | * 画板的大小
70 | */
71 | private int drawingBroadWidth=-1,drawingBroadHeight=-1;
72 |
73 | private PaintViewCallBack mCallBack = null;
74 |
75 | /**
76 | * 保存当前的X,Y坐标
77 | */
78 | private float currentX = 300,currentY = 500;
79 | /**
80 | * 需要绘制的形状
81 | */
82 | private int shapeType=0;
83 | /**
84 | * 画笔类型
85 | */
86 | private int paintType= PaintConstants.PEN_TYPE.PLAIN_PEN;
87 | /**
88 | * 画笔颜色
89 | */
90 | private int mPenColor = PaintConstants.DEFAULT.PEN_COLOR;;
91 | /**
92 | * 笔触大小
93 | */
94 | private int mPenSize = PaintConstants.PEN_SIZE.SIZE_1 ;
95 | /**
96 | * 橡皮擦的大小
97 | */
98 | private int mEraserSize = PaintConstants.ERASER_SIZE.SIZE_1;
99 |
100 | /**
101 | * 保存撤销与反撤销的次数
102 | */
103 | private int mStackedSize = UNDO_STACK_SIZE;
104 | private Paint.Style mStyle = Paint.Style.STROKE;
105 |
106 | private boolean isTouchUp = false;
107 |
108 | public void setCallBack(PaintViewCallBack mCallBack){
109 | this.mCallBack=mCallBack;
110 | }
111 |
112 |
113 | public Drawing(Context context) {
114 | super(context,null);
115 | }
116 |
117 | public Drawing(Context context,@Nullable AttributeSet attrs) {
118 | super(context, attrs);
119 | init();
120 | }
121 |
122 | public Drawing(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
123 | super(context, attrs, defStyleAttr);
124 | init();
125 | }
126 |
127 | private void init(){
128 | commCanvas=new CommCanvas();
129 | drawPaint=new Paint(Paint.DITHER_FLAG);
130 | padUndoStack = new PaintPadUndoStack(this, mStackedSize);
131 | paintType= PaintConstants.PEN_TYPE.PLAIN_PEN;
132 | shapeType= PaintConstants.SHAP.CURV;
133 | createNewPen();
134 | initEraserPaint();
135 | }
136 | /**
137 | * 初始化橡皮擦画笔大小
138 | */
139 | private void initEraserPaint(){
140 | eraserPaint=new Paint();
141 | eraserPaint.setColor(Color.parseColor("#595957"));
142 | eraserPaint.setDither(true);
143 | eraserPaint.setAntiAlias(true);
144 | eraserPaint.setStyle(Paint.Style.STROKE);
145 | eraserPaint.setStrokeJoin(Paint.Join.ROUND);
146 | eraserPaint.setStrokeCap(Paint.Cap.ROUND);
147 | }
148 | /**
149 | * 创建一个新的画笔
150 | */
151 | void createNewPen() {
152 | CommHandwriting tool = null;
153 | switch (paintType) {
154 | case PaintConstants.PEN_TYPE.PLAIN_PEN:
155 | tool = new PlainPen(mPenSize, mPenColor, mStyle);
156 | break;
157 | case PaintConstants.PEN_TYPE.ERASER:
158 | tool = new Eraser(mEraserSize);
159 | break;
160 | case PaintConstants.PEN_TYPE.BLUR:
161 | tool = new BlurPen(mPenSize, mPenColor, mStyle);
162 | break;
163 | case PaintConstants.PEN_TYPE.EMBOSS:
164 | tool = new EmbossPen(mPenSize, mPenColor, mStyle);
165 | break;
166 | default:
167 | break;
168 | }
169 | handwriting = tool;
170 | setShape();
171 | }
172 | /**
173 | * 设置具体形状,需要注意的是构造函数中的Painter必须是新鲜出炉的
174 | */
175 | private void setShape() {
176 | if (handwriting instanceof Shapable) {
177 | switch (shapeType) {
178 | case PaintConstants.SHAP.CURV:
179 | mCurrentShape = new Curv((Shapable) handwriting);
180 | break;
181 | case PaintConstants.SHAP.LINE:
182 | mCurrentShape = new Line((Shapable) handwriting);
183 | break;
184 | case PaintConstants.SHAP.SQUARE:
185 | mCurrentShape = new Square((Shapable) handwriting);
186 | break;
187 | case PaintConstants.SHAP.RECT:
188 | mCurrentShape = new Rectangle((Shapable) handwriting);
189 | break;
190 | case PaintConstants.SHAP.CIRCLE:
191 | mCurrentShape = new Circle((Shapable) handwriting);
192 | break;
193 | case PaintConstants.SHAP.OVAL:
194 | mCurrentShape = new Oval((Shapable) handwriting);
195 | break;
196 | default:
197 | break;
198 | }
199 | ((Shapable) handwriting).setShap(mCurrentShape);
200 | }
201 | }
202 |
203 | public void setTempForeBitmap(Bitmap tempForeBitmap){
204 | if (tempForeBitmap!=null){
205 | BitmapUtils.destroyBitmap(drawBitmap);
206 | drawBitmap=BitmapUtils.duplicateBitmap(tempForeBitmap);
207 | if (drawBitmap!=null&&commCanvas!=null){
208 | commCanvas.setBitmap(drawBitmap);
209 | invalidate();
210 | }
211 | }
212 | }
213 |
214 | /**
215 | * 创建bitMap同时获得其canvas
216 | */
217 | public void createCanvasBitmap(int w, int h) {
218 | if(w>0 || h>0){
219 | drawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
220 | commCanvas.setBitmap(drawBitmap);
221 | }
222 | }
223 |
224 |
225 | @Override
226 | protected void onDraw(Canvas canvas) {
227 | if (drawBitmap!=null&&!drawBitmap.isRecycled()){
228 | canvas.drawBitmap(drawBitmap,0,0,drawPaint);
229 | }
230 | if (!isTouchUp){
231 | if (paintType!= PaintConstants.PEN_TYPE.ERASER){
232 | handwriting.draw(canvas);
233 | }else{
234 | canvas.drawCircle(currentX,currentY,mEraserSize/2,eraserPaint);
235 | }
236 | }
237 | }
238 |
239 | @Override
240 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
241 | super.onSizeChanged(w, h, oldw, oldh);
242 | Log.i(TAG,"onSizeChanged w:"+w+"--h:"+h+"-oldw:"+oldw+"-oldh:"+oldh);
243 | drawingBroadHeight=h;
244 | drawingBroadWidth=w;
245 | createCanvasBitmap(w,h);
246 | }
247 |
248 | private float oldx = 0,oldy=0;
249 | @Override
250 | public boolean onTouchEvent(MotionEvent event) {
251 | float x=event.getX();
252 | float y=event.getY();
253 | currentX=x;
254 | currentY=y;
255 | isTouchUp=false;
256 | switch (event.getAction()){
257 | case MotionEvent.ACTION_DOWN:
258 | oldx=x;oldy=y;
259 | down(x,y);
260 | break;
261 | case MotionEvent.ACTION_MOVE:
262 | getParent().requestDisallowInterceptTouchEvent(true);
263 | move(x,y);
264 | invalidate();
265 | break;
266 | case MotionEvent.ACTION_CANCEL:
267 | getParent().requestDisallowInterceptTouchEvent(false);
268 | return false;
269 | case MotionEvent.ACTION_UP:
270 | if (handwriting.hasDraw()){
271 | padUndoStack.push(handwriting);
272 | if (mCallBack!=null)mCallBack.onHasDraw();
273 | }
274 | up(event.getX(),event.getY());
275 | isTouchUp = true;
276 | invalidate();
277 | break;
278 | }
279 | return true;
280 | }
281 |
282 | private void down(float x,float y){
283 | commCanvas.setBitmap(drawBitmap);
284 | createNewPen();
285 | if (handwriting!=null){
286 | handwriting.touchDown(x,y);
287 | }
288 | if (mCallBack!=null){
289 | mCallBack.onTouchDown();
290 | }
291 | }
292 |
293 | private void move(float x,float y){
294 | handwriting.touchMove(x,y);
295 | if (paintType== PaintConstants.PEN_TYPE.ERASER){
296 | handwriting.draw(commCanvas);
297 | }
298 | }
299 |
300 | private void up(float x,float y){
301 | if (handwriting==null){
302 | return;
303 | }
304 | handwriting.touchUp(x,y);
305 | handwriting.draw(commCanvas);
306 | final float dx=Math.abs(oldx-x);
307 | final float dy=Math.abs(oldy-y);
308 | if (dx==0&&dy==0){
309 | handwriting.touchUp(x+1,y);
310 | handwriting.draw(commCanvas);
311 | }
312 | }
313 |
314 | @Override
315 | public boolean dispatchTouchEvent(MotionEvent event) {
316 | getParent().requestDisallowInterceptTouchEvent(true);
317 | return super.dispatchTouchEvent(event);
318 | }
319 |
320 | public void addNewDrawing(){
321 | clearAll(false);
322 | resetHandwriting();
323 | }
324 | /**
325 | * 设置画笔的颜色
326 | * @param color
327 | */
328 | public void setPenColor(int color){
329 | mPenColor=color;
330 | }
331 |
332 | /**
333 | * 改变当前画笔的类型
334 | */
335 | public void setPenType(int type) {
336 | switch (type) {
337 | case PaintConstants.PEN_TYPE.BLUR:
338 | case PaintConstants.PEN_TYPE.PLAIN_PEN:
339 | case PaintConstants.PEN_TYPE.EMBOSS:
340 | case PaintConstants.PEN_TYPE.ERASER:
341 | paintType = type;
342 | break;
343 | default:
344 | paintType = PaintConstants.PEN_TYPE.PLAIN_PEN;
345 | break;
346 | }
347 | }
348 | /**
349 | * 设置画笔大小
350 | * @param size
351 | */
352 | public void setPenSize(int size){
353 | mPenSize=size;
354 | }
355 | /**
356 | * 加载图到画板中
357 | * @param bitmap
358 | */
359 | public void loadImg(Bitmap bitmap){
360 | if (bitmap==null)return;
361 | clearAll(false);
362 | drawBitmap=BitmapUtils.duplicateBitmap(bitmap);
363 | originalBitmap=BitmapUtils.duplicateBitmap(bitmap);
364 | invalidate();
365 | }
366 |
367 | public Bitmap getSnapShoot() {
368 | // 获得当前的view的图片
369 | setDrawingCacheEnabled(true);
370 | buildDrawingCache(true);
371 | Bitmap bitmap = getDrawingCache(true);
372 | Bitmap bmp = BitmapUtils.duplicateBitmap(bitmap);
373 | BitmapUtils.destroyBitmap(bitmap);
374 | // 将缓存清理掉
375 | setDrawingCacheEnabled(false);
376 | return bmp;
377 | }
378 |
379 | /**
380 | * 清除所有笔记
381 | * @param isUndo
382 | */
383 | public void clearAll(boolean isUndo){
384 | BitmapUtils.destroyBitmap(drawBitmap);
385 | BitmapUtils.destroyBitmap(originalBitmap);
386 | if (isUndo){
387 | padUndoStack.push(new ClearAll());
388 | }else{
389 | padUndoStack.clearAll();
390 | }
391 | createCanvasBitmap(drawingBroadWidth,drawingBroadHeight);
392 | invalidate();
393 | }
394 | public void onHasDraw() {
395 | if (mCallBack != null) {
396 | // 控制undo\redo的现实
397 | mCallBack.onHasDraw();
398 | }
399 | }
400 | /**
401 | * 清除笔迹
402 | */
403 | private void resetHandwriting() {
404 | if (null!=padUndoStack)padUndoStack.clearAll();
405 | }
406 |
407 | @Override
408 | public void undo() {
409 | if (null!=padUndoStack)padUndoStack.undo();
410 | }
411 |
412 | @Override
413 | public void redo() {
414 | if (null!=padUndoStack)padUndoStack.redo();
415 | }
416 |
417 | @Override
418 | public boolean canUndo() {
419 | if (null!=padUndoStack){
420 | return padUndoStack.canUndo();
421 | }else{
422 | return false;
423 | }
424 | }
425 |
426 | @Override
427 | public boolean canRedo() {
428 | if (null!=padUndoStack){
429 | return padUndoStack.canRedo();
430 | }else{
431 | return false;
432 | }
433 | }
434 |
435 | @Override
436 | protected void onDetachedFromWindow() {
437 | super.onDetachedFromWindow();
438 | BitmapUtils.destroyBitmap(drawBitmap);
439 | BitmapUtils.destroyBitmap(originalBitmap);
440 | }
441 |
442 | private class PaintPadUndoStack {
443 | private int m_stackSize = 0;
444 | private Drawing mDrawing = null;
445 | private ArrayList mUndoStack = new ArrayList<>();
446 | private ArrayList mRedoStack = new ArrayList<>();
447 | private ArrayList mOldActionStack = new ArrayList<>();
448 |
449 | public PaintPadUndoStack(Drawing drawing, int stackSize) {
450 | mDrawing = drawing;
451 | m_stackSize = stackSize;
452 | }
453 | /**
454 | * 将painter存入栈中
455 | */
456 | public void push(CommHandwriting penTool) {
457 | if (null != penTool) {
458 | // 如果undo已经存满
459 | if (mUndoStack.size() == m_stackSize && m_stackSize > 0) {
460 | // 得到最远的画笔
461 | CommHandwriting removedTool = mUndoStack.get(0);
462 | // 所有的笔迹增加
463 | mOldActionStack.add(removedTool);
464 | mUndoStack.remove(0);
465 | }
466 | mUndoStack.add(penTool);
467 | }
468 | }
469 | /**
470 | * 清空所有
471 | */
472 | public void clearAll() {
473 | mRedoStack.clear();
474 | mUndoStack.clear();
475 | mOldActionStack.clear();
476 | }
477 | /**
478 | * undo
479 | */
480 | public void undo() {
481 | if (canUndo() && null != mDrawing) {
482 | CommHandwriting removedTool = mUndoStack
483 | .get(mUndoStack.size() - 1);
484 | mRedoStack.add(removedTool);
485 | mUndoStack.remove(mUndoStack.size() - 1);
486 | renewDraw();
487 | }
488 | }
489 | /**
490 | * redo
491 | */
492 | public void redo() {
493 | if (canRedo() && null != mDrawing) {
494 | CommHandwriting removedTool = mRedoStack
495 | .get(mRedoStack.size() - 1);
496 | mUndoStack.add(removedTool);
497 | mRedoStack.remove(mRedoStack.size() - 1);
498 | renewDraw();
499 | }
500 | }
501 |
502 | private void renewDraw(){
503 | if (null != originalBitmap&&!originalBitmap.isRecycled()) {
504 | // Set the temporary fore bitmap to canvas.
505 | // 当载入文件时保存了一份,现在要重新绘制出来
506 | mDrawing.setTempForeBitmap(mDrawing.originalBitmap);
507 | } else {
508 | // 如果背景不存在,则重新创建一份背景
509 | mDrawing.createCanvasBitmap(mDrawing.drawingBroadWidth,
510 | mDrawing.drawingBroadHeight);
511 | }
512 | Canvas canvas = mDrawing.commCanvas;
513 | // First draw the removed tools from undo stack.
514 | for (CommHandwriting paintTool : mOldActionStack) {
515 | paintTool.draw(canvas);
516 | }
517 | for (CommHandwriting paintTool : mUndoStack) {
518 | paintTool.draw(canvas);
519 | }
520 | mDrawing.invalidate();
521 | }
522 |
523 |
524 | public boolean canUndo() {
525 | return (mUndoStack.size() > 0);
526 | }
527 |
528 | public boolean canRedo() {
529 | return (mRedoStack.size() > 0);
530 | }
531 |
532 | @Override
533 | public String toString() {
534 | return "canUndo" + canUndo();
535 | }
536 | }
537 | }
538 |
--------------------------------------------------------------------------------