getSizeConverters() {
23 |
24 | return null;
25 | }
26 |
27 | public int getStartRange() {
28 | return 0;
29 | }
30 |
31 | public void setStartRange(int startRange) {
32 | }
33 |
34 | public int getEndRange() {
35 | return 0;
36 | }
37 |
38 | public void setEndRange(int endRange) {
39 | }
40 |
41 | public boolean isClipDraw() {
42 | return false;
43 | }
44 |
45 | public void setClipDraw(boolean clipDraw) {
46 | }
47 |
48 | public int getMinRange() {
49 | return 0;
50 | }
51 |
52 | public int getMaxRange() {
53 | return 0;
54 | }
55 |
56 | public static class Build {
57 |
58 | public Build(Context context) {
59 | }
60 |
61 | public Build addSizeConverter(ISizeConverter sizeConverter) {
62 | return this;
63 | }
64 |
65 | public Build addLayerView(AbsLayer layerView) {
66 | return this;
67 | }
68 |
69 | public Build viewFilter(ViewFilter viewFilter) {
70 | return this;
71 | }
72 |
73 | public Build range(int min, int max) {
74 |
75 | return this;
76 | }
77 |
78 | public Build clipDraw(boolean clip) {
79 |
80 | return this;
81 | }
82 |
83 | public Config build() {
84 | return null;
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/sak-nop/src/main/java/com/wanjian/sak/converter/ISizeConverter.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.converter;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Created by wanjian on 2017/2/20.
7 | */
8 |
9 | public abstract class ISizeConverter {
10 | public static ISizeConverter CONVERTER;
11 |
12 | public abstract String desc();
13 |
14 | public abstract Size convert(Context context, float length);
15 |
16 | public abstract int recovery(Context context, float length);
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/sak-nop/src/main/java/com/wanjian/sak/converter/Size.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.converter;
2 |
3 |
4 | /**
5 | * Created by wanjian on 2017/2/20.
6 | */
7 |
8 | public class Size {
9 |
10 | private Size() {
11 | }
12 |
13 | public Size(int length, String unit) {
14 |
15 | }
16 |
17 | public static Size obtain() {
18 |
19 | return null;
20 | }
21 |
22 | public float getLength() {
23 | return 0;
24 | }
25 |
26 | public Size setLength(float length) {
27 | return this;
28 | }
29 |
30 | public String getUnit() {
31 | return null;
32 | }
33 |
34 | public Size setUnit(String unit) {
35 | return this;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/sak-nop/src/main/java/com/wanjian/sak/filter/ViewFilter.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.filter;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * Created by wanjian on 2017/2/20.
7 | */
8 |
9 | public abstract class ViewFilter {
10 | public static ViewFilter FILTER;
11 |
12 | public final boolean filter(View view) {
13 | return false;
14 | }
15 |
16 | protected abstract boolean apply(View view);
17 | }
18 |
--------------------------------------------------------------------------------
/sak-nop/src/main/java/com/wanjian/sak/layer/AbsLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.drawable.Drawable;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.view.WindowManager;
9 | import android.widget.FrameLayout;
10 |
11 | import com.wanjian.sak.config.Config;
12 | import com.wanjian.sak.converter.ISizeConverter;
13 | import com.wanjian.sak.filter.ViewFilter;
14 |
15 | /**
16 | * Created by wanjian on 2017/3/9.
17 | */
18 |
19 | public abstract class AbsLayer extends FrameLayout {
20 |
21 | public AbsLayer(Context context) {
22 | super(context);
23 | }
24 |
25 | public void attachConfig(Config config) {
26 | }
27 |
28 | public abstract String description();
29 |
30 | public abstract Drawable icon();
31 |
32 | public final void enable(boolean enable) {
33 | }
34 |
35 | protected void onStateChange(boolean isEnable) {
36 |
37 | }
38 |
39 | public final boolean isEnable() {
40 | return false;
41 | }
42 |
43 | protected boolean isClipDraw() {
44 | return false;
45 | }
46 |
47 | protected int getStartRange() {
48 | return 0;
49 | }
50 |
51 | protected int getEndRange() {
52 | return 0;
53 | }
54 |
55 | public final void uiUpdate(Canvas canvas, View view) {
56 |
57 | }
58 |
59 | protected void onUiUpdate(Canvas canvas, View rootView) {
60 |
61 | }
62 |
63 | protected void onAttached(View rootView) {
64 | }
65 |
66 |
67 | protected void onDetached(View rootView) {
68 | }
69 |
70 | protected int[] getLocationAndSize(View view) {
71 | return null;
72 | }
73 |
74 | protected int dp2px(int dip) {
75 | return 0;
76 | }
77 |
78 | protected int px2dp(float pxValue) {
79 | return 0;
80 | }
81 |
82 | protected ISizeConverter getSizeConverter() {
83 | return null;
84 | }
85 |
86 | protected ViewFilter getViewFilter() {
87 | return null;
88 | }
89 |
90 | protected void showWindow(View view, WindowManager.LayoutParams params) {
91 |
92 | }
93 |
94 | protected void updateWindow(View view, WindowManager.LayoutParams params) {
95 | }
96 |
97 | protected void removeWindow(View view) {
98 | }
99 |
100 | public ViewGroup.LayoutParams getLayoutParams(FrameLayout.LayoutParams params) {
101 | return null;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/sak-nop/src/main/java/com/wanjian/sak/layer/adapter/LayerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.adapter;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.view.View;
6 |
7 | import com.wanjian.sak.layer.AbsLayer;
8 |
9 |
10 | /**
11 | * Created by wanjian on 2016/10/23.
12 | */
13 |
14 | public abstract class LayerAdapter extends AbsLayer {
15 |
16 | public LayerAdapter(Context context) {
17 | super(context);
18 | }
19 |
20 | @Override
21 | protected void onUiUpdate(Canvas canvas, View rootView) {
22 | }
23 |
24 |
25 | protected abstract void onDrawLayer(Canvas canvas, View view);
26 | }
27 |
--------------------------------------------------------------------------------
/sak-nop/src/main/java/com/wanjian/sak/layer/adapter/LayerTxtAdapter.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.adapter;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.view.View;
6 |
7 | /**
8 | * Created by wanjian on 2016/10/26.
9 | *
10 | * 在view左上角画浅白色背景和文本
11 | */
12 |
13 | public abstract class LayerTxtAdapter extends LayerAdapter {
14 |
15 | public LayerTxtAdapter(Context context) {
16 | super(context);
17 | }
18 |
19 |
20 | @Override
21 | protected void onDrawLayer(Canvas canvas, View view) {
22 |
23 | }
24 |
25 | protected abstract String getTxt(View view);
26 |
27 |
28 | protected int getColor() {
29 | return 0;
30 | }
31 |
32 | protected int getBackgroundColor() {
33 | return 0;
34 | }
35 |
36 | public float getTextSize() {
37 | return 0;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/saklib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/saklib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'maven-publish'
3 | android {
4 | namespace('com.wanjian.sak')
5 | compileSdkVersion 33
6 | defaultConfig {
7 | minSdkVersion 14
8 | targetSdkVersion 33
9 | versionCode 1
10 | versionName "1.0"
11 | }
12 | buildTypes {
13 | release {
14 | minifyEnabled false
15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
16 | }
17 | }
18 |
19 | lintOptions {
20 | abortOnError false
21 | }
22 |
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(dir: 'libs', include: ['*.jar'])
27 | implementation('androidx.fragment:fragment:1.0.0')
28 | compileOnly project(path: ':systemlib')
29 | }
30 |
31 | publishing {
32 | publications {
33 | release(MavenPublication) {
34 | groupId = 'com.github.android-notes'
35 | artifactId = 'SwissArmyKnife'
36 | version = '4.0.6'
37 |
38 | afterEvaluate {
39 | from components.release
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/saklib/compressed_pictures:
--------------------------------------------------------------------------------
1 | # Do not modify this file !
2 | 1d945fdbaabefd7e3986dbe077868342
3 | 240eea45ebcb7c237bc3a346641ac7d7
4 | 27a7284489529b58f6b374d8116b0d29
5 | 280d8b92c8da65e545e31d12be9acee0
6 | 34dc3eba1f9167f6fa2667524ea375ad
7 | 3637923ded651ab8920168363d7ddc20
8 | 3692b48641664eb215cdc11caa40b94e
9 | 56ddc2b73473e056f7b61c216ea6cc6a
10 | 58306a5cf9b21e211d6f60c0f30f64df
11 | 5a0d35c1128a25d8418b3f5537f3dd91
12 | 69faa2c2dad502cb6bbaf63d10fe5c24
13 | 7a507bd56fc6a22c7c5268ed7d3deb74
14 | 7b527e6dc1ada3147423c11b5a4a045d
15 | 8440cfd5441ed66343579b0642bb4370
16 | 85b1e055efc190e649c23498ff224aa8
17 | 894a888fd0631ba8d4d4753fdafb4bee
18 | 9b550082c308a17e91b6976b7daba208
19 | 9f8775e185d0253ffcf512795f23dd12
20 | b93043c06e5790e316979cdb2a57fdea
21 | c29b1c79f3fa2ec21df1c31e431e7da0
22 | e989ecb07a56e9ae51ef982609315533
23 | ed6a27fab5ab85611bfb453d7f52c1c6
24 | edb7c8ded87e279e546303644cce5b45
25 | edcb4e91f3a8b41cd59aa758c381d6f2
26 | feb4a4069c8d94d966cc782d24f14c67
--------------------------------------------------------------------------------
/saklib/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/wanjian/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
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 | #}
18 |
--------------------------------------------------------------------------------
/saklib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/Scaffold.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak;
2 |
3 | import android.app.Application;
4 | import android.os.Build;
5 | import android.view.InputEvent;
6 | import android.view.View;
7 | import android.view.ViewRootImpl;
8 |
9 | import com.wanjian.sak.config.Config;
10 | import com.wanjian.sak.layer.LayerRoot;
11 | import com.wanjian.sak.system.input.InputEventListener;
12 | import com.wanjian.sak.system.input.InputEventProcessorCompact;
13 | import com.wanjian.sak.system.input.InputEventReceiverCompact;
14 | import com.wanjian.sak.system.traversals.ViewTraversalsCompact;
15 | import com.wanjian.sak.system.traversals.ViewTraversalsListener;
16 | import com.wanjian.sak.system.window.compact.IWindowChangeListener;
17 | import com.wanjian.sak.system.window.compact.WindowRootViewCompat;
18 | import com.wanjian.sak.utils.OptionPanelUtils;
19 | import com.wanjian.sak.view.SAKContainerView;
20 |
21 | //import com.wanjian.sak.system.canvas.compact.CanvasHolder;
22 |
23 | final class Scaffold {
24 | private static Application sApplication;
25 |
26 | public void install(final Application application, final Config config) {
27 | sApplication = application;
28 | WindowRootViewCompat.get(application).addWindowChangeListener(new IWindowChangeListener() {
29 |
30 | @Override
31 | public void onAddWindow(final ViewRootImpl viewRootImpl, final View view) {
32 | if (view instanceof SAKContainerView) {
33 | return;
34 | }
35 | view.post(new Runnable() {
36 | @Override
37 | public void run() {
38 | LayerRoot layerRoot = LayerRoot.create(config, viewRootImpl, view, sApplication);
39 | OptionPanelUtils.enableIfNeeded(layerRoot);
40 | observerUIChange(config, layerRoot, viewRootImpl, view);
41 | observerInputEvent(config, layerRoot, viewRootImpl, view);
42 | OptionPanelUtils.addLayerRoot(layerRoot);
43 | }
44 | });
45 | }
46 |
47 | @Override
48 | public void onRemoveWindow(ViewRootImpl viewRootImpl, View view) {
49 | // CanvasHolder.release(viewRootImpl);
50 | }
51 | });
52 | OptionPanelUtils.showEntrance(application, config);
53 | }
54 |
55 |
56 | private void observerInputEvent(Config config, final LayerRoot layerRoot, final ViewRootImpl viewRootImpl, final View rootView) {
57 | InputEventListener listener = new InputEventListener() {
58 | @Override
59 | public boolean onBeforeInputEvent(InputEvent inputEvent) {
60 | return layerRoot.beforeInputEvent(rootView, inputEvent);
61 | }
62 |
63 | @Override
64 | public void onAfterInputEvent(InputEvent inputEvent) {
65 | layerRoot.afterInputEvent(rootView, inputEvent);
66 | }
67 | };
68 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
69 | InputEventProcessorCompact.get(rootView.getContext(),viewRootImpl, listener);
70 | } else {
71 | InputEventReceiverCompact.get(viewRootImpl, listener);
72 | }
73 | }
74 |
75 | private void observerUIChange(Config config, final LayerRoot layerRoot, ViewRootImpl viewRootImpl, View view) {
76 | new ViewTraversalsCompact().register(viewRootImpl, view, new ViewTraversalsListener() {
77 | @Override
78 | public void onBeforeTraversal(View rootView) {
79 | layerRoot.beforeTraversal(rootView);
80 | }
81 |
82 | @Override
83 | public void onAfterTraversal(View rootView) {
84 | layerRoot.afterTraversal(rootView);
85 | }
86 | });
87 | }
88 |
89 |
90 | // public void unInstall() {
91 | //
92 | // }
93 | }
94 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/config/Item.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.config;
2 |
3 | import android.graphics.drawable.Drawable;
4 |
5 | import com.wanjian.sak.layer.Layer;
6 |
7 | public class Item {
8 | public Class extends Layer> layerType;
9 | public Drawable icon;
10 | public String name;
11 | private boolean isEnable;
12 | public Item(Class extends Layer> layerType, Drawable icon, String name) {
13 | this.layerType = layerType;
14 | this.icon = icon;
15 | this.name = name;
16 | }
17 |
18 | public boolean isEnable() {
19 | return isEnable;
20 | }
21 |
22 | public void setEnable(boolean enable) {
23 | isEnable = enable;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/converter/ISizeConverter.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.converter;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Created by wanjian on 2017/2/20.
7 | */
8 |
9 | public abstract class ISizeConverter {
10 | public static ISizeConverter CONVERTER = new Px2DpSizeConverter();
11 |
12 | public abstract String desc();
13 |
14 | public abstract Size convert(Context context, float length);
15 |
16 | public abstract int recovery(Context context, float length);
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/converter/OriginSizeConverter.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.converter;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Created by wanjian on 2017/2/20.
7 | */
8 |
9 | public class OriginSizeConverter extends ISizeConverter {
10 |
11 |
12 | @Override
13 | public String desc() {
14 | return "Px";
15 | }
16 |
17 | @Override
18 | public Size convert(Context context, float length) {
19 | Size size = Size.obtain();
20 |
21 | size.setLength(length);
22 | size.setUnit("px");
23 |
24 | return size;
25 | }
26 |
27 | @Override
28 | public int recovery(Context context, float length) {
29 | return (int) length;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/converter/Px2DpSizeConverter.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.converter;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Created by wanjian on 2017/2/20.
7 | */
8 |
9 | public class Px2DpSizeConverter extends ISizeConverter {
10 | @Override
11 | public String desc() {
12 | return "Dp";
13 | }
14 |
15 | @Override
16 | public Size convert(Context context, float length) {
17 | Size size = Size.obtain();
18 |
19 | size.setLength(px2dp(context, length));
20 |
21 | size.setUnit("dp");
22 |
23 | return size;
24 | }
25 |
26 | @Override
27 | public int recovery(Context context, float length) {
28 | float scale = context.getResources().getDisplayMetrics().density;
29 | return (int) (length * scale + 0.5f);
30 | }
31 |
32 | private int px2dp(Context context, float px) {
33 | final float scale = context.getResources().getDisplayMetrics().density;
34 | return (int) (px / scale + 0.5f);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/converter/Px2SpSizeConverter.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.converter;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Created by wanjian on 2017/3/9.
7 | */
8 |
9 | public class Px2SpSizeConverter extends ISizeConverter {
10 | @Override
11 | public String desc() {
12 | return "Sp";
13 | }
14 |
15 | @Override
16 | public Size convert(Context context, float length) {
17 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
18 | return Size.obtain().setLength((int) (length / fontScale + 0.5f)).setUnit("sp");
19 | }
20 |
21 | @Override
22 | public int recovery(Context context, float length) {
23 | float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
24 | return (int) (length * fontScale + 0.5f);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/converter/Size.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.converter;
2 |
3 |
4 | import java.util.LinkedList;
5 | import java.util.List;
6 |
7 | /**
8 | * Created by wanjian on 2017/2/20.
9 | */
10 |
11 | public class Size {
12 |
13 | private static List sList = new LinkedList<>();
14 | private float length;
15 | private String unit;
16 |
17 | private Size() {
18 | }
19 |
20 | public Size(int length, String unit) {
21 | this.length = length;
22 | this.unit = unit;
23 | }
24 |
25 | public static Size obtain() {
26 | // if (sList.isEmpty()) {
27 | // return new Size();
28 | // }
29 | //
30 | // return sList.get(0);
31 |
32 | return new Size();
33 | }
34 |
35 | public float getLength() {
36 | return length;
37 | }
38 |
39 | public Size setLength(float length) {
40 | this.length = length;
41 | return this;
42 | }
43 |
44 | public String getUnit() {
45 | return unit;
46 | }
47 |
48 | public Size setUnit(String unit) {
49 | this.unit = unit;
50 | return this;
51 | }
52 |
53 | // public static void returnSize(Size size) {
54 | // Check.isNull(size, "size");
55 | // if (sList.size() < 100) {
56 | // sList.add(size);
57 | // }
58 | // }
59 |
60 | @Override
61 | public String toString() {
62 | return length + " " + unit;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/event/EventListener.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.event;
2 |
3 | import android.view.InputEvent;
4 | import android.view.View;
5 |
6 | public interface EventListener {
7 |
8 | void beforeTraversal(View rootView);
9 |
10 | void afterTraversal(View rootView);
11 |
12 | boolean beforeInputEvent(View rootView, InputEvent event);
13 |
14 | void afterInputEvent(View rootView, InputEvent event);
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/filter/ViewFilter.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.filter;
2 |
3 | import android.view.View;
4 |
5 |
6 | /**
7 | * Created by wanjian on 2017/2/20.
8 | */
9 |
10 | public abstract class ViewFilter {
11 | public static ViewFilter FILTER = new ViewFilter() {
12 | @Override
13 | protected boolean apply(View view) {
14 | return view.getVisibility() == View.VISIBLE;
15 | }
16 | };
17 |
18 |
19 | public final boolean filter(View view) {
20 | return apply(view);
21 | }
22 |
23 | protected abstract boolean apply(View view);
24 |
25 | @Override
26 | public int hashCode() {
27 | return getClass().hashCode();
28 | }
29 |
30 | @Override
31 | public boolean equals(Object obj) {
32 | if (obj == null) {
33 | return false;
34 | }
35 | return obj.getClass() == getClass();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/IClip.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer;
2 |
3 | public interface IClip {
4 | void onClipChange(boolean clip);
5 | }
6 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/IRange.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer;
2 |
3 | public interface IRange {
4 | void onStartRangeChange(int start);
5 | void onEndRangeChange(int start);
6 | }
7 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/ISize.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer;
2 |
3 | import com.wanjian.sak.converter.ISizeConverter;
4 |
5 | public interface ISize {
6 | void onSizeConvertChange(ISizeConverter converter);
7 | }
8 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/Layer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer;
2 |
3 | import android.app.Application;
4 | import android.graphics.Canvas;
5 | import android.view.InputEvent;
6 | import android.view.View;
7 | import android.view.ViewRootImpl;
8 |
9 | import com.wanjian.sak.config.Config;
10 | import com.wanjian.sak.event.EventListener;
11 | import com.wanjian.sak.system.rendernode.RenderNodeCompact;
12 |
13 | public abstract class Layer implements EventListener {
14 | private ViewRootImpl viewRootImpl;
15 | private Config config;
16 | private Application application;
17 | private LayerRoot layerRoot;
18 | private RenderNodeCompact renderNode;
19 | private View rootView;
20 | private boolean isEnable;
21 |
22 | public Layer() {
23 |
24 | }
25 |
26 | public RenderNodeCompact getRenderNode() {
27 | return renderNode;
28 | }
29 |
30 | public final void attach(Config config, ViewRootImpl viewRoot, View rootView, Application application, LayerRoot layerRoot) {
31 | this.viewRootImpl = viewRoot;
32 | this.config = config;
33 | this.application = application;
34 | this.layerRoot = layerRoot;
35 | this.rootView = rootView;
36 | renderNode = RenderNodeCompact.create(getClass().getName());
37 | onAttach(getRootView());
38 | }
39 |
40 | //
41 | // private final Canvas requireCanvas() {
42 | // return CanvasHolder.requireCanvasFor(viewRootImpl);
43 | // }
44 | //
45 | // private final void releaseCanvas() {
46 | // CanvasHolder.releaseCanvasFor(viewRootImpl);
47 | // }
48 |
49 | protected void invalidate() {
50 | // renderNode.setLeftTopRightBottom(0, 0, getRootView().getWidth(), getRootView().getHeight());
51 | // DisplayListCanvas displayListCanvas = renderNode.start(getRootView().getWidth(), getRootView().getHeight());
52 | // onDraw(displayListCanvas);
53 | // renderNode.end(displayListCanvas);
54 | View view = getRootView();
55 | if (view == null) {
56 | return;
57 | }
58 | Canvas canvas = renderNode.beginRecording(view.getWidth(), view.getHeight());
59 | draw(canvas);
60 | renderNode.endRecording(canvas);
61 | layerRoot.invalidate();
62 | }
63 |
64 | private void draw(Canvas canvas) {
65 | if (isEnable == false) {
66 | canvas.drawColor(0);
67 | return;
68 | }
69 | onDraw(canvas);
70 | }
71 |
72 | public final boolean isEnable() {
73 | return isEnable;
74 | }
75 |
76 | public final void enable(boolean enable) {
77 | isEnable = enable;
78 | invalidate();
79 | onEnableChange(enable);
80 | }
81 |
82 | protected void onEnableChange(boolean enable) {
83 | }
84 |
85 | protected void onDraw(Canvas canvas) {
86 |
87 | }
88 |
89 | @Override
90 | public final void beforeTraversal(View rootView) {
91 | onBeforeTraversal(rootView);
92 | }
93 |
94 | @Override
95 | public final void afterTraversal(View rootView) {
96 | onAfterTraversal(rootView);
97 | }
98 |
99 | @Override
100 | public final boolean beforeInputEvent(View rootView, InputEvent event) {
101 | //rootView.invalidate();
102 | return onBeforeInputEvent(rootView, event);
103 | }
104 |
105 | @Override
106 | public final void afterInputEvent(View rootView, InputEvent event) {
107 | //rootView.invalidate();
108 | onAfterInputEvent(rootView, event);
109 | }
110 |
111 | protected View getRootView() {
112 | return rootView;
113 | }
114 |
115 | protected void onBeforeTraversal(View rootView) {
116 | }
117 |
118 | protected void onAfterTraversal(View rootView) {
119 | }
120 |
121 | protected boolean onBeforeInputEvent(View rootView, InputEvent event) {
122 | return false;
123 | }
124 |
125 | protected void onAfterInputEvent(View rootView, InputEvent event) {
126 | }
127 |
128 | protected void onAttach(View rootView) {
129 |
130 | }
131 |
132 | protected Application getContext() {
133 | return application;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/adapter/LayerAdapter.java:
--------------------------------------------------------------------------------
1 | //package com.wanjian.sak.layer.adapter;
2 | //
3 | //import android.content.Context;
4 | //import android.graphics.Canvas;
5 | //import android.graphics.Region;
6 | //import android.view.View;
7 | //import android.view.ViewGroup;
8 | //
9 | //import com.wanjian.sak.layer.AbsLayer;
10 | //
11 | //
12 | ///**
13 | // * Created by wanjian on 2016/10/23.
14 | // */
15 | //
16 | //public abstract class LayerAdapter extends AbsLayer {
17 | // private int mStartLayer;
18 | // private int mEndLayer;
19 | // private boolean isClip;
20 | //
21 | // public LayerAdapter(Context context) {
22 | // super(context);
23 | // }
24 | //
25 | // @Override
26 | // protected void onUiUpdate(Canvas canvas, View rootView) {
27 | // mStartLayer = getStartRange();
28 | // mEndLayer = getEndRange();
29 | // isClip = isClipDraw();
30 | // layerCount(canvas, rootView, 0);
31 | // }
32 | //
33 | //
34 | // private void layerCount(Canvas canvas, View view, int curLayer) {
35 | // if (!getViewFilter().filter(view)) {
36 | // return;
37 | // }
38 | // if (curLayer > mEndLayer) {
39 | // return;
40 | // }
41 | // canvas.save();
42 | // if (curLayer >= mStartLayer) {
43 | // drawLayer(canvas, view, curLayer);
44 | // }
45 | // if (!(view instanceof ViewGroup)) {
46 | // canvas.restore();
47 | // return;
48 | // }
49 | //
50 | // clipIfNeeded(canvas, view, curLayer);
51 | //
52 | // ViewGroup vg = ((ViewGroup) view);
53 | // for (int i = 0, len = vg.getChildCount(); i < len; i++) {
54 | // View child = vg.getChildAt(i);
55 | // layerCount(canvas, child, curLayer + 1);
56 | // }
57 | //
58 | // canvas.restore();
59 | // }
60 | //
61 | // private void clipIfNeeded(Canvas canvas, View view, int curLayer) {
62 | // if (!isClip) {
63 | // return;
64 | // }
65 | //
66 | // int w = view.getWidth();
67 | // int h = view.getHeight();
68 | // canvas.clipRect(0
69 | // , 0
70 | // , w
71 | // , h
72 | // , Region.Op.INTERSECT);
73 | // }
74 | //
75 | //
76 | // private void drawLayer(Canvas canvas, View view, int curLayer) {
77 | // int pl = 0;
78 | // int pt = 0;
79 | // if (curLayer == 1) {
80 | // View decorView = (View) view.getParent();
81 | // pl = decorView.getPaddingLeft();
82 | // pt = decorView.getPaddingTop();
83 | // }//view.getLocationInWindow();
84 | // canvas.translate(view.getX() - pl - view.getScrollX(), view.getY() - pt - view.getScrollY());
85 | // int count = canvas.save();
86 | // onDrawLayer(canvas, view);
87 | // canvas.restoreToCount(count);
88 | // }
89 | //
90 | // protected abstract void onDrawLayer(Canvas canvas, View view);
91 | //}
92 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/adapter/LayerTxtAdapter.java:
--------------------------------------------------------------------------------
1 | //package com.wanjian.sak.layer.adapter;
2 | //
3 | //import android.content.Context;
4 | //import android.graphics.Canvas;
5 | //import android.graphics.Color;
6 | //import android.graphics.Paint;
7 | //import android.graphics.Rect;
8 | //import android.view.View;
9 | //
10 | ///**
11 | // * Created by wanjian on 2016/10/26.
12 | // *
13 | // * 在view左上角画浅白色背景和文本
14 | // */
15 | //
16 | //public abstract class LayerTxtAdapter extends LayerAdapter {
17 | // private final Paint mPaint;
18 | // private Rect mRect = new Rect();
19 | //
20 | // public LayerTxtAdapter(Context context) {
21 | // super(context);
22 | // mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
23 | // mPaint.setTextSize(dp2px(10));
24 | // mPaint.setColor(getColor());
25 | // }
26 | //
27 | //
28 | // @Override
29 | // protected void onDrawLayer(Canvas canvas, View view) {
30 | // String txt = getTxt(view);
31 | // if (txt == null) {
32 | // txt = "";
33 | // }
34 | // drawTxt(txt, canvas, view);
35 | // }
36 | //
37 | // protected abstract String getTxt(View view);
38 | //
39 | // private void drawTxt(String txt, Canvas canvas, View view) {
40 | // mPaint.setTextSize(getTextSize());
41 | // mPaint.getTextBounds(txt, 0, txt.length(), mRect);
42 | // mPaint.setColor(getBackgroundColor());
43 | // canvas.drawRect(0, 0, mRect.width() + 2, mRect.height() + 2, mPaint);
44 | // mPaint.setColor(getColor());
45 | // canvas.drawText(txt, 1, 1 + mRect.height(), mPaint);
46 | // }
47 | //
48 | // protected int getColor() {
49 | // return Color.BLACK;
50 | // }
51 | //
52 | // protected int getBackgroundColor() {
53 | // return 0x88ffffff;
54 | // }
55 | //
56 | // public float getTextSize() {
57 | // return dp2px(10);
58 | // }
59 | //}
60 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/ActivityNameLayerView.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.graphics.drawable.Drawable;
8 | import android.text.Layout;
9 | import android.text.SpannableString;
10 | import android.text.Spanned;
11 | import android.text.StaticLayout;
12 | import android.text.TextPaint;
13 | import android.text.style.BackgroundColorSpan;
14 | import android.view.View;
15 |
16 | import com.wanjian.sak.R;
17 | import com.wanjian.sak.layer.Layer;
18 | import com.wanjian.sak.utils.ScreenUtils;
19 | import com.wanjian.sak.utils.Utils;
20 |
21 | public class ActivityNameLayerView extends Layer {
22 |
23 | private Paint mPaint;
24 | private String mActName;
25 | private int mRadius;
26 |
27 | @Override
28 | protected void onAttach(View rootView) {
29 | super.onAttach(rootView);
30 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
31 | mPaint.setTextSize(ScreenUtils.dp2px(getContext(), 10));
32 | mPaint.setColor(Color.RED);
33 | mPaint.setStrokeWidth(ScreenUtils.dp2px(getContext(), 1));
34 | mRadius = ScreenUtils.dp2px(getContext(), 8);
35 | getActivityName(rootView);
36 | }
37 |
38 | protected void getActivityName(View view) {
39 | Activity activity = Utils.findAct(view);
40 | if (activity == null) {
41 | return;
42 | }
43 | mActName = activity.getClass().getName();
44 | invalidate();
45 | }
46 |
47 | @Override
48 | protected void onDraw(Canvas canvas) {
49 | super.onDraw(canvas);
50 | drawActivityInfo(canvas);
51 | }
52 |
53 | protected void drawActivityInfo(Canvas canvas) {
54 | if (mActName == null) {
55 | return;
56 | }
57 | drawInfo(canvas, 0, 0, canvas.getWidth(), canvas.getHeight(), mActName);
58 | }
59 |
60 |
61 | protected void drawInfo(Canvas canvas, int x, int y, int w, int h, String txt) {
62 | canvas.save();
63 | drawCorner(canvas, x, y, w, h);
64 |
65 | drawX(canvas, x, y, w, h);
66 |
67 | drawName(canvas, x, y, w, h, txt);
68 | canvas.restore();
69 | }
70 |
71 | private void drawName(Canvas canvas, int x, int y, int w, int h, String txt) {
72 | TextPaint textPaint = new TextPaint(mPaint);
73 | textPaint.setTextSize(ScreenUtils.dp2px(getContext(), 13));
74 | canvas.translate(x, y);
75 | SpannableString decorStr = new SpannableString(txt);
76 | decorStr.setSpan(new BackgroundColorSpan(0x99FFFFFF), 0, txt.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
77 | StaticLayout staticLayout = new StaticLayout(decorStr, textPaint, (int) (w * 0.8), Layout.Alignment.ALIGN_CENTER, 1, 0, false);
78 |
79 | int txtW = staticLayout.getWidth();
80 | int txtH = staticLayout.getHeight();
81 | if (txtH > 0 && txtH > h * 0.8) {
82 | float scale = h * 0.8f / txtH;
83 | int realW = (int) (txtW * scale);
84 | int realH = (int) (txtH * scale);
85 |
86 | canvas.translate((w - realW) / 2f, (h - realH) / 2f);
87 | canvas.scale(scale, scale);
88 | } else {
89 | canvas.translate((w - txtW) / 2f, (h - txtH) / 2f);
90 | }
91 |
92 | staticLayout.draw(canvas);
93 | }
94 |
95 | private void drawX(Canvas canvas, int x, int y, int w, int h) {
96 | canvas.drawLine(x, y, x + w, y + h, mPaint);
97 | canvas.drawLine(x + w, y, x, y + h, mPaint);
98 | }
99 |
100 | private void drawCorner(Canvas canvas, int x, int y, int w, int h) {
101 | canvas.drawLine(x, y, x + mRadius, y, mPaint);
102 | canvas.drawLine(x, y, x, y + mRadius, mPaint);
103 |
104 | canvas.drawLine(x + w, y, x + w - mRadius, y, mPaint);
105 | canvas.drawLine(x + w, y, x + w, y + mRadius, mPaint);
106 |
107 |
108 | canvas.drawLine(x, y + h, x + mRadius, y + h, mPaint);
109 | canvas.drawLine(x, y + h, x, y + h - mRadius, mPaint);
110 |
111 |
112 | canvas.drawLine(x + w, y + h, x + w - mRadius, y + h, mPaint);
113 | canvas.drawLine(x + w, y + h, x + w, y + h - mRadius, mPaint);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/BackgroundColorLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.drawable.ColorDrawable;
4 | import android.graphics.drawable.Drawable;
5 | import android.graphics.drawable.ShapeDrawable;
6 | import android.view.View;
7 |
8 | import static android.os.Build.VERSION.SDK_INT;
9 |
10 | /**
11 | * Created by wanjian on 2016/10/26.
12 | */
13 |
14 | public class BackgroundColorLayer extends LayerTxtAdapter {
15 |
16 | @Override
17 | protected String getTxt(View view) {
18 | if (SDK_INT < 11) {
19 | return "";
20 | }
21 | Drawable drawable = view.getBackground();
22 | if (drawable != null) {
23 | drawable = drawable.getCurrent();
24 | }
25 | if (drawable instanceof ColorDrawable) {
26 | int color = ((ColorDrawable) drawable).getColor();
27 | String txt = String.format("#%08x", color);
28 | return txt;
29 | } else if (drawable instanceof ShapeDrawable) {
30 | }
31 |
32 | return "";
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/BitmapWidthHeightLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.drawable.BitmapDrawable;
6 | import android.graphics.drawable.Drawable;
7 | import android.view.View;
8 | import android.widget.ImageView;
9 |
10 | import com.wanjian.sak.converter.ISizeConverter;
11 | import com.wanjian.sak.layer.ISize;
12 |
13 |
14 | /**
15 | *
16 | */
17 |
18 | public class BitmapWidthHeightLayer extends LayerTxtAdapter implements ISize {
19 | private ISizeConverter sizeConverter = ISizeConverter.CONVERTER;
20 |
21 | @Override
22 | protected String getTxt(View view) {
23 | ISizeConverter converter = sizeConverter;
24 | Context context = getContext();
25 | if (view instanceof ImageView) {
26 | Drawable drawable = ((ImageView) view).getDrawable();
27 | if (drawable instanceof BitmapDrawable) {
28 | Bitmap bmp = ((BitmapDrawable) drawable).getBitmap();
29 | if (bmp != null && !bmp.isRecycled()) {
30 | return (int) converter.convert(context, bmp.getWidth()).getLength() + ":" + (int) converter.convert(context, bmp.getHeight()).getLength();
31 | }
32 | }
33 | }
34 | return "";
35 | }
36 |
37 |
38 | @Override
39 | public void onSizeConvertChange(ISizeConverter converter) {
40 | sizeConverter = converter;
41 | invalidate();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/BorderLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.Paint;
6 | import android.graphics.drawable.Drawable;
7 | import android.view.View;
8 |
9 | import com.wanjian.sak.R;
10 | import com.wanjian.sak.utils.ScreenUtils;
11 |
12 |
13 | /**
14 | * Created by wanjian on 2016/10/24.
15 | */
16 |
17 | public class BorderLayer extends ViewLayer {
18 |
19 | private Paint mBorderPaint;
20 | private Paint mCornerPaint;
21 | private int mCornerW;
22 |
23 | private int w;
24 | private int h;
25 |
26 | @Override
27 | protected void onAttach(View rootView) {
28 | super.onAttach(rootView);
29 | mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
30 | mBorderPaint.setStyle(Paint.Style.STROKE);
31 | mBorderPaint.setColor(getBorderColor());
32 |
33 | mCornerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
34 | mCornerPaint.setStyle(Paint.Style.STROKE);
35 | mCornerPaint.setStrokeWidth(ScreenUtils.dp2px(getContext(), 1));
36 | mCornerPaint.setColor(getCornerColor());
37 |
38 | mCornerW = ScreenUtils.dp2px(getContext(), 6);
39 | // invalidate();
40 | }
41 |
42 | @Override
43 | protected void onDraw(Canvas canvas, View view) {
44 | w = view.getWidth();
45 | h = view.getHeight();
46 | drawBorder(canvas);
47 | drawCorner(canvas);
48 | }
49 |
50 | protected int getBorderColor() {
51 | return getContext().getResources().getColor(R.color.sak_color_primary);
52 | }
53 |
54 | protected int getCornerColor() {
55 | return Color.MAGENTA;
56 | }
57 |
58 | private void drawBorder(Canvas canvas) {
59 | canvas.drawRect(0, 0, w, h, mBorderPaint);
60 | }
61 |
62 | private void drawCorner(Canvas canvas) {
63 | //--
64 | canvas.drawLine(0, 0, mCornerW, 0, mCornerPaint);
65 | //|
66 | canvas.drawLine(0, 0, 0, mCornerW, mCornerPaint);
67 | // --
68 | canvas.drawLine(w - mCornerW, 0, w, 0, mCornerPaint);
69 | // |
70 | canvas.drawLine(w, 0, w, mCornerW, mCornerPaint);
71 | //
72 | canvas.drawLine(0, h, 0, h - mCornerW, mCornerPaint);
73 | canvas.drawLine(0, h, mCornerW, h, mCornerPaint);
74 |
75 | canvas.drawLine(w - mCornerW, h, w, h, mCornerPaint);
76 | canvas.drawLine(w, h - mCornerW, w, h, mCornerPaint);
77 |
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/FlashWindowLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.Canvas;
4 | import android.os.Handler;
5 | import android.os.Looper;
6 | import android.view.View;
7 |
8 | import com.wanjian.sak.layer.Layer;
9 | import com.wanjian.sak.system.canvaspool.CanvasPoolCompact;
10 | import com.wanjian.sak.system.canvaspool.CanvasRecycleListener;
11 |
12 | public class FlashWindowLayer extends Layer {
13 | private CanvasRecycleListener listener = new CanvasRecycleListener() {
14 | @Override
15 | public void onRecycle(Canvas canvas) {
16 | if (traversaling == false || flash) {
17 | return;
18 | }
19 | flash();
20 | }
21 | };
22 | private Handler handler = new Handler(Looper.getMainLooper());
23 | private boolean flash;
24 |
25 | private void flash() {
26 | flash = true;
27 | handler.post(new Runnable() {
28 | @Override
29 | public void run() {
30 | invalidate();
31 | }
32 | });
33 | handler.postDelayed(new Runnable() {
34 | @Override
35 | public void run() {
36 | flash = false;
37 | }
38 | }, 1000);
39 | }
40 |
41 | @Override
42 | protected void onDraw(Canvas canvas) {
43 | super.onDraw(canvas);
44 | if (flash == false) {
45 | return;
46 | }
47 | int color = 0x88000000 | (int) (Math.random() * 0xFFFFFF);
48 | canvas.drawColor(color);
49 | handler.post(new Runnable() {
50 | @Override
51 | public void run() {
52 | invalidate();
53 | }
54 | });
55 | }
56 |
57 | private boolean traversaling;
58 |
59 | @Override
60 | protected void onBeforeTraversal(View rootView) {
61 | super.onBeforeTraversal(rootView);
62 | traversaling = true;
63 | }
64 |
65 | @Override
66 | protected void onAfterTraversal(View rootView) {
67 | super.onAfterTraversal(rootView);
68 | traversaling = false;
69 | }
70 |
71 | @Override
72 | protected void onEnableChange(boolean enable) {
73 | super.onEnableChange(enable);
74 | if (enable) {
75 | CanvasPoolCompact.get().registerListener(listener);
76 | } else {
77 | CanvasPoolCompact.get().removeListener(listener);
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/GridLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.Paint;
6 | import android.graphics.drawable.Drawable;
7 | import android.view.View;
8 |
9 | import com.wanjian.sak.R;
10 | import com.wanjian.sak.layer.Layer;
11 | import com.wanjian.sak.utils.ScreenUtils;
12 |
13 | public class GridLayer extends Layer {
14 |
15 | private Paint mPaint;
16 |
17 | @Override
18 | protected void onAttach(View rootView) {
19 | super.onAttach(rootView);
20 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
21 | mPaint.setColor(color());
22 | invalidate();
23 | }
24 |
25 | @Override
26 | protected void onEnableChange(boolean enable) {
27 | super.onEnableChange(enable);
28 |
29 | }
30 |
31 | @Override
32 | protected void onDraw(Canvas canvas) {
33 | super.onDraw(canvas);
34 |
35 | int w = getRootView().getWidth();
36 | int h = getRootView().getHeight();
37 | int space = space();
38 |
39 | for (int i = space; i < w; i += space) {
40 | canvas.drawLine(i, 0, i, h, mPaint);
41 | }
42 | for (int i = space; i < h; i += space) {
43 | canvas.drawLine(0, i, w, i, mPaint);
44 | }
45 | }
46 |
47 |
48 | @Override
49 | protected void onAfterTraversal(View rootView) {
50 | invalidate();
51 | }
52 |
53 | protected int color() {
54 | return 0x55000000;
55 | }
56 |
57 | protected int space() {
58 | return ScreenUtils.dp2px(getContext(), 5);
59 | }
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/HorizontalMeasureView.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.view.InputEvent;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 |
11 | import com.wanjian.sak.converter.ISizeConverter;
12 | import com.wanjian.sak.layer.ISize;
13 | import com.wanjian.sak.layer.Layer;
14 | import com.wanjian.sak.utils.ScreenUtils;
15 |
16 |
17 | /**
18 | * Created by wanjian on 2016/11/10.
19 | */
20 |
21 | public class HorizontalMeasureView extends Layer implements ISize {
22 | protected Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
23 | protected int m20DP;
24 | protected int maxHeight;
25 | protected int minHeight;
26 | private int height;
27 | private boolean consume;
28 | private float lastX, lastY;
29 | private Rect rect = new Rect();
30 |
31 | @Override
32 | protected void onAttach(View rootView) {
33 | super.onAttach(rootView);
34 | init();
35 | }
36 |
37 |
38 | private void init() {
39 | mPaint.setColor(Color.BLACK);
40 | m20DP = ScreenUtils.dp2px(getContext(), 20);
41 | mPaint.setTextSize(ScreenUtils.dp2px(getContext(), 8));
42 | maxHeight = ScreenUtils.dp2px(getContext(), 10);
43 | minHeight = ScreenUtils.dp2px(getContext(), 5);
44 | height = ScreenUtils.dp2px(getContext(), 60);
45 | rect.left = 0;
46 | rect.top = (int) (getRootView().getHeight() / 2f - height / 2f);
47 | rect.right = getRootView().getWidth();
48 | rect.bottom = (int) (getRootView().getHeight() / 2f + height / 2f);
49 | invalidate();
50 | }
51 |
52 | @Override
53 | protected void onAfterTraversal(View rootView) {
54 | super.onAfterTraversal(rootView);
55 | invalidate();
56 | }
57 |
58 | @Override
59 | protected boolean onBeforeInputEvent(View rootView, InputEvent event) {
60 | if (!(event instanceof MotionEvent)) {
61 | return false;
62 | }
63 | MotionEvent motionEvent = ((MotionEvent) event);
64 | if (motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
65 | lastX = motionEvent.getX();
66 | lastY = motionEvent.getY();
67 | if (rect.contains((int) lastX, (int) lastY)) {
68 | consume = true;
69 | } else {
70 | consume = false;
71 | }
72 | }
73 | if (consume == false) {
74 | return false;
75 | }
76 | float curX = motionEvent.getX();
77 | float curY = motionEvent.getY();
78 |
79 | int dx = (int) (curX - lastX);
80 | int dy = (int) (curY - lastY);
81 | rect.left += dx;
82 | rect.right += dx;
83 | rect.top += dy;
84 | rect.bottom += dy;
85 | invalidate();
86 | lastX = curX;
87 | lastY = curY;
88 | return true;
89 | }
90 |
91 | @Override
92 | protected void onDraw(Canvas canvas) {
93 | super.onDraw(canvas);
94 | canvas.translate(rect.left, rect.top);
95 | mPaint.setStyle(Paint.Style.FILL);
96 | mPaint.setColor(0xbbFFFFFF);
97 | canvas.drawRect(0, 0, rect.right - rect.left, rect.bottom - rect.top, mPaint);
98 | mPaint.setStyle(Paint.Style.STROKE);
99 | mPaint.setColor(Color.BLACK);
100 | canvas.drawRect(0, 0, rect.right - rect.left, rect.bottom - rect.top, mPaint);
101 | mPaint.setStyle(Paint.Style.FILL);
102 | int w = rect.right - rect.left;
103 | canvas.drawLine(0, 0, w, 0, mPaint);
104 | for (int i = 0; i <= w; i += m20DP) {
105 | canvas.drawLine(i, -maxHeight, i, maxHeight , mPaint);
106 | canvas.rotate(90, i, maxHeight);
107 | canvas.drawText(sizeConverter.convert(getContext(), i).toString(), i, maxHeight, mPaint);
108 | canvas.rotate(-90, i, maxHeight);
109 | for (int j = i; j <= w && j < i + m20DP; j += m20DP / 10) {
110 | canvas.drawLine(j, -minHeight, j, minHeight, mPaint);
111 | }
112 | }
113 | }
114 |
115 | ISizeConverter sizeConverter = ISizeConverter.CONVERTER;
116 |
117 | @Override
118 | public void onSizeConvertChange(ISizeConverter converter) {
119 | sizeConverter = converter;
120 | invalidate();
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/LayerTxtAdapter.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.view.View;
8 |
9 | import com.wanjian.sak.utils.ScreenUtils;
10 |
11 | /**
12 | * Created by wanjian on 2016/10/26.
13 | *
14 | * 在view左上角画浅白色背景和文本
15 | */
16 |
17 | public abstract class LayerTxtAdapter extends ViewLayer {
18 | private Paint mPaint;
19 | private Rect mRect = new Rect();
20 |
21 | @Override
22 | protected void onAttach(View rootView) {
23 | super.onAttach(rootView);
24 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
25 | mPaint.setTextSize(ScreenUtils.dp2px(getContext(), 10));
26 | mPaint.setColor(getColor());
27 | }
28 |
29 | @Override
30 | protected void onDraw(Canvas canvas, View view) {
31 | String txt = getTxt(view);
32 | if (txt == null) {
33 | txt = "";
34 | }
35 | drawTxt(txt, canvas, view);
36 | }
37 |
38 | protected abstract String getTxt(View view);
39 |
40 | private void drawTxt(String txt, Canvas canvas, View view) {
41 | mPaint.setTextSize(getTextSize());
42 | mPaint.getTextBounds(txt, 0, txt.length(), mRect);
43 | mPaint.setColor(getBackgroundColor());
44 | canvas.drawRect(0, 0, mRect.width(), mRect.height(), mPaint);
45 | mPaint.setColor(getColor());
46 | canvas.drawText(txt, 0, mRect.height(), mPaint);
47 | }
48 |
49 | protected int getColor() {
50 | return Color.BLACK;
51 | }
52 |
53 | protected int getBackgroundColor() {
54 | return 0x88ffffff;
55 | }
56 |
57 | public float getTextSize() {
58 | return ScreenUtils.dp2px(getContext(), 10);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/PaddingLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.Drawable;
8 | import android.view.View;
9 |
10 | import com.wanjian.sak.R;
11 | import com.wanjian.sak.converter.ISizeConverter;
12 | import com.wanjian.sak.layer.ISize;
13 | import com.wanjian.sak.utils.ScreenUtils;
14 |
15 | import java.text.DecimalFormat;
16 |
17 |
18 | /**
19 | * Created by wanjian on 2016/10/23.
20 | */
21 |
22 | public class PaddingLayer extends ViewLayer implements ISize {
23 | private Paint mTextPaint;
24 | private Paint mBgPaint;
25 | private Paint mPaddingPaint;
26 | private int mTxtColor = 0xFF000000;
27 | private int mBgColor = 0x88FFFFFF;
28 | private int mPaddingColor = 0x3300FF0D;
29 | private Rect mRect = new Rect();
30 | private DecimalFormat mFormat = new DecimalFormat("#.###");
31 |
32 | @Override
33 | protected void onAttach(View rootView) {
34 | super.onAttach(rootView);
35 | mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
36 | mTextPaint.setTextSize(ScreenUtils.dp2px(getContext(), 10));
37 | mTextPaint.setColor(mTxtColor);
38 |
39 | mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
40 | mBgPaint.setColor(mBgColor);
41 |
42 | mPaddingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
43 | mPaddingPaint.setColor(mPaddingColor);
44 | }
45 |
46 | protected void onDraw(Canvas canvas, View view) {
47 | int l = view.getPaddingLeft();
48 | int t = view.getPaddingTop();
49 | int r = view.getPaddingRight();
50 | int b = view.getPaddingBottom();
51 | int w = view.getWidth();
52 | int h = view.getHeight();
53 |
54 | canvas.drawRect(0, 0, l, h, mPaddingPaint);
55 | canvas.drawRect(0, 0, w, t, mPaddingPaint);
56 | canvas.drawRect(w - r, 0, w, h, mPaddingPaint);
57 | canvas.drawRect(0, h - b, w, h, mPaddingPaint);
58 |
59 | ISizeConverter converter = getSizeConverter();
60 | Context context = getContext();
61 | if (l != 0) {
62 | String txt = "L" + mFormat.format(converter.convert(context, l).getLength());
63 | mTextPaint.getTextBounds(txt, 0, txt.length(), mRect);
64 | canvas.drawRect(0, h / 2f - mRect.height() / 2f, mRect.width(), h / 2f + mRect.height() / 2f, mBgPaint);
65 | canvas.drawText(txt, 0, h / 2f + mRect.height() / 2f, mTextPaint);
66 | }
67 | if (t != 0) {
68 | String txt = "T" + mFormat.format(converter.convert(context, t).getLength());
69 | mTextPaint.getTextBounds(txt, 0, txt.length(), mRect);
70 | canvas.drawRect(w / 2f - mRect.width() / 2f, 0, w / 2f + mRect.width() / 2f, mRect.height(), mBgPaint);
71 | canvas.drawText(txt, w / 2f - mRect.width() / 2f, mRect.height(), mTextPaint);
72 | }
73 | if (r != 0) {
74 | String txt = "R" + mFormat.format(converter.convert(context, r).getLength());
75 | mTextPaint.getTextBounds(txt, 0, txt.length(), mRect);
76 | canvas.drawRect(w - mRect.width(), h / 2f - mRect.height() / 2f, w, h / 2f + mRect.height() / 2f, mBgPaint);
77 | canvas.drawText(txt, w - mRect.width(), h / 2f + mRect.height() / 2f, mTextPaint);
78 | }
79 | if (b != 0) {
80 | String txt = "B" + mFormat.format(converter.convert(context, b).getLength());
81 | mTextPaint.getTextBounds(txt, 0, txt.length(), mRect);
82 | canvas.drawRect(w / 2f - mRect.width() / 2f, h - mRect.height(), w / 2f + mRect.width() / 2f, h, mBgPaint);
83 | canvas.drawText(txt, w / 2f - mRect.width() / 2f, h, mTextPaint);
84 | }
85 | }
86 |
87 |
88 | private ISizeConverter getSizeConverter() {
89 | return sizeConverter == null ? ISizeConverter.CONVERTER : sizeConverter;
90 | }
91 |
92 | private ISizeConverter sizeConverter;
93 |
94 | @Override
95 | public void onSizeConvertChange(ISizeConverter converter) {
96 | sizeConverter = converter;
97 | invalidate();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/TextColorLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.drawable.Drawable;
4 | import android.text.SpannableString;
5 | import android.view.View;
6 | import android.widget.TextView;
7 |
8 | import com.wanjian.sak.R;
9 |
10 |
11 | /**
12 | * Created by wanjian on 2016/10/26.
13 | */
14 |
15 | public class TextColorLayer extends LayerTxtAdapter {
16 |
17 |
18 | @Override
19 | protected String getTxt(View view) {
20 | if (view instanceof TextView) {
21 | CharSequence charSequence = ((TextView) view).getText();
22 | if (charSequence instanceof SpannableString) {
23 | // TODO: 2019/2/17
24 | }
25 | int color = ((TextView) view).getCurrentTextColor();
26 | return String.format("#%08x", color);
27 |
28 | }
29 | return "";
30 | }
31 |
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/TextSizeLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.drawable.Drawable;
4 | import android.view.View;
5 | import android.widget.TextView;
6 |
7 | import com.wanjian.sak.R;
8 | import com.wanjian.sak.converter.ISizeConverter;
9 | import com.wanjian.sak.layer.ISize;
10 |
11 |
12 | /**
13 | * Created by wanjian on 2016/10/26.
14 | */
15 |
16 | public class TextSizeLayer extends LayerTxtAdapter implements ISize {
17 | @Override
18 | protected String getTxt(View view) {
19 | if (view instanceof TextView) {
20 | float size = ((TextView) view).getTextSize();
21 | return String.valueOf(getSizeConverter().convert(getContext(), size).getLength());
22 | }
23 |
24 | return "";
25 | }
26 |
27 |
28 |
29 | private ISizeConverter getSizeConverter() {
30 | return sizeConverter == null ? ISizeConverter.CONVERTER : sizeConverter;
31 | }
32 |
33 | private ISizeConverter sizeConverter;
34 |
35 | @Override
36 | public void onSizeConvertChange(ISizeConverter converter) {
37 | sizeConverter = converter;
38 | invalidate();
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/VerticalMeasureView.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.view.InputEvent;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 |
11 | import com.wanjian.sak.converter.ISizeConverter;
12 | import com.wanjian.sak.layer.ISize;
13 | import com.wanjian.sak.layer.Layer;
14 | import com.wanjian.sak.utils.ScreenUtils;
15 |
16 |
17 | /**
18 | * Created by wanjian on 2016/11/10.
19 | */
20 |
21 | public class VerticalMeasureView extends Layer implements ISize {
22 | protected Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
23 | protected int m20DP;
24 | protected int maxHeight;
25 | protected int minHeight;
26 | private int width;
27 | private boolean consume;
28 | private float lastX, lastY;
29 | private Rect rect = new Rect();
30 |
31 | @Override
32 | protected void onAttach(View rootView) {
33 | super.onAttach(rootView);
34 | init();
35 | }
36 |
37 |
38 | private void init() {
39 | mPaint.setColor(Color.BLACK);
40 | m20DP = ScreenUtils.dp2px(getContext(), 20);
41 | mPaint.setTextSize(ScreenUtils.dp2px(getContext(), 8));
42 | maxHeight = ScreenUtils.dp2px(getContext(), 10);
43 | minHeight = ScreenUtils.dp2px(getContext(), 5);
44 | width = ScreenUtils.dp2px(getContext(), 60);
45 | rect.left = (int) (getRootView().getWidth() / 2f - width / 2f);
46 | rect.top = 0;
47 | rect.right = (int) (getRootView().getWidth() / 2f + width / 2f);
48 | rect.bottom = getRootView().getHeight();
49 | invalidate();
50 | }
51 |
52 | @Override
53 | protected void onAfterTraversal(View rootView) {
54 | super.onAfterTraversal(rootView);
55 | invalidate();
56 | }
57 |
58 | @Override
59 | protected boolean onBeforeInputEvent(View rootView, InputEvent event) {
60 | if (!(event instanceof MotionEvent)) {
61 | return false;
62 | }
63 | MotionEvent motionEvent = ((MotionEvent) event);
64 | if (motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
65 | lastX = motionEvent.getX();
66 | lastY = motionEvent.getY();
67 | if (rect.contains((int) lastX, (int) lastY)) {
68 | consume = true;
69 | } else {
70 | consume = false;
71 | }
72 | }
73 | if (consume == false) {
74 | return false;
75 | }
76 | float curX = motionEvent.getX();
77 | float curY = motionEvent.getY();
78 |
79 | int dx = (int) (curX - lastX);
80 | int dy = (int) (curY - lastY);
81 | rect.left += dx;
82 | rect.right += dx;
83 | rect.top += dy;
84 | rect.bottom += dy;
85 | invalidate();
86 | lastX = curX;
87 | lastY = curY;
88 | return true;
89 | }
90 |
91 | @Override
92 | protected void onDraw(Canvas canvas) {
93 | super.onDraw(canvas);
94 | canvas.translate(rect.left, rect.top);
95 | mPaint.setStyle(Paint.Style.FILL);
96 | mPaint.setColor(0xbbFFFFFF);
97 | canvas.drawRect(0, 0, rect.right - rect.left, rect.bottom - rect.top, mPaint);
98 | mPaint.setStyle(Paint.Style.STROKE);
99 | mPaint.setColor(Color.BLACK);
100 | canvas.drawRect(0, 0, rect.right - rect.left, rect.bottom - rect.top, mPaint);
101 | mPaint.setStyle(Paint.Style.FILL);
102 | int h = rect.bottom - rect.top;
103 | int w = rect.right - rect.left;
104 | canvas.drawLine(0, 0, w, 0, mPaint);
105 |
106 | for (int i = 0; i <= h; i += m20DP) {
107 | canvas.drawLine(-maxHeight, i, maxHeight, i, mPaint);
108 | canvas.drawText(sizeConverter.convert(getContext(), i).toString(), maxHeight, i, mPaint);
109 | for (int j = i; j <= h && j < i + m20DP; j += m20DP / 10) {
110 | canvas.drawLine(-minHeight, j, minHeight, j, mPaint);
111 | }
112 | }
113 | }
114 |
115 | ISizeConverter sizeConverter = ISizeConverter.CONVERTER;
116 |
117 | @Override
118 | public void onSizeConvertChange(ISizeConverter converter) {
119 | sizeConverter = converter;
120 | invalidate();
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/ViewClassLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.view.View;
6 |
7 | import com.wanjian.sak.R;
8 |
9 | /**
10 | * Created by wanjian on 2017/3/9.
11 | */
12 |
13 | public class ViewClassLayer extends LayerTxtAdapter {
14 |
15 |
16 | @Override
17 | protected String getTxt(View view) {
18 | return view.getClass().getSimpleName();
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/ViewLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Region;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import com.wanjian.sak.layer.IClip;
9 | import com.wanjian.sak.layer.IRange;
10 | import com.wanjian.sak.layer.Layer;
11 |
12 | public abstract class ViewLayer extends Layer implements IRange, IClip {
13 | private int mStartLayer;
14 | private int mEndLayer = 100;
15 | private boolean isClip = true;
16 |
17 | @Override
18 | public void onStartRangeChange(int start) {
19 | mStartLayer = start;
20 | invalidate();
21 | }
22 |
23 | @Override
24 | public void onEndRangeChange(int end) {
25 | mEndLayer = end;
26 | invalidate();
27 | }
28 |
29 | @Override
30 | public void onClipChange(boolean clip) {
31 | isClip = clip;
32 | invalidate();
33 | }
34 |
35 | @Override
36 | protected void onAttach(View rootView) {
37 | super.onAttach(rootView);
38 | }
39 |
40 | @Override
41 | protected final void onDraw(Canvas canvas) {
42 | super.onDraw(canvas);
43 | traversals(canvas, getRootView(), 0);
44 | }
45 |
46 | @Override
47 | protected void onAfterTraversal(View rootView) {
48 | super.onAfterTraversal(rootView);
49 | invalidate();
50 | }
51 |
52 | //
53 | // public void setStartLayer(int startLayer) {
54 | // this.mStartLayer = startLayer;
55 | // }
56 | //
57 | // public void setEndLayer(int endLayer) {
58 | // this.mEndLayer = endLayer;
59 | // }
60 |
61 | // public void setClip(boolean clip) {
62 | // isClip = clip;
63 | // }
64 |
65 | private void traversals(Canvas canvas, View view, int curLayer) {
66 | if (curLayer > mEndLayer) {
67 | return;
68 | }
69 | if (curLayer >= mStartLayer) {
70 | int count = canvas.save();
71 | onDraw(canvas, view);
72 | canvas.restoreToCount(count);
73 | }
74 |
75 | if (view instanceof ViewGroup) {
76 | ViewGroup vg = ((ViewGroup) view);
77 | int sx = view.getScrollX();
78 | int sy = view.getScrollY();
79 | canvas.save(); //save 1
80 | canvas.translate(-sx, -sy);
81 |
82 | for (int i = 0, len = vg.getChildCount(); i < len; i++) {
83 | View child = vg.getChildAt(i);
84 | canvas.save();//save 2
85 | canvas.translate(child.getX(), child.getY());
86 | if (isClip) {
87 | canvas.clipRect(0, 0, child.getWidth(), child.getHeight(), Region.Op.INTERSECT);
88 | }
89 |
90 | // canvas.save(); //save 3
91 | traversals(canvas, child, curLayer + 1);
92 | // canvas.restore();// restore 3
93 |
94 | canvas.restore();// restore 2
95 | }
96 | canvas.restore(); // restore 1
97 | }
98 | }
99 |
100 | protected abstract void onDraw(Canvas canvas, View view);
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl/WidthHeightLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl;
2 |
3 | import android.graphics.drawable.Drawable;
4 | import android.view.View;
5 |
6 | import com.wanjian.sak.R;
7 | import com.wanjian.sak.converter.ISizeConverter;
8 | import com.wanjian.sak.layer.ISize;
9 |
10 | /**
11 | *
12 | */
13 |
14 | public class WidthHeightLayer extends LayerTxtAdapter implements ISize {
15 |
16 |
17 | @Override
18 | protected String getTxt(View view) {
19 | int w = view.getWidth();
20 | int h = view.getHeight();
21 | ISizeConverter converter = getSizeConverter();
22 | return converter.convert(getContext(), w).getLength() + ":" + converter.convert(getContext(), h).getLength();
23 | }
24 |
25 |
26 | private ISizeConverter getSizeConverter() {
27 | return sizeConverter == null ? ISizeConverter.CONVERTER : sizeConverter;
28 | }
29 |
30 | private ISizeConverter sizeConverter;
31 |
32 | @Override
33 | public void onSizeConvertChange(ISizeConverter converter) {
34 | sizeConverter = converter;
35 | invalidate();
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl_tmp/CornerMeasureView.java:
--------------------------------------------------------------------------------
1 | //package com.wanjian.sak.layer.impl_tmp;
2 | //
3 | //import android.content.Context;
4 | //import android.graphics.Canvas;
5 | //import android.graphics.Color;
6 | //import android.graphics.Paint;
7 | //import android.graphics.Path;
8 | //import android.graphics.RectF;
9 | //import android.graphics.drawable.Drawable;
10 | //import android.view.ViewGroup;
11 | //import android.widget.FrameLayout;
12 | //
13 | //import com.wanjian.sak.R;
14 | //import com.wanjian.sak.support.DragLayerView;
15 | //
16 | ///**
17 | // * Created by wanjian on 2016/11/10.
18 | // */
19 | //@Deprecated
20 | //public class CornerMeasureView extends DragLayerView {
21 | // private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
22 | // private int twoDP;
23 | // private int fourDP;
24 | // private int sixDP;
25 | // private int eightDP;
26 | // private int tenDP;
27 | // private int gap;
28 | // private int textSize;
29 | //
30 | // public CornerMeasureView(Context context) {
31 | // super(context);
32 | // init();
33 | // }
34 | //
35 | // @Override
36 | // public Drawable icon() {
37 | // return getResources().getDrawable(R.drawable.sak_corner_measure_icon);
38 | // }
39 | //
40 | // @Override
41 | // public String description() {
42 | // return getContext().getString(R.string.sak_corner_measure);
43 | // }
44 | //
45 | // private void init() {
46 | // mPaint.setColor(Color.BLACK);
47 | // mPaint.setStyle(Paint.Style.STROKE);
48 | // mPaint.setStrokeWidth(1);
49 | // twoDP = dp2px(2);
50 | // fourDP = dp2px(4);
51 | // sixDP = dp2px(6);
52 | // eightDP = dp2px(8);
53 | // tenDP = dp2px(10);
54 | // gap = dp2px(8);
55 | // textSize = dp2px(6);
56 | // mPaint.setTextSize(textSize);
57 | // }
58 | //
59 | // @Override
60 | // protected void onDraw(Canvas canvas) {
61 | // super.onDraw(canvas);
62 | //
63 | // int w = getWidth();
64 | // int h = getHeight();
65 | // mPaint.setStyle(Paint.Style.STROKE);
66 | // drawRound(canvas, 0, 0, w, h, twoDP);
67 | // drawRound(canvas, gap * 1, gap * 1, w - gap * 1, h - gap * 1, fourDP);
68 | // drawRound(canvas, gap * 2, gap * 2, w - gap * 2, h - gap * 2, sixDP);
69 | // drawRound(canvas, gap * 3, gap * 3, w - gap * 3, h - gap * 3, eightDP);
70 | // drawRound(canvas, gap * 4, gap * 4, w - gap * 4, h - gap * 4, tenDP);
71 | //
72 | //
73 | // mPaint.setStyle(Paint.Style.FILL);
74 | // canvas.drawText("2", w / 2, 0, mPaint);
75 | // canvas.drawText("4", w / 2, gap * 1, mPaint);
76 | // canvas.drawText("6", w / 2, gap * 2, mPaint);
77 | // canvas.drawText("8", w / 2, gap * 3, mPaint);
78 | // canvas.drawText("10", w / 2, gap * 4, mPaint);
79 | //
80 | // }
81 | //
82 | // private void drawRound(Canvas canvas, int l, int t, int r, int b, int corner) {
83 | //
84 | // Path path = new Path();
85 | // path.arcTo(new RectF(l, t, l + corner * 2, t + corner * 2), 180, 90);
86 | //
87 | // path.arcTo(new RectF(r - corner * 2, t, r, t + corner * 2), -90, 90);
88 | //
89 | // path.arcTo(new RectF(r - corner * 2, b - corner * 2, r, b), 0, 90);
90 | //
91 | // path.arcTo(new RectF(l, b - corner * 2, l + corner * 2, b), 90, 90);
92 | //
93 | // path.close();
94 | // canvas.drawPath(path, mPaint);
95 | //
96 | // }
97 | //
98 | //
99 | // @Override
100 | // public ViewGroup.LayoutParams getLayoutParams(FrameLayout.LayoutParams params) {
101 | // params.width = dp2px(150);
102 | // params.height = dp2px(120);
103 | // return params;
104 | // }
105 | //
106 | //}
107 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/layer/impl_tmp/InfoLayer.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.layer.impl_tmp;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.view.View;
6 |
7 | import com.wanjian.sak.R;
8 |
9 |
10 | /**
11 | * Created by wanjian on 2016/10/24.
12 | */
13 | @Deprecated
14 | public class InfoLayer {
15 | public static final int INFO_KEY = R.layout.sak_view_info_layout;
16 |
17 | // public InfoLayer(Context context) {
18 | // super(context);
19 | // }
20 | //
21 | //
22 | // @Override
23 | // protected String getTxt(View view) {
24 | // Object obj = view.getTag(INFO_KEY);
25 | // String info;
26 | // if (obj == null) {
27 | // info = "";
28 | // } else {
29 | // info = obj.toString();
30 | // }
31 | // return info;
32 | //
33 | // }
34 | //
35 | // @Override
36 | // public Drawable icon() {
37 | // return getContext().getResources().getDrawable(R.drawable.sak_custom_info_icon);
38 | // }
39 | //
40 | // @Override
41 | // public String description() {
42 | // return getContext().getString(R.string.sak_personal_info);
43 | // }
44 | }
45 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/support/DragLayerView.java:
--------------------------------------------------------------------------------
1 | //package com.wanjian.sak.support;
2 | //
3 | //import android.content.Context;
4 | //import android.support.v4.view.GestureDetectorCompat;
5 | //import android.view.GestureDetector;
6 | //import android.view.MotionEvent;
7 | //import android.view.View;
8 | //
9 | //import com.wanjian.sak.layer.AbsLayer;
10 | //
11 | //
12 | ///**
13 | // * Created by wanjian on 2017/2/20.
14 | // */
15 | //
16 | //public abstract class DragLayerView extends AbsLayer {
17 | //
18 | // private OnTouchListener touchListener;
19 | //
20 | // public DragLayerView(Context context) {
21 | // super(context);
22 | // init();
23 | // }
24 | //
25 | // private void init() {
26 | // final GestureDetectorCompat detectorCompat = new GestureDetectorCompat(getContext(), new GestureDetector.SimpleOnGestureListener() {
27 | // private float lastRowX;
28 | // private float lastRowY;
29 | //
30 | // @Override
31 | // public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
32 | // setTranslationX(getTranslationX() + (e2.getRawX() - lastRowX));
33 | // setTranslationY(getTranslationY() + (e2.getRawY() - lastRowY));
34 | // lastRowX = e2.getRawX();
35 | // lastRowY = e2.getRawY();
36 | // return true;
37 | // }
38 | //
39 | // @Override
40 | // public boolean onDown(MotionEvent e) {
41 | // lastRowX = e.getRawX();
42 | // lastRowY = e.getRawY();
43 | // return true;
44 | // }
45 | // });
46 | // detectorCompat.setIsLongpressEnabled(false);
47 | // super.setOnTouchListener(new View.OnTouchListener() {
48 | // @Override
49 | // public boolean onTouch(View v, MotionEvent event) {
50 | // boolean b = false;
51 | // if (touchListener != null) {
52 | // b = touchListener.onTouch(v, event);
53 | // }
54 | // return detectorCompat.onTouchEvent(event) || b;
55 | // }
56 | // });
57 | // }
58 | //
59 | // @Override
60 | // public void setOnTouchListener(OnTouchListener l) {
61 | // touchListener = l;
62 | // }
63 | //}
64 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/support/FPSView.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.support;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.graphics.Path;
8 | import android.util.AttributeSet;
9 | import android.view.View;
10 |
11 | import androidx.annotation.NonNull;
12 | import androidx.annotation.Nullable;
13 |
14 | import com.wanjian.sak.utils.LoopQueue;
15 |
16 | public class FPSView extends View {
17 | private Paint paint;
18 | private float density;
19 | private Path path = new Path();
20 | private LoopQueue data;
21 |
22 | public FPSView(@NonNull Context context) {
23 | this(context, null);
24 | }
25 |
26 | public FPSView(@NonNull Context context, @Nullable AttributeSet attrs) {
27 | super(context, attrs);
28 | setWillNotDraw(false);
29 | density = getRootView().getResources().getDisplayMetrics().density;
30 | paint = new Paint(Paint.ANTI_ALIAS_FLAG);
31 | paint.setTextSize(dp2px(10));
32 | paint.setStyle(Paint.Style.STROKE);
33 | paint.setStrokeWidth(dp2px(0.8f));
34 | }
35 |
36 | protected int dp2px(float dip) {
37 | return (int) (dip * density + 0.5);
38 | }
39 |
40 |
41 | public void update(LoopQueue data) {
42 | this.data = data;
43 | postInvalidate();
44 | }
45 |
46 | @Override
47 | protected void onDraw(Canvas canvas) {
48 | super.onDraw(canvas);
49 | if (data == null) {
50 | return;
51 | }
52 | float width = getWidth();
53 | int height = getHeight();
54 | float gap = width / (data.maxSize() - 1);
55 | float x = width - gap * data.size();
56 |
57 | paint.setColor(Color.RED);
58 | path.reset();
59 | path.moveTo(x, height);
60 |
61 | data.reset();
62 | while (data.has()) {
63 | float y = -dp2px(data.take()) * 2;
64 | path.lineTo(x, y);
65 | x += gap;
66 | }
67 | canvas.translate(0, height);
68 | canvas.drawPath(path, paint);
69 |
70 | paint.setColor(Color.GREEN);
71 | int dp16 = dp2px(16) * 2;
72 | canvas.drawLine(0, -dp16, width, -dp16, paint);
73 | canvas.drawText("16", 5, -dp16, paint);
74 |
75 | paint.setColor(Color.RED);
76 | int dp30 = dp2px(30) * 2;
77 | canvas.drawLine(0, -dp30, width, -dp30, paint);
78 | canvas.drawText("30", 5, -dp30, paint);
79 |
80 | paint.setColor(Color.MAGENTA);
81 | int dp50 = dp2px(50) * 2;
82 | canvas.drawLine(0, -dp50, width, -dp50, paint);
83 | canvas.drawText("50", 5, -dp50, paint);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/canvas/compact/CanvasCompact.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.canvas.compact;
2 |
3 | import android.graphics.Canvas;
4 | import android.os.Build;
5 | import android.view.ViewRootImpl;
6 |
7 | public abstract class CanvasCompact {
8 |
9 | protected ViewRootImpl viewRootImpl;
10 |
11 | CanvasCompact(ViewRootImpl viewRootImpl) {
12 | this.viewRootImpl = viewRootImpl;
13 | }
14 |
15 | public static CanvasCompact get(ViewRootImpl viewRootImpl) {
16 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
17 | return new HardwareCanvasV31Impl(viewRootImpl);
18 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
19 | return new HardwareCanvasV29Impl(viewRootImpl);
20 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
21 | return new HardwareCanvasV26Impl(viewRootImpl);
22 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
23 | return new HardwareCanvasV24Impl(viewRootImpl);
24 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
25 | return new HardwareCanvasV23Impl(viewRootImpl);
26 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
27 | return new HardwareCanvasV21Impl(viewRootImpl);
28 | } else {
29 | throw new RuntimeException("unsupport android version");
30 | }
31 | }
32 |
33 | public abstract Canvas requireCanvas();
34 |
35 | public abstract void releaseCanvas();
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/canvas/compact/HardwareCanvasV24Impl.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.canvas.compact;
2 |
3 | import android.view.ThreadedRenderer;
4 | import android.view.View;
5 | import android.view.ViewRootImpl;
6 |
7 | import java.lang.reflect.Method;
8 |
9 | public class HardwareCanvasV24Impl extends HardwareCanvasV23Impl {
10 | HardwareCanvasV24Impl(ViewRootImpl viewRootImpl) {
11 | super(viewRootImpl);
12 | }
13 |
14 | protected boolean isThreadRendererEnable(ThreadedRenderer threadRenderer) {
15 | try {
16 | Method isEnabledM = ThreadedRenderer.class.getDeclaredMethod("isEnabled");
17 | isEnabledM.setAccessible(true);
18 | return (boolean) isEnabledM.invoke(threadRenderer);
19 | } catch (Exception e) {
20 | throw new RuntimeException(e);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/canvas/compact/HardwareCanvasV26Impl.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.canvas.compact;
2 |
3 | import android.view.ThreadedRenderer;
4 | import android.view.View;
5 | import android.view.ViewParent;
6 | import android.view.ViewRootImpl;
7 |
8 | import java.lang.reflect.Field;
9 |
10 | class HardwareCanvasV26Impl extends HardwareCanvasV24Impl {
11 |
12 | HardwareCanvasV26Impl(ViewRootImpl viewRootImpl) {
13 | super(viewRootImpl);
14 | }
15 |
16 |
17 | protected ThreadedRenderer getHardwareRenderer(ViewRootImpl viewRootImpl) {
18 | try {
19 | Field mAttachInfoF = ViewRootImpl.class.getDeclaredField("mAttachInfo");
20 | mAttachInfoF.setAccessible(true);
21 | Object mAttachInfo = mAttachInfoF.get(viewRootImpl);
22 | Field threadedRendererF;
23 | threadedRendererF = mAttachInfo.getClass().getDeclaredField("mThreadedRenderer");
24 | threadedRendererF.setAccessible(true);
25 | return (ThreadedRenderer) threadedRendererF.get(mAttachInfo);
26 | } catch (Exception e) {
27 | throw new RuntimeException(e);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/canvas/compact/HardwareCanvasV29Impl.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.canvas.compact;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.FrameInfo;
5 | import android.graphics.HardwareRenderer;
6 | import android.graphics.RecordingCanvas;
7 | import android.graphics.RenderNode;
8 | import android.view.Choreographer;
9 | import android.view.ThreadedRenderer;
10 | import android.view.View;
11 | import android.view.ViewRootImpl;
12 |
13 | import java.lang.reflect.Field;
14 | import java.lang.reflect.Method;
15 |
16 | class HardwareCanvasV29Impl extends HardwareCanvasV26Impl {
17 | private RenderNode mRootNode;
18 | private RecordingCanvas canvas;
19 | private int saveCount;
20 |
21 | HardwareCanvasV29Impl(ViewRootImpl viewRootImpl) {
22 | super(viewRootImpl);
23 | }
24 |
25 | @Override
26 | protected Canvas innerRequire() {
27 | if (threadRenderer != null && isThreadRendererEnable(threadRenderer)) {
28 | markDrawStart(Choreographer.getInstance());
29 | mRootNode = getRooNodeV29(threadRenderer);
30 | canvas = mRootNode.beginRecording(getSurfaceW(threadRenderer), getSurfaceH(threadRenderer));
31 | canvas.translate(getInsertLeft(), getInsertTop());
32 | canvas.translate(-getHardwareXOffset(), -getHardwareYOffset());
33 | saveCount = canvas.save();
34 | canvas.enableZ();
35 | canvas.drawRenderNode(getUpdateDisplayListIfDirty());
36 | canvas.disableZ();
37 | return canvas;
38 | } else {
39 | mRootNode = null;
40 | return getSoftCanvas().requireCanvas();
41 | }
42 | }
43 |
44 | @Override
45 | protected void innerRelease() {
46 | if (mRootNode != null) {
47 | // canvas.disableZ();
48 | canvas.restoreToCount(saveCount);
49 | mRootNode.endRecording();
50 | nSyncAndDrawFrame();
51 | } else {
52 | getSoftCanvas().releaseCanvas();
53 | }
54 | }
55 |
56 | private RenderNode getUpdateDisplayListIfDirty() {
57 | try {
58 | Method method = View.class.getDeclaredMethod("updateDisplayListIfDirty");
59 | method.setAccessible(true);
60 | return (RenderNode) method.invoke(viewRootImpl.getView());
61 | } catch (Exception e) {
62 | throw new RuntimeException(e);
63 | }
64 | }
65 |
66 | protected RenderNode getRooNodeV29(ThreadedRenderer hardwareRenderer) {
67 | try {
68 | Field mRootNodeF = HardwareRenderer.class.getDeclaredField("mRootNode");
69 | mRootNodeF.setAccessible(true);
70 | return (RenderNode) mRootNodeF.get(hardwareRenderer);
71 | } catch (Exception e) {
72 | throw new RuntimeException(e);
73 | }
74 | }
75 |
76 | @Override
77 | protected void markDrawStart(Choreographer choreographer) {
78 | try {
79 | FrameInfo frameInfo = getFrameInfo();
80 | frameInfo.markDrawStart();
81 | } catch (Exception e) {
82 | throw new RuntimeException(e);
83 | }
84 | }
85 |
86 | private FrameInfo getFrameInfo() {
87 | try {
88 | Field mFrameInfoF = Choreographer.class.getDeclaredField("mFrameInfo");
89 | mFrameInfoF.setAccessible(true);
90 | FrameInfo frameInfo = (FrameInfo) mFrameInfoF.get(Choreographer.getInstance());
91 | return frameInfo;
92 | } catch (Exception e) {
93 | throw new RuntimeException(e);
94 | }
95 | }
96 |
97 | @Override
98 | protected void nSyncAndDrawFrame() {
99 | // int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
100 | try {
101 | ThreadedRenderer renderer = getHardwareRenderer(viewRootImpl);
102 | Method method = android.graphics.HardwareRenderer.class.getDeclaredMethod("syncAndDrawFrame", FrameInfo.class);
103 | method.setAccessible(true);
104 | method.invoke(renderer, getFrameInfo());
105 | } catch (Exception e) {
106 | throw new RuntimeException(e);
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/canvas/compact/HardwareCanvasV31Impl.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.canvas.compact;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.FrameInfo;
5 | import android.graphics.HardwareRenderer;
6 | import android.graphics.RecordingCanvas;
7 | import android.graphics.RenderNode;
8 | import android.view.Choreographer;
9 | import android.view.ThreadedRenderer;
10 | import android.view.View;
11 | import android.view.ViewFrameInfo;
12 | import android.view.ViewRootImpl;
13 |
14 | import java.lang.reflect.Field;
15 | import java.lang.reflect.Method;
16 |
17 | class HardwareCanvasV31Impl extends HardwareCanvasV29Impl {
18 | HardwareCanvasV31Impl(ViewRootImpl viewRootImpl) {
19 | super(viewRootImpl);
20 | }
21 |
22 | @Override
23 | protected void markDrawStart(Choreographer choreographer) {
24 | try {
25 | ViewFrameInfo frameInfo = getViewFrameInfo();
26 | frameInfo.markDrawStart();
27 | } catch (Exception e) {
28 | throw new RuntimeException(e);
29 | }
30 | }
31 |
32 | private ViewFrameInfo getViewFrameInfo() {
33 | try {
34 | Field mFrameInfoF = ViewRootImpl.class.getDeclaredField("mViewFrameInfo");
35 | mFrameInfoF.setAccessible(true);
36 | ViewFrameInfo frameInfo = (ViewFrameInfo) mFrameInfoF.get(viewRootImpl);
37 | return frameInfo;
38 | } catch (Exception e) {
39 | throw new RuntimeException(e);
40 | }
41 | }
42 |
43 | private FrameInfo getFrameInfo() {
44 | try {
45 | Method mFrameInfoM = ViewRootImpl.class.getDeclaredMethod("getUpdatedFrameInfo");
46 | mFrameInfoM.setAccessible(true);
47 | FrameInfo frameInfo = (FrameInfo) mFrameInfoM.invoke(viewRootImpl);
48 | return frameInfo;
49 | } catch (Exception e) {
50 | throw new RuntimeException(e);
51 | }
52 | }
53 |
54 | @Override
55 | protected void nSyncAndDrawFrame() {
56 | try {
57 | ThreadedRenderer renderer = getHardwareRenderer(viewRootImpl);
58 | Method method = HardwareRenderer.class.getDeclaredMethod("syncAndDrawFrame", FrameInfo.class);
59 | method.setAccessible(true);
60 | method.invoke(renderer, getFrameInfo());
61 | } catch (Exception e) {
62 | throw new RuntimeException(e);
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/canvas/compact/SoftCanvas.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.canvas.compact;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Rect;
5 | import android.view.Surface;
6 | import android.view.View;
7 | import android.view.ViewRootImpl;
8 |
9 | import java.lang.reflect.Field;
10 |
11 | class SoftCanvas extends CanvasCompact {
12 |
13 | private int count;
14 | private Rect rect = new Rect();
15 | private Canvas canvas;
16 | private Surface surface;
17 |
18 | SoftCanvas(ViewRootImpl viewRootImpl) {
19 | super(viewRootImpl);
20 |
21 | }
22 |
23 | @Override
24 | public Canvas requireCanvas() {
25 | if (count != 0) {
26 | throw new IllegalStateException("count == " + count);
27 | }
28 | count++;
29 | rect.left = 0;
30 | rect.top = 0;
31 | View rootView = viewRootImpl.getView();
32 | rect.right = rootView.getWidth();
33 | rect.bottom = rootView.getHeight();
34 | canvas = getSurface().lockCanvas(rect);
35 | return canvas;
36 | }
37 |
38 | @Override
39 | public void releaseCanvas() {
40 | if (count != 1) {
41 | throw new IllegalStateException("count == " + count);
42 | }
43 | count--;
44 | getSurface().unlockCanvasAndPost(canvas);
45 | }
46 |
47 |
48 | private Surface getSurface() {
49 | if (surface != null) {
50 | return surface;
51 | }
52 | try {
53 | Field mSurfaceF = ViewRootImpl.class.getDeclaredField("mSurface");
54 | mSurfaceF.setAccessible(true);
55 | surface = (Surface) mSurfaceF.get(viewRootImpl);
56 | } catch (Exception e) {
57 | throw new RuntimeException(e);
58 | }
59 | return surface;
60 | }
61 |
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/canvaspool/CanvasPoolCompact.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.canvaspool;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.RecordingCanvas;
5 | import android.os.Build;
6 | import android.util.Pools;
7 | import android.view.DisplayListCanvas;
8 |
9 | import java.lang.ref.WeakReference;
10 | import java.lang.reflect.Field;
11 | import java.util.ArrayList;
12 | import java.util.Iterator;
13 | import java.util.List;
14 |
15 | public class CanvasPoolCompact {
16 | private static CanvasPoolCompact sInstance = new CanvasPoolCompact();
17 |
18 | public static CanvasPoolCompact get() {
19 | return sInstance;
20 | }
21 |
22 | private List> listeners = new ArrayList<>();
23 |
24 | private CanvasPoolCompact() {
25 | Class clz;
26 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
27 | clz = RecordingCanvas.class;
28 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
29 | clz = DisplayListCanvas.class;
30 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
31 | try {
32 | clz = Class.forName("android.view.GLES20RecordingCanvas");
33 | } catch (ClassNotFoundException e) {
34 | throw new RuntimeException(e);
35 | }
36 | } else {
37 | throw new RuntimeException();
38 | }
39 | final Pools.SynchronizedPool origin;
40 | Field field;
41 | try {
42 | field = clz.getDeclaredField("sPool");
43 | field.setAccessible(true);
44 | origin = (Pools.SynchronizedPool) field.get(null);
45 | } catch (Exception e) {
46 | throw new RuntimeException(e);
47 | }
48 | Pools.SynchronizedPool pool = new Pools.SynchronizedPool(1) {
49 | @Override
50 | public Object acquire() {
51 | return origin.acquire();
52 | }
53 |
54 | @Override
55 | public boolean release(Object element) {
56 | boolean b = origin.release(element);
57 | Iterator> iterator = listeners.iterator();
58 | while (iterator.hasNext()) {
59 | WeakReference reference = iterator.next();
60 | CanvasRecycleListener recycleListener = reference.get();
61 | if (recycleListener == null) {
62 | iterator.remove();
63 | } else {
64 | recycleListener.onRecycle((Canvas) element);
65 | }
66 | }
67 | return b;
68 | }
69 | };
70 |
71 | try {
72 | field.set(null, pool);
73 | } catch (IllegalAccessException e) {
74 | throw new RuntimeException(e);
75 | }
76 | }
77 |
78 | public void registerListener(CanvasRecycleListener listener) {
79 | listeners.add(new WeakReference<>(listener));
80 | }
81 |
82 | public void removeListener(CanvasRecycleListener listener) {
83 | Iterator> iterator = listeners.iterator();
84 | while (iterator.hasNext()) {
85 | WeakReference reference = iterator.next();
86 | CanvasRecycleListener recycleListener = reference.get();
87 | if (recycleListener == null || recycleListener == listener) {
88 | iterator.remove();
89 | }
90 | }
91 | }
92 |
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/canvaspool/CanvasRecycleListener.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.canvaspool;
2 |
3 | import android.graphics.Canvas;
4 |
5 | public interface CanvasRecycleListener {
6 | void onRecycle(Canvas canvas);
7 | }
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/canvaspool/MySynchronizedPool.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.canvaspool;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Rect;
5 | import android.util.Pools;
6 | import android.view.DisplayListCanvas;
7 | import android.view.RenderNode;
8 | import android.view.Surface;
9 | import android.view.View;
10 | import android.view.ViewRootImpl;
11 |
12 | import java.lang.reflect.Field;
13 |
14 | public class MySynchronizedPool extends Pools.SynchronizedPool {
15 | private Pools.SynchronizedPool origin;
16 |
17 | public MySynchronizedPool(Pools.SynchronizedPool origin) {
18 | super(1, null);
19 | this.origin = origin;
20 | }
21 |
22 | @Override
23 | public Object acquire() {
24 | Object o = origin.acquire();
25 | System.out.println("MySynchronizedPool...acquire:" + o);
26 | return o;
27 | }
28 |
29 | @Override
30 | public boolean release(Object element) {
31 | System.out.println("MySynchronizedPool...release:" + element);//DisplayListCanvas
32 |
33 |
34 | // Canvas canvas = (Canvas) element;
35 | // int w = canvas.getWidth();
36 | // int h = canvas.getHeight();
37 |
38 | // canvas.clipRect(0,0,w*2,h*2, Region.Op.REPLACE);
39 | // canvas.drawColor(0x6600ff00);
40 | // System.out.println("w:h " + w + " " + h);
41 |
42 |
43 |
44 | //
45 | /*
46 | private RenderNode(String name, View owningView) {
47 | 147 mNativeRenderNode = nCreate(name);
48 | 148 NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
49 | 149 mOwningView = owningView;
50 | 150 }
51 | 151
52 | */
53 |
54 | ((Canvas) element).drawColor(0x88FF0000);
55 |
56 | try {
57 | Field mWidthF = DisplayListCanvas.class.getDeclaredField("mWidth");
58 | mWidthF.setAccessible(true);
59 | int mWidth = (int) mWidthF.get(element);
60 |
61 | Field mHeightF = DisplayListCanvas.class.getDeclaredField("mHeight");
62 | mHeightF.setAccessible(true);
63 | int mHeight = (int) mHeightF.get(element);
64 |
65 |
66 | Field field = DisplayListCanvas.class.getDeclaredField("mNode");
67 | field.setAccessible(true);
68 | RenderNode renderNode = (RenderNode) field.get(element);
69 | if (renderNode == null) {
70 | System.out.println(element + ":" + renderNode + ":" + mWidth + ":" + mHeight);
71 | } else {
72 | Field mOwningViewField = RenderNode.class.getDeclaredField("mOwningView");
73 | mOwningViewField.setAccessible(true);
74 | View view = (View) mOwningViewField.get(renderNode);
75 | System.out.println(element + ":" + renderNode + ":" + mWidth + ":" + mHeight + ":" + view);
76 | }
77 |
78 | } catch (Exception e) {
79 | throw new RuntimeException(e);
80 | }
81 |
82 | return origin.release(element);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/input/InputEventCompatProcessorV30.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.input;
2 |
3 | import android.content.Context;
4 | import android.view.InputEvent;
5 | import android.view.InputEventCompatProcessor;
6 | import android.view.ViewRootImpl;
7 |
8 | import java.lang.reflect.Field;
9 | import java.util.ArrayList;
10 | import java.util.Arrays;
11 | import java.util.List;
12 |
13 | public class InputEventCompatProcessorV30 extends InputEventCompatProcessor {
14 | private InputEventCompatProcessor originInputEventCompatProcessor;
15 | private InputEventListener listener;
16 |
17 | public InputEventCompatProcessorV30(Context context, ViewRootImpl viewRootImpl, InputEventListener listener) {
18 | super(context);
19 | this.listener = listener;
20 | try {
21 | Field field = viewRootImpl.getClass().getDeclaredField("mInputCompatProcessor");
22 | field.setAccessible(true);
23 | originInputEventCompatProcessor = (InputEventCompatProcessor) field.get(viewRootImpl);
24 | field.set(viewRootImpl, this);
25 | } catch (Exception e) {
26 | throw new RuntimeException(e);
27 | }
28 | }
29 |
30 | @Override
31 | public InputEvent processInputEventBeforeFinish(InputEvent e) {
32 | return originInputEventCompatProcessor.processInputEventBeforeFinish(e);
33 | }
34 |
35 | @Override
36 | public List processInputEventForCompatibility(InputEvent e) {
37 | List list;
38 | if (listener.onBeforeInputEvent(e)) {
39 | list = new ArrayList<>();
40 | } else {
41 | list = originInputEventCompatProcessor.processInputEventForCompatibility(e);
42 | }
43 | listener.onAfterInputEvent(e);
44 | return list;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/input/InputEventListener.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.input;
2 |
3 | import android.view.InputEvent;
4 |
5 | public interface InputEventListener {
6 |
7 | boolean onBeforeInputEvent(InputEvent inputEvent);
8 |
9 | void onAfterInputEvent(InputEvent inputEvent);
10 | }
11 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/input/InputEventProcessorCompact.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.input;
2 |
3 | import android.content.Context;
4 | import android.os.Build;
5 | import android.os.Looper;
6 | import android.util.SparseIntArray;
7 | import android.view.InputChannel;
8 | import android.view.InputEventReceiver;
9 | import android.view.ViewRootImpl;
10 |
11 | import com.wanjian.sak.unsafe.UnsafeProxy;
12 |
13 | import java.lang.reflect.Field;
14 |
15 | public abstract class InputEventProcessorCompact {
16 | public static void get(Context context, ViewRootImpl viewRootImpl, InputEventListener listener) {
17 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
18 | new InputEventCompatProcessorV30(context, viewRootImpl, listener);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/input/InputEventReceiverCompact.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.input;
2 |
3 | import android.os.Build;
4 | import android.os.Looper;
5 | import android.util.SparseIntArray;
6 | import android.view.InputChannel;
7 | import android.view.InputEventReceiver;
8 | import android.view.View;
9 | import android.view.ViewRootImpl;
10 |
11 | import com.wanjian.sak.unsafe.UnsafeProxy;
12 |
13 | import java.lang.reflect.Field;
14 |
15 | public abstract class InputEventReceiverCompact {
16 |
17 | public static void get(ViewRootImpl viewRootImpl, InputEventListener listener) {
18 | InputChannel inputChannel = getInputChannel(viewRootImpl);
19 | Looper looper = Looper.getMainLooper();//todo
20 | InputEventReceiver originInputEventReceiver = getOriginInputEventReceiver(viewRootImpl);
21 | InputEventReceiver inputEventReceiver;
22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
23 | inputEventReceiver = new InputEventReceiverV29Impl(inputChannel, looper, viewRootImpl, listener, originInputEventReceiver);
24 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
25 | inputEventReceiver = new InputEventReceiverV27Impl(inputChannel, looper, viewRootImpl, listener, originInputEventReceiver);
26 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
27 | inputEventReceiver = new InputEventReceiverV21Impl(inputChannel, looper, viewRootImpl, listener, originInputEventReceiver);
28 | } else {
29 | throw new RuntimeException("unsuooprt");
30 | }
31 | replace(viewRootImpl, originInputEventReceiver, inputEventReceiver);
32 | }
33 |
34 | private static InputEventReceiver getOriginInputEventReceiver(ViewRootImpl viewRootImpl) {
35 | try {
36 | Field mInputEventReceiverF = ViewRootImpl.class.getDeclaredField("mInputEventReceiver");
37 | mInputEventReceiverF.setAccessible(true);
38 | return (InputEventReceiver) mInputEventReceiverF.get(viewRootImpl);
39 | } catch (Exception e) {
40 | throw new RuntimeException(e);
41 | }
42 | }
43 |
44 |
45 | private static InputChannel getInputChannel(ViewRootImpl viewRoot) {
46 | try {
47 | Field mInputChannelF = ViewRootImpl.class.getDeclaredField("mInputChannel");
48 | mInputChannelF.setAccessible(true);
49 | return (InputChannel) mInputChannelF.get(viewRoot);
50 | } catch (Exception e) {
51 | throw new RuntimeException(e);
52 | }
53 | }
54 |
55 | private static void replace(ViewRootImpl viewRootImpl, InputEventReceiver originInputEventReceiver, InputEventReceiver myInputEventReceiver) {
56 | try {
57 | Field mInputEventReceiverF = ViewRootImpl.class.getDeclaredField("mInputEventReceiver");
58 | Field mSeqMapField = InputEventReceiver.class.getDeclaredField("mSeqMap");
59 | mSeqMapField.setAccessible(true);
60 | SparseIntArray originmSeqMap = (SparseIntArray) mSeqMapField.get(originInputEventReceiver);
61 |
62 | ////
63 | mSeqMapField.set(myInputEventReceiver, originmSeqMap); // TODO: 2020/6/26 必须?
64 |
65 | long offset = UnsafeProxy.objectFieldOffset(mInputEventReceiverF);
66 | UnsafeProxy.putObject(viewRootImpl, offset, myInputEventReceiver);
67 | } catch (Exception e) {
68 | throw new RuntimeException();
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/input/InputEventReceiverHolder.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.input;
2 |
3 | public class InputEventReceiverHolder {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/rendernode/RenderNodeCompact.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.rendernode;
2 |
3 | import android.graphics.Canvas;
4 | import android.os.Build;
5 |
6 | public abstract class RenderNodeCompact {
7 | RenderNodeCompact() {
8 |
9 | }
10 |
11 | public static RenderNodeCompact create(String name) {
12 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
13 | return new RenderNodeV29Impl(name);
14 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
15 | return new RenderNodeV23Impl(name);
16 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
17 | return new RenderNodeV21Impl(name);
18 | } else {
19 | throw new RuntimeException("unsupport android version");
20 | }
21 | }
22 |
23 | public abstract void drawRenderNode(Canvas canvas);
24 |
25 | public abstract Canvas beginRecording(int width, int height);
26 |
27 | public abstract void endRecording(Canvas canvas);
28 |
29 | public abstract boolean isValid();
30 | }
31 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/rendernode/RenderNodeV21Impl.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.rendernode;
2 |
3 | import android.graphics.Canvas;
4 | import android.view.DisplayListCanvas;
5 | import android.view.HardwareCanvas;
6 | import android.view.RenderNode;
7 |
8 | import java.lang.reflect.Method;
9 |
10 | public class RenderNodeV21Impl extends RenderNodeCompact {
11 |
12 | private RenderNode renderNode;
13 |
14 | public RenderNodeV21Impl(String name) {
15 | renderNode = RenderNode.create(name, null);
16 | }
17 |
18 | @Override
19 | public void drawRenderNode(Canvas canvas) {
20 | ((HardwareCanvas) canvas).drawRenderNode(renderNode);
21 | }
22 |
23 | @Override
24 | public HardwareCanvas beginRecording(int width, int height) {
25 | renderNode.setLeftTopRightBottom(0, 0, width, height);
26 | try {
27 | Method method = RenderNode.class.getDeclaredMethod("start", int.class, int.class);
28 | method.setAccessible(true);
29 | return (HardwareCanvas) method.invoke(renderNode, width, height);
30 | } catch (Exception e) {
31 | throw new RuntimeException(e);
32 | }
33 | }
34 |
35 | @Override
36 | public void endRecording(Canvas canvas) {
37 | renderNode.end((HardwareCanvas) canvas);
38 | }
39 |
40 | @Override
41 | public boolean isValid() {
42 | return renderNode.isValid();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/rendernode/RenderNodeV23Impl.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.rendernode;
2 |
3 | import android.graphics.Canvas;
4 | import android.view.DisplayListCanvas;
5 | import android.view.HardwareCanvas;
6 | import android.view.RenderNode;
7 | import android.view.ThreadedRenderer;
8 |
9 | import java.lang.reflect.Method;
10 |
11 | public class RenderNodeV23Impl extends RenderNodeCompact {
12 |
13 | private RenderNode renderNode;
14 |
15 | public RenderNodeV23Impl(String name) {
16 | renderNode = RenderNode.create(name, null);
17 | }
18 |
19 | @Override
20 | public void drawRenderNode(Canvas canvas) {
21 | ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
22 | }
23 |
24 |
25 | @Override
26 | public DisplayListCanvas beginRecording(int width, int height) {
27 | renderNode.setLeftTopRightBottom(0, 0, width, height);
28 | return renderNode.start(width,height);
29 | }
30 |
31 | @Override
32 | public void endRecording(Canvas canvas) {
33 | renderNode.end((DisplayListCanvas) canvas);
34 | }
35 |
36 | @Override
37 | public boolean isValid() {
38 | return renderNode.isValid();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/rendernode/RenderNodeV29Impl.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.rendernode;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.RecordingCanvas;
5 | import android.graphics.RenderNode;
6 |
7 | import java.lang.reflect.Method;
8 |
9 | public class RenderNodeV29Impl extends RenderNodeCompact {
10 |
11 | private RenderNode renderNode;
12 |
13 | public RenderNodeV29Impl(String name) {
14 | renderNode = new RenderNode(name);
15 | }
16 |
17 | @Override
18 | public void drawRenderNode(Canvas canvas) {
19 | ((RecordingCanvas) canvas).drawRenderNode(renderNode);
20 | }
21 |
22 | @Override
23 | public RecordingCanvas beginRecording(int width, int height) {
24 | // renderNode.setLeftTopRightBottom(0, 0, width, height);
25 | try {
26 | Method method = RenderNode.class.getDeclaredMethod("setLeftTopRightBottom", int.class, int.class, int.class, int.class);
27 | method.setAccessible(true);
28 | method.invoke(renderNode, 0, 0, width, height);
29 | } catch (Exception e) {
30 | throw new RuntimeException(e);
31 | }
32 | return renderNode.beginRecording();
33 | }
34 |
35 | @Override
36 | public void endRecording(Canvas canvas) {
37 | renderNode.endRecording();
38 | }
39 |
40 | @Override
41 | public boolean isValid() {
42 | return renderNode.hasDisplayList();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/traversals/MyTraversalRunnable.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.traversals;
2 |
3 | import android.util.Log;
4 | import android.view.View;
5 | import android.view.ViewRootImpl;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | public class MyTraversalRunnable implements Runnable {
11 | private ViewRootImpl $$viewRootImpl;
12 | private Runnable originTraversals;
13 | private View rootView;
14 | private List listeners = new ArrayList<>();
15 |
16 | public MyTraversalRunnable(Runnable originTraversals, View rootView) {
17 | $$viewRootImpl = (ViewRootImpl) rootView.getRootView().getParent();
18 | this.originTraversals = originTraversals;
19 | this.rootView = rootView;
20 | }
21 |
22 | @Override
23 | public void run() {
24 | Log.d("TAG", "run: "+$$viewRootImpl);
25 | notifyBeforeRun();
26 | originTraversals.run();
27 | notifyAfterRun();
28 | }
29 |
30 | private void notifyBeforeRun() {
31 | for (ViewTraversalsListener listener : listeners) {
32 | listener.onBeforeTraversal(rootView);
33 | }
34 | }
35 |
36 | private void notifyAfterRun() {
37 | for (ViewTraversalsListener listener : listeners) {
38 | listener.onAfterTraversal(rootView);
39 | }
40 | }
41 |
42 |
43 | public void addTraversalsListener(ViewTraversalsListener listener) {
44 | listeners.add(listener);
45 | }
46 |
47 | public void removeTraversalsListener(ViewTraversalsListener listener) {
48 | listeners.remove(listener);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/traversals/ViewTraversalsCompact.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.traversals;
2 |
3 | import android.view.View;
4 | import android.view.ViewRootImpl;
5 |
6 | import com.wanjian.sak.unsafe.UnsafeProxy;
7 |
8 | import java.lang.reflect.Field;
9 |
10 | public class ViewTraversalsCompact {
11 | static Field sTraversalRunnableF;
12 |
13 | static {
14 | try {
15 | sTraversalRunnableF = ViewRootImpl.class.getDeclaredField("mTraversalRunnable");
16 | sTraversalRunnableF.setAccessible(true);
17 | } catch (Exception e) {
18 | throw new RuntimeException(e);
19 | }
20 | }
21 |
22 | public void register(ViewRootImpl viewRootImpl, View view, ViewTraversalsListener listener) {
23 |
24 | Runnable originTraversal = null;
25 | try {
26 | originTraversal = (Runnable) sTraversalRunnableF.get(viewRootImpl);
27 | } catch (IllegalAccessException e) {
28 | throw new RuntimeException(e);
29 | }
30 |
31 | if (originTraversal instanceof MyTraversalRunnable) {
32 | ((MyTraversalRunnable) originTraversal).addTraversalsListener(listener);
33 | return;
34 | }
35 |
36 | MyTraversalRunnable myTraversal = new MyTraversalRunnable(originTraversal, view);
37 |
38 | myTraversal.addTraversalsListener(listener);
39 |
40 | long offset = UnsafeProxy.objectFieldOffset(sTraversalRunnableF);
41 |
42 | UnsafeProxy.putObject(viewRootImpl, offset, myTraversal);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/traversals/ViewTraversalsListener.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.traversals;
2 |
3 | import android.view.View;
4 |
5 | public interface ViewTraversalsListener {
6 |
7 | void onBeforeTraversal(View rootView);
8 |
9 | void onAfterTraversal(View rootView);
10 | }
11 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/window/compact/IWindowChangeListener.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.window.compact;
2 |
3 | import android.view.View;
4 | import android.view.ViewRootImpl;
5 |
6 | public interface IWindowChangeListener {
7 | void onAddWindow(ViewRootImpl viewRootImpl, View rootView);
8 |
9 | void onRemoveWindow(ViewRootImpl viewRootImpl, View rootView);
10 | }
11 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/window/compact/WindowRootViewCompactV18Impl.java:
--------------------------------------------------------------------------------
1 | //package com.wanjian.sak.system.window.compact;
2 | //
3 | //
4 | //import android.support.annotation.NonNull;
5 | //import android.view.View;
6 | //import android.view.ViewRootImpl;
7 | //
8 | //import java.lang.reflect.Field;
9 | //import java.lang.reflect.InvocationTargetException;
10 | //import java.lang.reflect.Method;
11 | //import java.util.ArrayList;
12 | //import java.util.List;
13 | //
14 | //class WindowRootViewCompactV18Impl extends WindowRootViewCompactV16Impl {
15 | //
16 | // private Field mViewsField;
17 | // private Object mWindowManagerGlobal;
18 | // private List changeListeners = new ArrayList<>();
19 | // private ViewRootImpl[] lastViews;
20 | //
21 | // WindowRootViewCompactV18Impl() {
22 | // super(null);
23 | // }
24 | //
25 | // @Override
26 | // void init() {
27 | // try {
28 | // Class wmClz = Class.forName("android.view.WindowManagerGlobal");
29 | // Method getInstanceMethod = wmClz.getDeclaredMethod("getInstance");
30 | // mWindowManagerGlobal = getInstanceMethod.invoke(wmClz);
31 | // mViewsField = wmClz.getDeclaredField("mRoots");
32 | // mViewsField.setAccessible(true);
33 | // lastViews = (ViewRootImpl[]) mViewsField.get(mWindowManagerGlobal);
34 | // } catch (ClassNotFoundException e) {
35 | // throw new RuntimeException(e);
36 | // } catch (NoSuchMethodException e) {
37 | // throw new RuntimeException(e);
38 | // } catch (IllegalAccessException e) {
39 | // throw new RuntimeException(e);
40 | // } catch (InvocationTargetException e) {
41 | // throw new RuntimeException(e);
42 | // } catch (NoSuchFieldException e) {
43 | // throw new RuntimeException(e);
44 | // }
45 | // }
46 | //
47 | // @Override
48 | // void check() {
49 | // if (changeListeners == null || changeListeners.isEmpty()) {
50 | // return;
51 | // }
52 | // try {
53 | // ViewRootImpl[] curViews = (ViewRootImpl[]) mViewsField.get(mWindowManagerGlobal);
54 | // if (curViews != lastViews) {
55 | // notifyWindowChange(lastViews, curViews, changeListeners);
56 | // lastViews = curViews;
57 | // }
58 | // } catch (IllegalAccessException e) {
59 | // throw new RuntimeException(e);
60 | // }
61 | // }
62 | //
63 | // @Override
64 | // void onAddWindowChangeListener(@NonNull IWindowChangeListener changeListener) {
65 | // changeListeners.add(changeListener);
66 | // if (lastViews == null) {
67 | // return;
68 | // }
69 | // for (ViewRootImpl view : lastViews) {
70 | // changeListener.onAddWindow(view);
71 | // }
72 | // }
73 | //
74 | // @Override
75 | // void onRemoveWindowChangeListener(@NonNull IWindowChangeListener changeListener) {
76 | // changeListeners.remove(changeListener);
77 | // }
78 | //
79 | //}
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/window/compact/WindowRootViewCompactV19Impl.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.window.compact;
2 |
3 | import android.view.View;
4 | import android.view.ViewRootImpl;
5 |
6 | import com.wanjian.sak.proxy.ProxyArrayList;
7 |
8 | import java.lang.reflect.Array;
9 | import java.lang.reflect.Field;
10 | import java.lang.reflect.InvocationTargetException;
11 | import java.lang.reflect.Method;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | class WindowRootViewCompactV19Impl extends WindowRootViewCompat {
16 |
17 | private List changeListeners = new ArrayList<>();
18 | private List viewRoots;
19 | private List rootViews;
20 |
21 | WindowRootViewCompactV19Impl() {
22 | try {
23 | Class wmClz = Class.forName("android.view.WindowManagerGlobal");
24 | Method getInstanceMethod = wmClz.getDeclaredMethod("getInstance");
25 | Object managerGlobal = getInstanceMethod.invoke(wmClz);
26 |
27 | Field mViewsField = wmClz.getDeclaredField("mViews");
28 | mViewsField.setAccessible(true);
29 | rootViews = (List) mViewsField.get(managerGlobal);
30 | mViewsField.set(managerGlobal, rootViews);
31 | mViewsField.setAccessible(false);
32 |
33 | Field mRootsField = wmClz.getDeclaredField("mRoots");
34 | mRootsField.setAccessible(true);
35 | viewRoots = getProxy((ArrayList) mRootsField.get(managerGlobal));
36 | mRootsField.set(managerGlobal, viewRoots);
37 | mRootsField.setAccessible(false);
38 |
39 | } catch (ClassNotFoundException e) {
40 | throw new RuntimeException(e);
41 | } catch (NoSuchMethodException e) {
42 | throw new RuntimeException(e);
43 | } catch (IllegalAccessException e) {
44 | throw new RuntimeException(e);
45 | } catch (InvocationTargetException e) {
46 | throw new RuntimeException(e);
47 | } catch (NoSuchFieldException e) {
48 | throw new RuntimeException(e);
49 | }
50 | }
51 |
52 | private ArrayList getProxy(final ArrayList list) {
53 | return new ProxyArrayList(list) {
54 | @Override
55 | public boolean add(ViewRootImpl object) {
56 | boolean b = super.add(object);
57 | int index=indexOf(object);
58 | View view=rootViews.get(index);
59 | for (IWindowChangeListener listener : changeListeners) {
60 | listener.onAddWindow(object,view);
61 | }
62 | return b;
63 | }
64 |
65 | @Override
66 | public ViewRootImpl remove(int index) {
67 | ViewRootImpl viewRoot = super.remove(index);
68 | View view=rootViews.get(index);
69 | for (IWindowChangeListener listener : changeListeners) {
70 | listener.onRemoveWindow(viewRoot,view);
71 | }
72 | return viewRoot;
73 | }
74 |
75 | @Override
76 | public boolean remove(Object object) {
77 | int index = indexOf(object);
78 | View view = rootViews.get(index);
79 | boolean b = super.remove(object);
80 | for (IWindowChangeListener listener : changeListeners) {
81 | listener.onRemoveWindow(((ViewRootImpl) object), view);
82 | }
83 | return b;
84 | }
85 | };
86 | }
87 |
88 | @Override
89 | void onAddWindowChangeListener(IWindowChangeListener changeListener) {
90 | changeListeners.add(changeListener);
91 | for (int i = 0; i < viewRoots.size(); i++) {
92 | ViewRootImpl viewRoot=viewRoots.get(i);
93 | View view=rootViews.get(i);
94 | changeListener.onAddWindow(viewRoot,view);
95 | }
96 |
97 | }
98 | @Override
99 | void onRemoveWindowChangeListener(IWindowChangeListener changeListener) {
100 | changeListeners.remove(changeListener);
101 | }
102 | }
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/system/window/compact/WindowRootViewCompat.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.system.window.compact;
2 |
3 | import android.content.Context;
4 | import android.os.Build;
5 |
6 | /*
7 | * get the root view of all windows
8 | *
9 | * when you add view by windowManager.addView(), the root view may not be a DecorView
10 | *
11 | *
12 | * There are some differences when you want to get the root view
13 | *
14 | * 4.0.3_r1 WindowManagerImpl private View[] mViews;
15 | *
16 | * 4.0.4 WindowManagerImpl private View[] mViews;
17 | *
18 | * 4.1.1 WindowManagerImpl private View[] mViews;
19 | *
20 | * 4.1.2 WindowManagerImpl private View[] mViews;
21 | *
22 | * 4.2_r1 WindowManagerGlobal private View[] mViews
23 | *
24 | * 4.2.2 r1 WindowManagerGlobal private View[] mViews
25 | *
26 | * 4.3_r2.1 WindowManagerGlobal private View[] mViews;
27 | *
28 | * 4.4_r1 WindowManagerGlobal private final ArrayList<View> mViews
29 | *
30 | * 4.4.2_r1 WindowManagerGlobal private final ArrayList<View> mViews
31 | *
32 | * 5.0.0_r2 WindowManagerGlobal private final ArrayList<View> mViews
33 | *
34 | * 6.0.0_r1 WindowManagerGlobal private final ArrayList<View> mViews
35 | *
36 | * 7.0.0_r1 WindowManagerGlobal private final ArrayList<View> mViews
37 | *
38 | * 8.0.0_r4 WindowManagerGlobal private final ArrayList<View> mViews
39 | */
40 | public abstract class WindowRootViewCompat {
41 |
42 | public static WindowRootViewCompat get(Context context) {
43 | WindowRootViewCompat windowRootViewCompat;
44 |
45 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
46 | windowRootViewCompat = new WindowRootViewCompactV19Impl();
47 | } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1
48 | || Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2) {
49 | throw new RuntimeException("unsupport");
50 | // windowRootViewCompat = new WindowRootViewCompactV18Impl();
51 | } else {
52 | throw new RuntimeException("unsupport");
53 | // windowRootViewCompat = new WindowRootViewCompactV16Impl(context.getApplicationContext());
54 | }
55 | return windowRootViewCompat;
56 | }
57 |
58 | public final void addWindowChangeListener(IWindowChangeListener changeListener) {
59 | if (changeListener == null) {
60 | return;
61 | }
62 | onAddWindowChangeListener(changeListener);
63 | }
64 |
65 | public final void removeWindowChangeListener(IWindowChangeListener changeListener) {
66 | if (changeListener == null) {
67 | return;
68 | }
69 | onRemoveWindowChangeListener(changeListener);
70 | }
71 |
72 | abstract void onAddWindowChangeListener(IWindowChangeListener changeListener);
73 |
74 | abstract void onRemoveWindowChangeListener(IWindowChangeListener changeListener);
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/unsafe/ReflectUtils.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.unsafe;
2 |
3 | import java.lang.reflect.Method;
4 |
5 | public class ReflectUtils {
6 |
7 | private static ReflectUtils sInstance;
8 |
9 | private ReflectUtils() {
10 | }
11 |
12 | public static ReflectUtils getInstance() {
13 | if (sInstance == null) {
14 | sInstance = new ReflectUtils();
15 | }
16 | return sInstance;
17 | }
18 |
19 | public Method getMethod(Class> clazz, String methodName, Class>... values) {
20 | Method method = null;
21 | try {
22 | if (values != null) {
23 | method = clazz.getDeclaredMethod(methodName, values);
24 | } else {
25 | method = clazz.getDeclaredMethod(methodName);
26 | }
27 | } catch (NoSuchMethodException e) {
28 | e.printStackTrace();
29 | }
30 | return method;
31 | }
32 |
33 | public Object invokeStaticMethod(Method method, Object... values) {
34 | return invokeMethod(method, null, values);
35 | }
36 |
37 | public Object invokeMethod(Method method, Object classValue, Object... values) {
38 | if (method != null) {
39 | try {
40 | return method.invoke(classValue, values);
41 | } catch (Exception e) {
42 | throw new RuntimeException(e);
43 | }
44 | }
45 | return null;
46 | }
47 |
48 | /**
49 | * 这里我们通过反射静态方法 getUnsafe()方法来获取Unsafe对象,其实在之前的代码
50 | * 的时候我们也可以直接反射静态的成员变量来直接获取Unsafe对象的,其实都是差不多的。
51 | */
52 | public Object getUnsafe(Class> clazz) {
53 | Method method = getMethod(clazz, "getUnsafe");
54 | return invokeStaticMethod(method);
55 | }
56 | }
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/unsafe/UnsafeProxy.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.unsafe;
2 |
3 | import java.lang.reflect.Field;
4 | import java.lang.reflect.Method;
5 |
6 | public class UnsafeProxy {
7 |
8 | private static ReflectUtils sUtils;
9 | private static Class sUnsafeClass;
10 | private static Object sUnsafe;
11 |
12 | static {
13 |
14 | try {
15 | sUtils = ReflectUtils.getInstance();
16 | sUnsafeClass = Class.forName("sun.misc.Unsafe");
17 | sUnsafe = sUtils.getUnsafe(sUnsafeClass);
18 | } catch (ClassNotFoundException e) {
19 | e.printStackTrace();
20 | }
21 | }
22 |
23 |
24 | public static long objectFieldOffset(Field field) {
25 | Method method = sUtils.getMethod(sUnsafeClass, "objectFieldOffset", Field.class);
26 | Object obj = sUtils.invokeMethod(method, sUnsafe, field);
27 | return obj == null ? 0 : (Long) obj;
28 | }
29 |
30 |
31 | public static long putObject(Object object, long offset, Object newValue) {
32 | Method method = sUtils.getMethod(sUnsafeClass, "putObject", Object.class, long.class, Object.class);
33 | Object obj = sUtils.invokeMethod(method, sUnsafe, object, offset, newValue);
34 | return obj == null ? 0 : (Long) obj;
35 | }
36 | }
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/utils/BitmapCreater.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.utils;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | /**
6 | * Created by wanjian on 2017/4/1.
7 | */
8 |
9 | public class BitmapCreater {
10 | public static Bitmap create(int w, int h, Bitmap.Config config) {
11 |
12 | Check.isNull(config, "config");
13 | if (w <= 0) {
14 | new IllegalArgumentException("w can not be <= 0").printStackTrace();
15 | return null;
16 | }
17 | if (h <= 0) {
18 | new IllegalArgumentException("h can not be <= 0").printStackTrace();
19 | return null;
20 | }
21 | for (int i = 0; i < 3; i++) {
22 | try {
23 | return Bitmap.createBitmap(w, h, config);
24 | } catch (Throwable e) {
25 | Runtime.getRuntime().gc();
26 | }
27 | }
28 | return null;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/utils/Check.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.utils;
2 |
3 | /**
4 | * Created by wanjian on 2017/2/20.
5 | */
6 |
7 | public class Check {
8 |
9 | public static void isNull(Object obj, String what) {
10 | if (obj == null) {
11 | throw new NullPointerException(what + " cannot be null !");
12 | }
13 | }
14 |
15 | public static void throwException(String msg) {
16 | throw new RuntimeException(msg);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/utils/LoopQueue.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.utils;
2 |
3 | import java.util.LinkedList;
4 |
5 | public class LoopQueue {
6 | private int size;
7 | private LinkedList queue;
8 | private int cursor;
9 |
10 | public LoopQueue(int size) {
11 | if (size < 1) {
12 | throw new IllegalArgumentException();
13 | }
14 | this.size = size;
15 | queue = new LinkedList();
16 | }
17 |
18 | public T take() {
19 | if (has() == false) {
20 | throw new IllegalStateException("end!");
21 | }
22 | return queue.get(cursor++);
23 | }
24 |
25 | public void append(T t) {
26 | if (queue.size() == size) {
27 | queue.remove(0);
28 | cursor--;
29 | if (cursor < 0) {
30 | cursor = 0;
31 | }
32 | }
33 | queue.add(t);
34 | }
35 |
36 | public boolean has() {
37 | return cursor != queue.size();
38 | }
39 |
40 | public int maxSize() {
41 | return size;
42 | }
43 |
44 | public int size() {
45 | return queue.size();
46 | }
47 |
48 | public void reset() {
49 | cursor = 0;
50 | }
51 |
52 | public void clean() {
53 | cursor = 0;
54 | queue.clear();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/utils/RunningActivityFetcher.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.utils;
2 |
3 | import android.app.Activity;
4 |
5 | import java.lang.ref.WeakReference;
6 | import java.lang.reflect.Field;
7 | import java.lang.reflect.Method;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | public class RunningActivityFetcher {
13 |
14 | private static Map mActivities; //ActivityThread.mActivities
15 | private static Field activityField;//ActivityClientRecord.activity
16 |
17 | public static List> fetch() {
18 |
19 | if (mActivities == null) {
20 | getmActivities();
21 | }
22 | List> references = new ArrayList<>();
23 |
24 | for (Object actRecord : mActivities.values()) {
25 | if (activityField == null) {
26 | getActivityField(actRecord);
27 | }
28 | if (activityField == null) {
29 | return null;
30 | }
31 |
32 | try {
33 | Activity activity = (Activity) activityField.get(actRecord);
34 | references.add(new WeakReference<>(activity));
35 | } catch (Throwable throwable) {
36 | throwable.printStackTrace();
37 | return null;
38 | }
39 | }
40 | return references;
41 | }
42 |
43 | private static void getActivityField(Object actRecord) {
44 | try {
45 | activityField = actRecord.getClass().getDeclaredField("activity");
46 | activityField.setAccessible(true);
47 | } catch (Throwable throwable) {
48 | throwable.printStackTrace();
49 | }
50 | }
51 |
52 | private static void getmActivities() {
53 | try {
54 | Class activityThreadClz = Class.forName("android.app.ActivityThread");
55 | Method currentActivityThreadMethod = activityThreadClz.getDeclaredMethod("currentActivityThread");
56 | currentActivityThreadMethod.setAccessible(true);
57 | Object activityThread = currentActivityThreadMethod.invoke(null);
58 | Field mActivitiesField = activityThreadClz.getDeclaredField("mActivities");
59 | mActivitiesField.setAccessible(true);
60 | //
61 | mActivities = (Map) mActivitiesField.get(activityThread);
62 | } catch (Throwable throwable) {
63 | throwable.printStackTrace();
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/utils/ScreenUtils.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.utils;
2 |
3 | import android.content.Context;
4 |
5 | public class ScreenUtils {
6 |
7 | public static int dp2px(Context context, int dip) {
8 | float density = context.getResources().getDisplayMetrics().density;
9 | return (int) (dip * density + 0.5);
10 | }
11 |
12 | public static int px2dp(Context context, float pxValue) {
13 | final float scale = context.getResources().getDisplayMetrics().density;
14 | return (int) (pxValue / scale + 0.5f);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/saklib/src/main/java/com/wanjian/sak/utils/SpanStrBuilder.java:
--------------------------------------------------------------------------------
1 | package com.wanjian.sak.utils;
2 |
3 | import android.text.SpannableString;
4 | import android.text.Spanned;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 |
10 | public class SpanStrBuilder {
11 |
12 | private List