├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── assets
│ │ │ └── xposed_init
│ │ ├── res
│ │ │ ├── drawable-hdpi
│ │ │ │ ├── check_off.png
│ │ │ │ └── check_on.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── drawable-xhdpi
│ │ │ │ └── colorpicker.9.png
│ │ │ ├── values
│ │ │ │ ├── styles.xml
│ │ │ │ ├── arrays.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── strings.xml
│ │ │ ├── drawable
│ │ │ │ ├── checks.xml
│ │ │ │ ├── background_card_dark.xml
│ │ │ │ ├── background_card_normal_dark.xml
│ │ │ │ └── background_card_pressed_dark.xml
│ │ │ ├── xml
│ │ │ │ └── module_prefs.xml
│ │ │ └── layout
│ │ │ │ └── colorpicker.xml
│ │ ├── java
│ │ │ └── in
│ │ │ │ └── proficientapps
│ │ │ │ └── MaterializeXposedInstaller
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── preferences
│ │ │ │ ├── AlphaPatternDrawable.java
│ │ │ │ ├── ColorPickerPanelView.java
│ │ │ │ ├── ColorPickerDialog.java
│ │ │ │ ├── ColorPickerPreference.java
│ │ │ │ └── ColorPickerView.java
│ │ │ │ └── Module.java
│ │ └── AndroidManifest.xml
│ └── test
│ │ └── java
│ │ └── in
│ │ └── proficientapps
│ │ └── MaterializeXposedInstaller
│ │ └── ExampleUnitTest.java
├── app-release.apk
├── XposedBridgeApi-LP.jar
├── MaterializeXposedInstaller.apk
├── MaterializeXposedInstaller_1.1.apk
├── build.gradle
├── proguard-rules.pro
└── app.iml
├── settings.gradle
├── .idea
├── .name
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── vcs.xml
├── libraries
│ └── XposedBridgeApi_LP.xml
├── inspectionProfiles
│ ├── profiles_settings.xml
│ └── Project_Default.xml
├── modules.xml
├── runConfigurations.xml
├── gradle.xml
├── compiler.xml
└── misc.xml
├── .gitignore
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitattributes
├── gradle.properties
├── MaterializeXposedInstaller.iml
├── README.md
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | Materialize Xposed Installer
--------------------------------------------------------------------------------
/app/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | in.proficientapps.MaterializeXposedInstaller.Module
--------------------------------------------------------------------------------
/app/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Proficient-Apps/MaterializeXposedInstaller/HEAD/app/app-release.apk
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/app/XposedBridgeApi-LP.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Proficient-Apps/MaterializeXposedInstaller/HEAD/app/XposedBridgeApi-LP.jar
--------------------------------------------------------------------------------
/app/MaterializeXposedInstaller.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Proficient-Apps/MaterializeXposedInstaller/HEAD/app/MaterializeXposedInstaller.apk
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Proficient-Apps/MaterializeXposedInstaller/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/MaterializeXposedInstaller_1.1.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Proficient-Apps/MaterializeXposedInstaller/HEAD/app/MaterializeXposedInstaller_1.1.apk
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/check_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Proficient-Apps/MaterializeXposedInstaller/HEAD/app/src/main/res/drawable-hdpi/check_off.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/check_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Proficient-Apps/MaterializeXposedInstaller/HEAD/app/src/main/res/drawable-hdpi/check_on.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Proficient-Apps/MaterializeXposedInstaller/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/colorpicker.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Proficient-Apps/MaterializeXposedInstaller/HEAD/app/src/main/res/drawable-xhdpi/colorpicker.9.png
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/libraries/XposedBridgeApi_LP.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Sep 06 14:27:50 IST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
7 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/checks.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background_card_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/app/src/test/java/in/proficientapps/MaterializeXposedInstaller/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package in.proficientapps.MaterializeXposedInstaller;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Stock
5 | - "Material UI Light + Dark Action Bar[Recommended]"
6 | - "Material UI Light"
7 | - "Material UI Dark"
8 |
9 |
10 |
11 | - 0
12 | - 1
13 | - 2
14 | - 3
15 |
16 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #363636
5 | #505050
6 | #161616
7 |
8 | #FF0094FF
9 | #FFFF006E
10 | #FFFF0000
11 | #FFFF6A00
12 | #FFFFD800
13 | #FFB200FF
14 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.0"
6 |
7 | defaultConfig {
8 | applicationId "in.proficientapps.MaterializeXposedInstaller"
9 | minSdkVersion 21
10 | targetSdkVersion 23
11 | versionCode 2
12 | versionName "1.1"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | provided files('XposedBridgeApi-LP.jar')
25 | }
26 |
--------------------------------------------------------------------------------
/app/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 C:\Users\Arnab\AppData\Local\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 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Materialize Xposed Installer
4 |
5 |
6 | Activate Module
7 | Choose Desired Theme
8 | Theme Options
9 | Primary Colour
10 | Accent Colour
11 | Background Colour
12 |
13 |
14 | Color Picker
15 | Click to apply
16 | HEX
17 | →
18 |
19 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background_card_normal_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | -
17 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background_card_pressed_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | -
17 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/MaterializeXposedInstaller.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/java/in/proficientapps/MaterializeXposedInstaller/MainActivity.java:
--------------------------------------------------------------------------------
1 | package in.proficientapps.MaterializeXposedInstaller;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.preference.PreferenceFragment;
6 |
7 | /*
8 | * Created by SArnab©® on 06-09-2015.
9 | */
10 | public class MainActivity extends Activity {
11 |
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState) {
14 | super.onCreate(savedInstanceState);
15 | // Display the fragment as the main content.
16 | getFragmentManager().beginTransaction()
17 | .replace(android.R.id.content, new PrefsFragment())
18 | .commit();
19 | }
20 |
21 | public static class PrefsFragment extends PreferenceFragment {
22 |
23 | @Override
24 | public void onCreate(Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 | getPreferenceManager().setSharedPreferencesMode(MODE_WORLD_READABLE);
27 | addPreferencesFromResource(R.xml.module_prefs);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
15 |
18 |
21 |
22 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MaterializeXposedInstaller
2 | Xposed Module to convert Xposed Installer App UI to Material UI
3 |
4 | Developer Note : I made this Module in 10 Minutes so that I can enjoy Material UI inside the Xposed Installer App.
5 | For now it's very basic and provides 3 different themes to choose from.
6 | Feel free to fork and upgrade it if you have anything new in mind.
7 | But, please do not release a new separate version.
8 | Instead, update me regarding your changes and I will try my best to add those in my source and release an update.
9 | You may compile a different version for your personal use.
10 |
11 | Screenshots :
12 |
13 |  
14 |
15 |  
16 |
17 |  
18 |
19 |  
20 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/module_prefs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
16 |
17 |
23 |
29 |
35 |
36 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/java/in/proficientapps/MaterializeXposedInstaller/preferences/AlphaPatternDrawable.java:
--------------------------------------------------------------------------------
1 | package in.proficientapps.MaterializeXposedInstaller.preferences;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Bitmap.Config;
5 | import android.graphics.Canvas;
6 | import android.graphics.ColorFilter;
7 | import android.graphics.Paint;
8 | import android.graphics.Rect;
9 | import android.graphics.drawable.Drawable;
10 |
11 | public class AlphaPatternDrawable extends Drawable {
12 |
13 | private int mRectangleSize = 10;
14 | private Paint mPaint = new Paint();
15 | private Paint mPaintWhite = new Paint();
16 | private Paint mPaintGray = new Paint();
17 | private int numRectanglesHorizontal;
18 | private int numRectanglesVertical;
19 | private Bitmap mBitmap;
20 | public AlphaPatternDrawable(int rectangleSize) {
21 | mRectangleSize = rectangleSize;
22 | mPaintWhite.setColor(0xffffffff);
23 | mPaintGray.setColor(0xffcbcbcb);
24 | }
25 | @Override
26 | public void draw(Canvas canvas) { canvas.drawBitmap(mBitmap, null, getBounds(), mPaint); }
27 | @Override
28 | public int getOpacity() { return 0; }
29 | @Override
30 | public void setAlpha(int alpha) { throw new UnsupportedOperationException("Alpha is not supported by this drawable."); }
31 | @Override
32 | public void setColorFilter(ColorFilter cf) { throw new UnsupportedOperationException("ColorFilter is not supported by this drawable."); }
33 | @Override
34 | protected void onBoundsChange(Rect bounds) {
35 | super.onBoundsChange(bounds);
36 | int height = bounds.height();
37 | int width = bounds.width();
38 | numRectanglesHorizontal = (int) Math.ceil((width / mRectangleSize));
39 | numRectanglesVertical = (int) Math.ceil(height / mRectangleSize);
40 | generatePatternBitmap();
41 | }
42 | private void generatePatternBitmap(){
43 | if(getBounds().width() <= 0 || getBounds().height() <= 0){ return; }
44 | mBitmap = Bitmap.createBitmap(getBounds().width(), getBounds().height(), Config.ARGB_8888);
45 | Canvas canvas = new Canvas(mBitmap);
46 | Rect r = new Rect();
47 | boolean verticalStartWhite = true;
48 | for (int i = 0; i <= numRectanglesVertical; i++) {
49 | boolean isWhite = verticalStartWhite;
50 | for (int j = 0; j <= numRectanglesHorizontal; j++) {
51 | r.top = i * mRectangleSize;
52 | r.left = j * mRectangleSize;
53 | r.bottom = r.top + mRectangleSize;
54 | r.right = r.left + mRectangleSize;
55 | canvas.drawRect(r, isWhite ? mPaintWhite : mPaintGray);
56 | isWhite = !isWhite;
57 | }
58 | verticalStartWhite = !verticalStartWhite;
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/colorpicker.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
14 |
21 |
27 |
35 |
36 |
37 |
42 |
47 |
55 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/java/in/proficientapps/MaterializeXposedInstaller/preferences/ColorPickerPanelView.java:
--------------------------------------------------------------------------------
1 | package in.proficientapps.MaterializeXposedInstaller.preferences;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.RectF;
7 | import android.util.AttributeSet;
8 | import android.view.View;
9 |
10 | public class ColorPickerPanelView extends View {
11 |
12 | private final static float BORDER_WIDTH_PX = 1;
13 | private float mDensity = 1f;
14 | private int mBorderColor = 0xff6E6E6E;
15 | private int mColor = 0xff000000;
16 | private Paint mBorderPaint;
17 | private Paint mColorPaint;
18 | private RectF mDrawingRect;
19 | private RectF mColorRect;
20 | private AlphaPatternDrawable mAlphaPattern;
21 | public ColorPickerPanelView(Context context){ this(context, null); }
22 | public ColorPickerPanelView(Context context, AttributeSet attrs){ this(context, attrs, 0); }
23 | public ColorPickerPanelView(Context context, AttributeSet attrs, int defStyle) {
24 | super(context, attrs, defStyle);
25 | init();
26 | }
27 | private void init(){
28 | mBorderPaint = new Paint();
29 | mColorPaint = new Paint();
30 | mDensity = getContext().getResources().getDisplayMetrics().density;
31 | }
32 | @Override
33 | protected void onDraw(Canvas canvas) {
34 | final RectF rect = mColorRect;
35 | if(BORDER_WIDTH_PX > 0){
36 | mBorderPaint.setColor(mBorderColor);
37 | canvas.drawRect(mDrawingRect, mBorderPaint);
38 | }
39 | if(mAlphaPattern != null){ mAlphaPattern.draw(canvas); }
40 | mColorPaint.setColor(mColor);
41 | canvas.drawRect(rect, mColorPaint);
42 | }
43 | @Override
44 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
45 | int width = MeasureSpec.getSize(widthMeasureSpec);
46 | int height = MeasureSpec.getSize(heightMeasureSpec);
47 | setMeasuredDimension(width, height);
48 | }
49 | @Override
50 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
51 | super.onSizeChanged(w, h, oldw, oldh);
52 | mDrawingRect = new RectF();
53 | mDrawingRect.left = getPaddingLeft();
54 | mDrawingRect.right = w - getPaddingRight();
55 | mDrawingRect.top = getPaddingTop();
56 | mDrawingRect.bottom = h - getPaddingBottom();
57 | setUpColorRect();
58 | }
59 | private void setUpColorRect(){
60 | final RectF dRect = mDrawingRect;
61 | float left = dRect.left + BORDER_WIDTH_PX;
62 | float top = dRect.top + BORDER_WIDTH_PX;
63 | float bottom = dRect.bottom - BORDER_WIDTH_PX;
64 | float right = dRect.right - BORDER_WIDTH_PX;
65 | mColorRect = new RectF(left,top, right, bottom);
66 | mAlphaPattern = new AlphaPatternDrawable((int)(5 * mDensity));
67 | mAlphaPattern.setBounds(
68 | Math.round(mColorRect.left),
69 | Math.round(mColorRect.top),
70 | Math.round(mColorRect.right),
71 | Math.round(mColorRect.bottom)
72 | );
73 | }
74 | public void setColor(int color){
75 | mColor = color;
76 | invalidate();
77 | }
78 | public int getColor(){ return mColor; }
79 | public void setBorderColor(int color){
80 | mBorderColor = color;
81 | invalidate();
82 | }
83 | public int getBorderColor(){ return mBorderColor; }
84 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/app/src/main/java/in/proficientapps/MaterializeXposedInstaller/preferences/ColorPickerDialog.java:
--------------------------------------------------------------------------------
1 | package in.proficientapps.MaterializeXposedInstaller.preferences;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.content.res.ColorStateList;
6 | import android.graphics.Color;
7 | import android.graphics.PixelFormat;
8 | import android.os.Bundle;
9 | import android.text.Editable;
10 | import android.text.InputFilter;
11 | import android.text.TextWatcher;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.widget.EditText;
15 | import android.widget.LinearLayout;
16 |
17 | import in.proficientapps.MaterializeXposedInstaller.R;
18 |
19 | public class ColorPickerDialog extends Dialog implements ColorPickerView.OnColorChangedListener, View.OnClickListener {
20 |
21 | private ColorPickerView mColorPicker;
22 | private ColorPickerPanelView mOldColor;
23 | private ColorPickerPanelView mNewColor;
24 | private EditText mHexVal;
25 | private boolean mHexInternalTextChange;
26 | private boolean mHexValueEnabled = false;
27 | private ColorStateList mHexDefaultTextColor;
28 | private OnColorChangedListener mListener;
29 | public interface OnColorChangedListener { public void onColorChanged(int color); }
30 | public ColorPickerDialog(Context context, int initialColor) {
31 | super(context);
32 | init(initialColor);
33 | }
34 | private void init(int color) {
35 | getWindow().setFormat(PixelFormat.RGBA_8888);
36 | setUp(color);
37 | }
38 | private void setUp(int color) {
39 | LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
40 | View layout = inflater.inflate(R.layout.colorpicker, null);
41 | setContentView(layout);
42 | setTitle(R.string.dialog_color_picker);
43 | mColorPicker = (ColorPickerView) layout.findViewById(R.id.color_picker_view);
44 | mOldColor = (ColorPickerPanelView) layout.findViewById(R.id.old_color_panel);
45 | mNewColor = (ColorPickerPanelView) layout.findViewById(R.id.new_color_panel);
46 | mHexVal = (EditText) layout.findViewById(R.id.hex_val);
47 | mHexDefaultTextColor = mHexVal.getTextColors();
48 | mHexVal.addTextChangedListener(new TextWatcher() {
49 | @Override
50 | public void onTextChanged(CharSequence s, int start, int before, int count) {}
51 | @Override
52 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
53 | @Override
54 | public void afterTextChanged(Editable s) {
55 | if (mHexValueEnabled) {
56 | if (mHexInternalTextChange) return;
57 |
58 | if (s.length() > 5 || s.length() < 10) {
59 | try {
60 | int c = ColorPickerPreference.convertToColorInt(s.toString());
61 | mHexInternalTextChange = true;
62 | mColorPicker.setColor(c, true);
63 | mHexInternalTextChange = false;
64 | mHexVal.setTextColor(mHexDefaultTextColor);
65 | } catch (NumberFormatException e) {
66 | mHexVal.setTextColor(Color.RED);
67 | }
68 | } else
69 | mHexVal.setTextColor(Color.RED);
70 | }
71 | }
72 | });
73 | setHexValueEnabled(true);
74 | ((LinearLayout) mOldColor.getParent()).setPadding(
75 | Math.round(mColorPicker.getDrawingOffset()),
76 | 0,
77 | Math.round(mColorPicker.getDrawingOffset()),
78 | 0
79 | );
80 | mOldColor.setOnClickListener(this);
81 | mNewColor.setOnClickListener(this);
82 | mColorPicker.setOnColorChangedListener(this);
83 | mOldColor.setColor(color);
84 | mColorPicker.setColor(color, true);
85 | }
86 | @Override
87 | public void onColorChanged(int color) {
88 | mNewColor.setColor(color);
89 | if (mHexValueEnabled)
90 | updateHexValue(color);
91 | }
92 | public void setHexValueEnabled(boolean enable) {
93 | mHexValueEnabled = enable;
94 | if (enable) {
95 | mHexVal.setVisibility(View.VISIBLE);
96 | updateHexLengthFilter();
97 | updateHexValue(getColor());
98 | }
99 | else
100 | mHexVal.setVisibility(View.GONE);
101 | }
102 | public boolean getHexValueEnabled() { return mHexValueEnabled; }
103 | private void updateHexLengthFilter() {
104 | if (getAlphaSliderVisible())
105 | mHexVal.setFilters(new InputFilter[] {new InputFilter.LengthFilter(9)});
106 | else
107 | mHexVal.setFilters(new InputFilter[] {new InputFilter.LengthFilter(7)});
108 | }
109 | private void updateHexValue(int color) {
110 | if (mHexInternalTextChange) return;
111 | mHexInternalTextChange = true;
112 | if (getAlphaSliderVisible())
113 | mHexVal.setText(ColorPickerPreference.convertToARGB(color));
114 | else
115 | mHexVal.setText(ColorPickerPreference.convertToRGB(color));
116 | mHexInternalTextChange = false;
117 | }
118 | public void setAlphaSliderVisible(boolean visible) {
119 | mColorPicker.setAlphaSliderVisible(visible);
120 | if (mHexValueEnabled) {
121 | updateHexLengthFilter();
122 | updateHexValue(getColor());
123 | }
124 | }
125 | public boolean getAlphaSliderVisible() { return mColorPicker.getAlphaSliderVisible(); }
126 | public void setOnColorChangedListener(OnColorChangedListener listener){ mListener = listener; }
127 | public int getColor() { return mColorPicker.getColor(); }
128 | @Override
129 | public void onClick(View v) {
130 | if (v.getId() == R.id.new_color_panel) {
131 | if (mListener != null) { mListener.onColorChanged(mNewColor.getColor()); }
132 | }
133 | dismiss();
134 | }
135 | @Override
136 | public Bundle onSaveInstanceState() {
137 | Bundle state = super.onSaveInstanceState();
138 | state.putInt("old_color", mOldColor.getColor());
139 | state.putInt("new_color", mNewColor.getColor());
140 | return state;
141 | }
142 | @Override
143 | public void onRestoreInstanceState(Bundle savedInstanceState) {
144 | super.onRestoreInstanceState(savedInstanceState);
145 | mOldColor.setColor(savedInstanceState.getInt("old_color"));
146 | mColorPicker.setColor(savedInstanceState.getInt("new_color"), true);
147 | }
148 | }
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/app/src/main/java/in/proficientapps/MaterializeXposedInstaller/preferences/ColorPickerPreference.java:
--------------------------------------------------------------------------------
1 | package in.proficientapps.MaterializeXposedInstaller.preferences;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Color;
7 | import android.graphics.PorterDuff;
8 | import android.graphics.drawable.Drawable;
9 | import android.os.Bundle;
10 | import android.os.Parcel;
11 | import android.os.Parcelable;
12 | import android.preference.Preference;
13 | import android.util.AttributeSet;
14 | import android.view.View;
15 | import android.widget.CheckBox;
16 | import android.widget.CompoundButton;
17 | import android.widget.ImageView;
18 | import android.widget.LinearLayout;
19 |
20 | import in.proficientapps.MaterializeXposedInstaller.R;
21 |
22 | public class ColorPickerPreference extends Preference implements Preference.OnPreferenceClickListener,
23 | ColorPickerDialog.OnColorChangedListener, CompoundButton.OnCheckedChangeListener {
24 |
25 | View mView;
26 | ColorPickerDialog mDialog;
27 | boolean mShowCheckBox = false;
28 | boolean mPickerEnabled = false;
29 | private int mValue = Color.BLACK;
30 | private float mDensity = 0;
31 | private boolean mAlphaSliderEnabled = false;
32 | private boolean mHexValueEnabled = false;
33 | public ColorPickerPreference(Context context) {
34 | super(context);
35 | init(context, null);
36 | }
37 | public ColorPickerPreference(Context context, AttributeSet attrs) {
38 | super(context, attrs);
39 | init(context, attrs);
40 | }
41 | public ColorPickerPreference(Context context, AttributeSet attrs, int defStyle) {
42 | super(context, attrs, defStyle);
43 | init(context, attrs);
44 | }
45 | @Override
46 | protected Object onGetDefaultValue(TypedArray a, int index) {
47 | return a.getColor(index, Color.BLACK);
48 | }
49 | @Override
50 | protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
51 | if (restoreValue)
52 | mPickerEnabled = !mShowCheckBox || getSharedPreferences().getBoolean(getKey() + "_checkbox", mPickerEnabled);
53 | onColorChanged(restoreValue ? getPersistedInt(mValue) : (Integer) defaultValue);
54 | }
55 | private void init(Context context, AttributeSet attrs) {
56 | mDensity = getContext().getResources().getDisplayMetrics().density;
57 | setOnPreferenceClickListener(this);
58 | if (attrs != null) {
59 | mAlphaSliderEnabled = attrs.getAttributeBooleanValue(null, "alphaSlider", false);
60 | mShowCheckBox = attrs.getAttributeBooleanValue(null, "showCheckBox", false);
61 | mPickerEnabled = !mShowCheckBox || attrs.getAttributeBooleanValue(null, "enabledByDefault", false);
62 | mHexValueEnabled = attrs.getAttributeBooleanValue(null, "hexValue", false);
63 | }
64 | }
65 | @Override
66 | protected void onBindView(View view) {
67 | super.onBindView(view);
68 | mView = view;
69 | setPreviewColor();
70 | }
71 | private void setPreviewColor() {
72 | if (mView == null) return;
73 | CheckBox cbPickerEnabled = null;
74 | if (mShowCheckBox) {
75 | cbPickerEnabled = new CheckBox(getContext());
76 | Drawable checkbg = getContext().getResources().getDrawable(R.drawable.checks);
77 | int colorAccent = getContext().getResources().getColor(R.color.colorAccent0);
78 | checkbg.setColorFilter(colorAccent, PorterDuff.Mode.MULTIPLY );
79 | cbPickerEnabled.setButtonDrawable(checkbg);
80 | cbPickerEnabled.setFocusable(false);
81 | cbPickerEnabled.setEnabled(super.isEnabled());
82 | cbPickerEnabled.setChecked(mPickerEnabled);
83 | cbPickerEnabled.setOnCheckedChangeListener(this);
84 | }
85 | ImageView iView = new ImageView(getContext());
86 | LinearLayout widgetFrameView = ((LinearLayout)mView.findViewById(android.R.id.widget_frame));
87 | if (widgetFrameView == null) return;
88 | widgetFrameView.setVisibility(View.VISIBLE);
89 | widgetFrameView.setPadding(
90 | widgetFrameView.getPaddingLeft(),
91 | widgetFrameView.getPaddingTop(),
92 | (int)(mDensity * 8),
93 | widgetFrameView.getPaddingBottom()
94 | );
95 | int count = widgetFrameView.getChildCount();
96 | if (count > 0) {
97 | widgetFrameView.removeViews(0, count);
98 | }
99 | if (mShowCheckBox) {
100 | widgetFrameView.setOrientation(LinearLayout.HORIZONTAL);
101 | widgetFrameView.addView(cbPickerEnabled);
102 | }
103 | widgetFrameView.addView(iView);
104 | widgetFrameView.setMinimumWidth(0);
105 | getPreviewDrawable(iView);
106 | }
107 | private Drawable getPreviewDrawable(ImageView image) {
108 | int color = mValue;
109 | Drawable bm = getContext().getResources().getDrawable(R.drawable.colorpicker);
110 | bm.setColorFilter(color, PorterDuff.Mode.MULTIPLY);
111 | image.setImageDrawable(bm);
112 | return bm;
113 | }
114 | @Override
115 | public void onColorChanged(int color) {
116 | if (isPersistent()) { persistInt(color); }
117 | mValue = color;
118 | persistBothValues();
119 | setPreviewColor();
120 | notifyChanged();
121 | try { getOnPreferenceChangeListener().onPreferenceChange(this, color);
122 | } catch (NullPointerException ignored) {}
123 | }
124 | @Override
125 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
126 | mPickerEnabled = isChecked;
127 | persistBothValues();
128 | notifyDependencyChange(shouldDisableDependents());
129 | notifyChanged();
130 | }
131 | protected void persistBothValues() {
132 | if (shouldPersist()) {
133 | SharedPreferences.Editor editor = getEditor();
134 | editor.putInt(getKey(), mValue);
135 | if (mShowCheckBox)
136 | editor.putBoolean(getKey() + "_checkbox", mPickerEnabled);
137 | if (shouldCommit()) {
138 | try {
139 | editor.apply();
140 | } catch (AbstractMethodError unused) { editor.commit(); }
141 | }
142 | }
143 | }
144 | @Override
145 | public boolean isEnabled() {
146 | return super.isEnabled() && mPickerEnabled;
147 | }
148 | public void setValue(int color) {
149 | if (isPersistent()) { persistInt(color); }
150 | mValue = color;
151 | setPreviewColor();
152 | }
153 | public boolean onPreferenceClick(Preference preference) {
154 | showDialog(null);
155 | return false;
156 | }
157 | protected void showDialog(Bundle state) {
158 | mDialog = new ColorPickerDialog(getContext(), mValue);
159 | mDialog.setOnColorChangedListener(this);
160 | if (mAlphaSliderEnabled) { mDialog.setAlphaSliderVisible(true); }
161 | if (mHexValueEnabled) { mDialog.setHexValueEnabled(true); }
162 | if (state != null) { mDialog.onRestoreInstanceState(state); }
163 | mDialog.show();
164 | }
165 | public void setAlphaSliderEnabled(boolean enable) { mAlphaSliderEnabled = enable; }
166 | public void setHexValueEnabled(boolean enable) { mHexValueEnabled = enable; }
167 | public static String convertToARGB(int color) {
168 | String alpha = Integer.toHexString(Color.alpha(color));
169 | String red = Integer.toHexString(Color.red(color));
170 | String green = Integer.toHexString(Color.green(color));
171 | String blue = Integer.toHexString(Color.blue(color));
172 | if (alpha.length() == 1) { alpha = "0" + alpha; }
173 | if (red.length() == 1) { red = "0" + red; }
174 | if (green.length() == 1) { green = "0" + green; }
175 | if (blue.length() == 1) { blue = "0" + blue; }
176 | return "#" + alpha + red + green + blue;
177 | }
178 | public static String convertToRGB(int color) {
179 | String red = Integer.toHexString(Color.red(color));
180 | String green = Integer.toHexString(Color.green(color));
181 | String blue = Integer.toHexString(Color.blue(color));
182 | if (red.length() == 1) { red = "0" + red; }
183 | if (green.length() == 1) { green = "0" + green; }
184 | if (blue.length() == 1) { blue = "0" + blue; }
185 | return "#" + red + green + blue;
186 | }
187 | public static int convertToColorInt(String argb) throws NumberFormatException {
188 | if (argb.startsWith("#")) { argb = argb.replace("#", ""); }
189 | int alpha = -1, red = -1, green = -1, blue = -1;
190 | if (argb.length() == 8) {
191 | alpha = Integer.parseInt(argb.substring(0, 2), 16);
192 | red = Integer.parseInt(argb.substring(2, 4), 16);
193 | green = Integer.parseInt(argb.substring(4, 6), 16);
194 | blue = Integer.parseInt(argb.substring(6, 8), 16);
195 | }
196 | else if (argb.length() == 6) {
197 | alpha = 255;
198 | red = Integer.parseInt(argb.substring(0, 2), 16);
199 | green = Integer.parseInt(argb.substring(2, 4), 16);
200 | blue = Integer.parseInt(argb.substring(4, 6), 16);
201 | }
202 | else
203 | throw new NumberFormatException("string " + argb + "did not meet length requirements");
204 | return Color.argb(alpha, red, green, blue);
205 | }
206 | @Override
207 | protected Parcelable onSaveInstanceState() {
208 | final Parcelable superState = super.onSaveInstanceState();
209 | if (mDialog == null || !mDialog.isShowing()) { return superState; }
210 | final SavedState myState = new SavedState(superState);
211 | myState.dialogBundle = mDialog.onSaveInstanceState();
212 | myState.pickerEnabled = mPickerEnabled;
213 | return myState;
214 | }
215 | @Override
216 | protected void onRestoreInstanceState(Parcelable state) {
217 | if (state == null || !(state instanceof SavedState)) {
218 | super.onRestoreInstanceState(state);
219 | return;
220 | }
221 | SavedState myState = (SavedState) state;
222 | super.onRestoreInstanceState(myState.getSuperState());
223 | mPickerEnabled = myState.pickerEnabled;
224 | if (myState.dialogBundle != null)
225 | showDialog(myState.dialogBundle);
226 | }
227 | private static class SavedState extends BaseSavedState {
228 | Bundle dialogBundle;
229 | boolean pickerEnabled;
230 | public SavedState(Parcel source) {
231 | super(source);
232 | dialogBundle = source.readBundle();
233 | pickerEnabled = source.readInt() == 1;
234 | }
235 | @Override
236 | public void writeToParcel(Parcel dest, int flags) {
237 | super.writeToParcel(dest, flags);
238 | dest.writeBundle(dialogBundle);
239 | dest.writeInt(pickerEnabled ? 1 : 0);
240 | }
241 | public SavedState(Parcelable superState) { super(superState); }
242 | @SuppressWarnings("unused")
243 | public static final Creator CREATOR = new Creator() {
244 | public SavedState createFromParcel(Parcel in) { return new SavedState(in); }
245 | public SavedState[] newArray(int size) { return new SavedState[size]; }
246 | };
247 | }
248 | }
--------------------------------------------------------------------------------
/app/src/main/java/in/proficientapps/MaterializeXposedInstaller/Module.java:
--------------------------------------------------------------------------------
1 | package in.proficientapps.MaterializeXposedInstaller;
2 |
3 | import android.app.Activity;
4 | import android.content.res.XModuleResources;
5 | import android.content.res.XResources;
6 | import android.graphics.Color;
7 | import android.os.Bundle;
8 | import android.view.Window;
9 | import android.view.WindowManager;
10 | import android.widget.TextView;
11 |
12 | import de.robv.android.xposed.IXposedHookInitPackageResources;
13 | import de.robv.android.xposed.IXposedHookLoadPackage;
14 | import de.robv.android.xposed.IXposedHookZygoteInit;
15 | import de.robv.android.xposed.XC_MethodHook;
16 | import de.robv.android.xposed.XSharedPreferences;
17 | import de.robv.android.xposed.XposedBridge;
18 | import de.robv.android.xposed.callbacks.XC_InitPackageResources.InitPackageResourcesParam;
19 | import de.robv.android.xposed.callbacks.XC_LayoutInflated;
20 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
21 |
22 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
23 | import static de.robv.android.xposed.XposedHelpers.findClass;
24 |
25 | /*
26 | * Created by SArnab©® on 06-09-2015.
27 | *
28 | * Developer Note : I made this Module in 10 Minutes
29 | * so that I can enjoy Material UI inside the Xposed
30 | * Installer App. For now it's very basic and provides
31 | * 3 different themes to choose from. Feel free to fork
32 | * and upgrade it if you have anything new in mind.
33 | * But, please do not release a new separate version.
34 | * Instead, update me regarding your changes and I will try my best
35 | * to add those in my source and release an update.
36 | * You may compile a different version for your personal use.
37 | */
38 | public class Module implements IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
39 |
40 | public static String MODULE_PATH = null;
41 | public static XSharedPreferences pref;
42 |
43 | @Override
44 | public void initZygote(StartupParam startupParam) throws Throwable {
45 | MODULE_PATH = startupParam.modulePath;
46 | pref = new XSharedPreferences("in.proficientapps.MaterializeXposedInstaller");
47 | }
48 |
49 | /* Fixing Cards BG issue in Dark Theme(s). */
50 | @Override
51 | public void handleInitPackageResources(InitPackageResourcesParam resparam) throws Throwable {
52 | pref.reload();
53 | /* Checking if it's really Xposed Installer App or not. */
54 | if (!resparam.packageName.equals("de.robv.android.xposed.installer"))
55 | return;
56 |
57 | XModuleResources modRes = XModuleResources.createInstance(Module.MODULE_PATH, resparam.res);
58 |
59 | /* Checking if the module has been activated within the app. */
60 | if (pref.getBoolean("pref_key_activate_module", false)) {
61 | /* Getting selected colour from ColourPickerPreference */
62 | int mPrimaryColour = pref.getInt("pref_key_colour_primary", R.color.colorAccent0);
63 | final int mAccentColour = pref.getInt("pref_key_colour_accent", R.color.colorAccent1);
64 | int mBgColour = pref.getInt("pref_key_colour_bg", R.color.colorAccent2);
65 | /* Creating PrimaryColourDark from PrimaryColour */
66 | int mPrimaryColourDark = Color.rgb(Color.red(mPrimaryColour) * 192 / 256, Color.green(mPrimaryColour) * 192 / 256, Color.blue(mPrimaryColour) * 192 / 256);
67 | /* Getting selected theme index. */
68 | int transition = Integer.parseInt(pref.getString("pref_key_theme_list", "0"));
69 | switch (transition) {
70 | case 0:
71 | break;
72 |
73 | case 1:
74 | /*
75 | * Added in version 1.1
76 | * Checking if Colour Picker CheckBox is checked or not.
77 | * If checked than app's primary and primary dark colours are applied from ColourPickerPreference.
78 | * Same occurs in all other cases.
79 | */
80 | if(pref.getBoolean("pref_key_colour_primary_checkbox", false)) {
81 | XResources.setSystemWideReplacement("android", "color", "primary_material_dark", mPrimaryColour);
82 | XResources.setSystemWideReplacement("android", "color", "primary_dark_material_dark", mPrimaryColourDark);
83 | }
84 | if(pref.getBoolean("pref_key_colour_accent_checkbox", false)) {
85 | XResources.setSystemWideReplacement("android", "color", "material_deep_teal_500", mAccentColour);
86 | resparam.res.hookLayout("android", "layout", "preference_category_material", new XC_LayoutInflated() {
87 | @Override
88 | public void handleLayoutInflated(LayoutInflatedParam liparam) throws Throwable {
89 | TextView preferenceCategory = (TextView) liparam.view.getRootView();
90 | preferenceCategory.setTextColor(mAccentColour);
91 | }
92 | });
93 | }
94 | if(pref.getBoolean("pref_key_colour_bg_checkbox", false)) {
95 | XResources.setSystemWideReplacement("android", "color", "background_material_light", mBgColour);
96 | }
97 | break;
98 |
99 | case 2:
100 | /* Added in version v1.1 */
101 | if(pref.getBoolean("pref_key_colour_primary_checkbox", false)) {
102 | XResources.setSystemWideReplacement("android", "color", "primary_material_light", mPrimaryColour);
103 | XResources.setSystemWideReplacement("android", "color", "primary_dark_material_light", mPrimaryColourDark);
104 | }
105 | if(pref.getBoolean("pref_key_colour_accent_checkbox", false)) {
106 | XResources.setSystemWideReplacement("android", "color", "material_deep_teal_500", mAccentColour);
107 | resparam.res.hookLayout("android", "layout", "preference_category_material", new XC_LayoutInflated() {
108 | @Override
109 | public void handleLayoutInflated(LayoutInflatedParam liparam) throws Throwable {
110 | TextView preferenceCategory = (TextView) liparam.view.getRootView();
111 | preferenceCategory.setTextColor(mAccentColour);
112 | }
113 | });
114 | }
115 | if(pref.getBoolean("pref_key_colour_bg_checkbox", false)) {
116 | XResources.setSystemWideReplacement("android", "color", "background_material_light", mBgColour);
117 | }
118 | break;
119 |
120 | case 3:
121 | /* Only the last theme requires the fix as the text is white on white bg in Modules Page */
122 | resparam.res.setReplacement("de.robv.android.xposed.installer", "drawable", "background_card_light", modRes.fwd(R.drawable.background_card_dark));
123 | resparam.res.setReplacement("de.robv.android.xposed.installer", "drawable", "background_card_pressed_light", modRes.fwd(R.drawable.background_card_pressed_dark));
124 | /* Added in version v1.1 */
125 | if(pref.getBoolean("pref_key_colour_primary_checkbox", false)) {
126 | XResources.setSystemWideReplacement("android", "color", "primary_material_dark", mPrimaryColour);
127 | XResources.setSystemWideReplacement("android", "color", "primary_dark_material_dark", mPrimaryColourDark);
128 | }
129 | if(pref.getBoolean("pref_key_colour_accent_checkbox", false)) {
130 | XResources.setSystemWideReplacement("android", "color", "material_deep_teal_200", mAccentColour);
131 | resparam.res.hookLayout("android", "layout", "preference_category_material", new XC_LayoutInflated() {
132 | @Override
133 | public void handleLayoutInflated(LayoutInflatedParam liparam) throws Throwable {
134 | TextView preferenceCategory = (TextView) liparam.view.getRootView();
135 | preferenceCategory.setTextColor(mAccentColour);
136 | }
137 | });
138 | }
139 | if(pref.getBoolean("pref_key_colour_bg_checkbox", false)) {
140 | XResources.setSystemWideReplacement("android", "color", "background_material_dark", mBgColour);
141 | }
142 | break;
143 | }
144 | }
145 | }
146 |
147 | @Override
148 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
149 | pref.reload();
150 | /* Checking if it's really Xposed Installer App or not. */
151 | if (!lpparam.packageName.equals("de.robv.android.xposed.installer"))
152 | return;
153 |
154 | /* Setting the base activity class to hook it for making changes. */
155 | final Class> XposedInstallerBase = findClass("de.robv.android.xposed.installer.XposedBaseActivity", lpparam.classLoader);
156 |
157 | try {
158 | findAndHookMethod(XposedInstallerBase, "onCreate", Bundle.class, new XC_MethodHook() {
159 | @Override
160 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
161 | /* Getting the base activity */
162 | Activity activity = (Activity) param.thisObject;
163 | /* Checking if the module has been activated within the app. */
164 | if (pref.getBoolean("pref_key_activate_module", false)) {
165 | /* Getting selected colour from ColourPickerPreference */
166 | int mPrimaryColour = pref.getInt("pref_key_colour_primary", R.color.colorAccent2);
167 | /* Creating PrimaryColourDark from PrimaryColour */
168 | int mPrimaryColourDark = Color.rgb(Color.red(mPrimaryColour) * 192 / 256, Color.green(mPrimaryColour) * 192 / 256, Color.blue(mPrimaryColour) * 192 / 256);
169 | /* Getting selected theme index. */
170 | int transition = Integer.parseInt(pref.getString("pref_key_theme_list", "0"));
171 | switch (transition) {
172 | case 0:
173 | break;
174 |
175 | case 1:
176 | activity.setTheme(android.R.style.Theme_Material_Light_DarkActionBar);
177 | /* Added in version v1.1 */
178 | /*
179 | * Checking if Colour Picker CheckBox is checked or not.
180 | * If checked than change statusbar colour to PrimaryDark.
181 | * Same occurs in all other cases.
182 | */
183 | if(pref.getBoolean("pref_key_colour_primary_checkbox", false)) {
184 | Window window = activity.getWindow();
185 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
186 | window.setStatusBarColor(mPrimaryColourDark);
187 | }
188 | break;
189 |
190 | case 2:
191 | activity.setTheme(android.R.style.Theme_Material_Light);
192 | /* Added in version v1.1 */
193 | if(pref.getBoolean("pref_key_colour_primary_checkbox", false)) {
194 | Window window = activity.getWindow();
195 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
196 | window.setStatusBarColor(mPrimaryColourDark);
197 | }
198 | break;
199 |
200 | case 3:
201 | activity.setTheme(android.R.style.Theme_Material);
202 | /* Added in version v1.1 */
203 | if(pref.getBoolean("pref_key_colour_primary_checkbox", false)) {
204 | Window window = activity.getWindow();
205 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
206 | window.setStatusBarColor(mPrimaryColourDark);
207 | }
208 | break;
209 | }
210 | }
211 | }
212 | });
213 | } catch (Exception e) {
214 | /* Doing everything inside a try-catch block in order to get any error that occurs. */
215 | XposedBridge.log("================================\nError Message : " + e.getMessage());
216 | XposedBridge.log("Error Cause" + e.getCause().toString() + "\n================================");
217 | }
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/app/src/main/java/in/proficientapps/MaterializeXposedInstaller/preferences/ColorPickerView.java:
--------------------------------------------------------------------------------
1 | package in.proficientapps.MaterializeXposedInstaller.preferences;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.ComposeShader;
7 | import android.graphics.LinearGradient;
8 | import android.graphics.Paint;
9 | import android.graphics.Paint.Align;
10 | import android.graphics.Paint.Style;
11 | import android.graphics.Point;
12 | import android.graphics.PorterDuff;
13 | import android.graphics.RectF;
14 | import android.graphics.Shader;
15 | import android.graphics.Shader.TileMode;
16 | import android.util.AttributeSet;
17 | import android.view.MotionEvent;
18 | import android.view.View;
19 |
20 | public class ColorPickerView extends View {
21 |
22 | private final static int PANEL_SAT_VAL = 0;
23 | private final static int PANEL_HUE = 1;
24 | private final static int PANEL_ALPHA = 2;
25 | private final static float BORDER_WIDTH_PX = 1;
26 | private float HUE_PANEL_WIDTH = 30f;
27 | private float ALPHA_PANEL_HEIGHT = 20f;
28 | private float PANEL_SPACING = 10f;
29 | private float PALETTE_CIRCLE_TRACKER_RADIUS = 5f;
30 | private float RECTANGLE_TRACKER_OFFSET = 2f;
31 | private float mDensity = 1f;
32 | private OnColorChangedListener mListener;
33 | private Paint mSatValPaint;
34 | private Paint mSatValTrackerPaint;
35 | private Paint mHuePaint;
36 | private Paint mHueTrackerPaint;
37 | private Paint mAlphaPaint;
38 | private Paint mAlphaTextPaint;
39 | private Paint mBorderPaint;
40 | private Shader mValShader;
41 | private Shader mSatShader;
42 | private Shader mHueShader;
43 | private Shader mAlphaShader;
44 | private int mAlpha = 0xff;
45 | private float mHue = 360f;
46 | private float mSat = 0f;
47 | private float mVal = 0f;
48 | private String mAlphaSliderText = "";
49 | private int mSliderTrackerColor = 0xff1c1c1c;
50 | private int mBorderColor = 0xff6E6E6E;
51 | private boolean mShowAlphaPanel = false;
52 | private int mLastTouchedPanel = PANEL_SAT_VAL;
53 | private float mDrawingOffset;
54 | private RectF mDrawingRect;
55 | private RectF mSatValRect;
56 | private RectF mHueRect;
57 | private RectF mAlphaRect;
58 | private AlphaPatternDrawable mAlphaPattern;
59 | private Point mStartTouchPoint = null;
60 | public interface OnColorChangedListener { public void onColorChanged(int color); }
61 | public ColorPickerView(Context context){ this(context, null); }
62 | public ColorPickerView(Context context, AttributeSet attrs) { this(context, attrs, 0); }
63 | public ColorPickerView(Context context, AttributeSet attrs, int defStyle) {
64 | super(context, attrs, defStyle);
65 | init();
66 | }
67 | private void init(){
68 | mDensity = getContext().getResources().getDisplayMetrics().density;
69 | PALETTE_CIRCLE_TRACKER_RADIUS *= mDensity;
70 | RECTANGLE_TRACKER_OFFSET *= mDensity;
71 | HUE_PANEL_WIDTH *= mDensity;
72 | ALPHA_PANEL_HEIGHT *= mDensity;
73 | PANEL_SPACING = PANEL_SPACING * mDensity;
74 | mDrawingOffset = calculateRequiredOffset();
75 | initPaintTools();
76 | setFocusable(true);
77 | setFocusableInTouchMode(true);
78 | }
79 | private void initPaintTools(){
80 | mSatValPaint = new Paint();
81 | mSatValTrackerPaint = new Paint();
82 | mHuePaint = new Paint();
83 | mHueTrackerPaint = new Paint();
84 | mAlphaPaint = new Paint();
85 | mAlphaTextPaint = new Paint();
86 | mBorderPaint = new Paint();
87 | mSatValTrackerPaint.setStyle(Style.STROKE);
88 | mSatValTrackerPaint.setStrokeWidth(2f * mDensity);
89 | mSatValTrackerPaint.setAntiAlias(true);
90 | mHueTrackerPaint.setColor(mSliderTrackerColor);
91 | mHueTrackerPaint.setStyle(Style.STROKE);
92 | mHueTrackerPaint.setStrokeWidth(2f * mDensity);
93 | mHueTrackerPaint.setAntiAlias(true);
94 | mAlphaTextPaint.setColor(0xff1c1c1c);
95 | mAlphaTextPaint.setTextSize(14f * mDensity);
96 | mAlphaTextPaint.setAntiAlias(true);
97 | mAlphaTextPaint.setTextAlign(Align.CENTER);
98 | mAlphaTextPaint.setFakeBoldText(true);
99 | }
100 | private float calculateRequiredOffset(){
101 | float offset = Math.max(PALETTE_CIRCLE_TRACKER_RADIUS, RECTANGLE_TRACKER_OFFSET);
102 | offset = Math.max(offset, BORDER_WIDTH_PX * mDensity);
103 | return offset * 1.5f;
104 | }
105 | private int[] buildHueColorArray(){
106 | int[] hue = new int[361];
107 | int count = 0;
108 | for(int i = hue.length -1; i >= 0; i--, count++){ hue[count] = Color.HSVToColor(new float[]{i, 1f, 1f}); }
109 | return hue;
110 | }
111 | @Override
112 | protected void onDraw(Canvas canvas) {
113 | if(mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0) return;
114 | drawSatValPanel(canvas);
115 | drawHuePanel(canvas);
116 | drawAlphaPanel(canvas);
117 | }
118 | private void drawSatValPanel(Canvas canvas){
119 | final RectF rect = mSatValRect;
120 | if(BORDER_WIDTH_PX > 0){
121 | mBorderPaint.setColor(mBorderColor);
122 | canvas.drawRect(mDrawingRect.left, mDrawingRect.top, rect.right + BORDER_WIDTH_PX, rect.bottom + BORDER_WIDTH_PX, mBorderPaint);
123 | }
124 | if (mValShader == null) {
125 | mValShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
126 | 0xffffffff, 0xff000000, TileMode.CLAMP);
127 | }
128 | int rgb = Color.HSVToColor(new float[]{mHue,1f,1f});
129 | mSatShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top, 0xffffffff, rgb, TileMode.CLAMP);
130 | ComposeShader mShader = new ComposeShader(mValShader, mSatShader, PorterDuff.Mode.MULTIPLY);
131 | mSatValPaint.setShader(mShader);
132 | canvas.drawRect(rect, mSatValPaint);
133 | Point p = satValToPoint(mSat, mVal);
134 | mSatValTrackerPaint.setColor(0xff000000);
135 | canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS - 1f * mDensity, mSatValTrackerPaint);
136 | mSatValTrackerPaint.setColor(0xffdddddd);
137 | canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS, mSatValTrackerPaint);
138 | }
139 | private void drawHuePanel(Canvas canvas){
140 | final RectF rect = mHueRect;
141 | if(BORDER_WIDTH_PX > 0){
142 | mBorderPaint.setColor(mBorderColor);
143 | canvas.drawRect(rect.left - BORDER_WIDTH_PX,
144 | rect.top - BORDER_WIDTH_PX,
145 | rect.right + BORDER_WIDTH_PX,
146 | rect.bottom + BORDER_WIDTH_PX,
147 | mBorderPaint);
148 | }
149 | if (mHueShader == null) {
150 | mHueShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom, buildHueColorArray(), null, TileMode.CLAMP);
151 | mHuePaint.setShader(mHueShader);
152 | }
153 | canvas.drawRect(rect, mHuePaint);
154 | float rectHeight = 4 * mDensity / 2;
155 | Point p = hueToPoint(mHue);
156 | RectF r = new RectF();
157 | r.left = rect.left - RECTANGLE_TRACKER_OFFSET;
158 | r.right = rect.right + RECTANGLE_TRACKER_OFFSET;
159 | r.top = p.y - rectHeight;
160 | r.bottom = p.y + rectHeight;
161 | canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
162 | }
163 | private void drawAlphaPanel(Canvas canvas){
164 | if(!mShowAlphaPanel || mAlphaRect == null || mAlphaPattern == null) return;
165 | final RectF rect = mAlphaRect;
166 | if(BORDER_WIDTH_PX > 0){
167 | mBorderPaint.setColor(mBorderColor);
168 | canvas.drawRect(rect.left - BORDER_WIDTH_PX,
169 | rect.top - BORDER_WIDTH_PX,
170 | rect.right + BORDER_WIDTH_PX,
171 | rect.bottom + BORDER_WIDTH_PX,
172 | mBorderPaint);
173 | }
174 | mAlphaPattern.draw(canvas);
175 | float[] hsv = new float[]{mHue,mSat,mVal};
176 | int color = Color.HSVToColor(hsv);
177 | int acolor = Color.HSVToColor(0, hsv);
178 | mAlphaShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top, color, acolor, TileMode.CLAMP);
179 | mAlphaPaint.setShader(mAlphaShader);
180 | canvas.drawRect(rect, mAlphaPaint);
181 | if(mAlphaSliderText != null && mAlphaSliderText!= ""){
182 | canvas.drawText(mAlphaSliderText, rect.centerX(), rect.centerY() + 4 * mDensity, mAlphaTextPaint);
183 | }
184 | float rectWidth = 4 * mDensity / 2;
185 | Point p = alphaToPoint(mAlpha);
186 | RectF r = new RectF();
187 | r.left = p.x - rectWidth;
188 | r.right = p.x + rectWidth;
189 | r.top = rect.top - RECTANGLE_TRACKER_OFFSET;
190 | r.bottom = rect.bottom + RECTANGLE_TRACKER_OFFSET;
191 | canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
192 | }
193 | private Point hueToPoint(float hue){
194 | final RectF rect = mHueRect;
195 | final float height = rect.height();
196 | Point p = new Point();
197 | p.y = (int) (height - (hue * height / 360f) + rect.top);
198 | p.x = (int) rect.left;
199 | return p;
200 | }
201 | private Point satValToPoint(float sat, float val){
202 | final RectF rect = mSatValRect;
203 | final float height = rect.height();
204 | final float width = rect.width();
205 | Point p = new Point();
206 | p.x = (int) (sat * width + rect.left);
207 | p.y = (int) ((1f - val) * height + rect.top);
208 | return p;
209 | }
210 | private Point alphaToPoint(int alpha){
211 | final RectF rect = mAlphaRect;
212 | final float width = rect.width();
213 | Point p = new Point();
214 | p.x = (int) (width - (alpha * width / 0xff) + rect.left);
215 | p.y = (int) rect.top;
216 | return p;
217 | }
218 | private float[] pointToSatVal(float x, float y){
219 | final RectF rect = mSatValRect;
220 | float[] result = new float[2];
221 | float width = rect.width();
222 | float height = rect.height();
223 | if (x < rect.left){ x = 0f; }
224 | else if(x > rect.right){ x = width; }
225 | else{ x = x - rect.left; }
226 | if (y < rect.top){ y = 0f; }
227 | else if(y > rect.bottom){ y = height; }
228 | else{ y = y - rect.top; }
229 | result[0] = 1.f / width * x;
230 | result[1] = 1.f - (1.f / height * y);
231 | return result;
232 | }
233 | private float pointToHue(float y){
234 | final RectF rect = mHueRect;
235 | float height = rect.height();
236 | if (y < rect.top){ y = 0f; }
237 | else if(y > rect.bottom){ y = height; }
238 | else{ y = y - rect.top; }
239 | return 360f - (y * 360f / height);
240 | }
241 |
242 | private int pointToAlpha(int x){
243 | final RectF rect = mAlphaRect;
244 | final int width = (int) rect.width();
245 | if(x < rect.left){ x = 0; }
246 | else if(x > rect.right){ x = width; }
247 | else{ x = x - (int)rect.left; }
248 | return 0xff - (x * 0xff / width);
249 | }
250 | @Override
251 | public boolean onTrackballEvent(MotionEvent event) {
252 | float x = event.getX();
253 | float y = event.getY();
254 | boolean update = false;
255 | if(event.getAction() == MotionEvent.ACTION_MOVE){
256 | switch(mLastTouchedPanel){
257 | case PANEL_SAT_VAL:
258 | float sat, val;
259 | sat = mSat + x/50f;
260 | val = mVal - y/50f;
261 | if(sat < 0f){ sat = 0f; }
262 | else if(sat > 1f){ sat = 1f; }
263 | if(val < 0f){ val = 0f; }
264 | else if(val > 1f){ val = 1f; }
265 | mSat = sat;
266 | mVal = val;
267 | update = true;
268 | break;
269 | case PANEL_HUE:
270 | float hue = mHue - y * 10f;
271 | if(hue < 0f){ hue = 0f; }
272 | else if(hue > 360f){ hue = 360f; }
273 | mHue = hue;
274 | update = true;
275 | break;
276 | case PANEL_ALPHA:
277 | if(!mShowAlphaPanel || mAlphaRect == null){ update = false; }
278 | else{
279 | int alpha = (int) (mAlpha - x*10);
280 | if(alpha < 0){ alpha = 0; }
281 | else if(alpha > 0xff){ alpha = 0xff; }
282 | mAlpha = alpha;
283 | update = true;
284 | }
285 | break;
286 | }
287 | }
288 | if(update){
289 | if(mListener != null){ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal})); }
290 | invalidate();
291 | return true;
292 | }
293 | return super.onTrackballEvent(event);
294 | }
295 | @Override
296 | public boolean onTouchEvent(MotionEvent event) {
297 | boolean update = false;
298 | switch(event.getAction()){
299 | case MotionEvent.ACTION_DOWN:
300 | mStartTouchPoint = new Point((int)event.getX(), (int)event.getY());
301 | update = moveTrackersIfNeeded(event);
302 | break;
303 | case MotionEvent.ACTION_MOVE:
304 | update = moveTrackersIfNeeded(event);
305 | break;
306 | case MotionEvent.ACTION_UP:
307 | mStartTouchPoint = null;
308 | update = moveTrackersIfNeeded(event);
309 | break;
310 | }
311 | if(update){
312 | if(mListener != null){ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal})); }
313 | invalidate();
314 | return true;
315 | }
316 | return super.onTouchEvent(event);
317 | }
318 | private boolean moveTrackersIfNeeded(MotionEvent event){
319 | if(mStartTouchPoint == null) return false;
320 | boolean update = false;
321 | int startX = mStartTouchPoint.x;
322 | int startY = mStartTouchPoint.y;
323 | if(mHueRect.contains(startX, startY)){
324 | mLastTouchedPanel = PANEL_HUE;
325 | mHue = pointToHue(event.getY());
326 | update = true;
327 | }
328 | else if(mSatValRect.contains(startX, startY)){
329 | mLastTouchedPanel = PANEL_SAT_VAL;
330 | float[] result = pointToSatVal(event.getX(), event.getY());
331 | mSat = result[0];
332 | mVal = result[1];
333 | update = true;
334 | }
335 | else if(mAlphaRect != null && mAlphaRect.contains(startX, startY)){
336 | mLastTouchedPanel = PANEL_ALPHA;
337 | mAlpha = pointToAlpha((int)event.getX());
338 | update = true;
339 | }
340 | return update;
341 | }
342 | @Override
343 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
344 | int width = 0;
345 | int height = 0;
346 | int widthMode = MeasureSpec.getMode(widthMeasureSpec);
347 | int heightMode = MeasureSpec.getMode(heightMeasureSpec);
348 | int widthAllowed = MeasureSpec.getSize(widthMeasureSpec);
349 | int heightAllowed = MeasureSpec.getSize(heightMeasureSpec);
350 | widthAllowed = chooseWidth(widthMode, widthAllowed);
351 | heightAllowed = chooseHeight(heightMode, heightAllowed);
352 | if(!mShowAlphaPanel){
353 | height = (int) (widthAllowed - PANEL_SPACING - HUE_PANEL_WIDTH);
354 | if(height > heightAllowed || getTag().equals("landscape")) {
355 | height = heightAllowed;
356 | width = (int) (height + PANEL_SPACING + HUE_PANEL_WIDTH);
357 | }
358 | else{ width = widthAllowed; }
359 | }
360 | else{
361 | width = (int) (heightAllowed - ALPHA_PANEL_HEIGHT + HUE_PANEL_WIDTH);
362 | if(width > widthAllowed){
363 | width = widthAllowed;
364 | height = (int) (widthAllowed - HUE_PANEL_WIDTH + ALPHA_PANEL_HEIGHT);
365 | }
366 | else{ height = heightAllowed; }
367 | }
368 | setMeasuredDimension(width, height);
369 | }
370 | private int chooseWidth(int mode, int size){
371 | if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) { return size;}
372 | else { return getPrefferedWidth(); }
373 | }
374 | private int chooseHeight(int mode, int size){
375 | if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) { return size; }
376 | else { return getPrefferedHeight(); }
377 | }
378 | private int getPrefferedWidth(){
379 | int width = getPrefferedHeight();
380 | if(mShowAlphaPanel){ width -= (PANEL_SPACING + ALPHA_PANEL_HEIGHT); }
381 | return (int) (width + HUE_PANEL_WIDTH + PANEL_SPACING);
382 | }
383 | private int getPrefferedHeight(){
384 | int height = (int)(200 * mDensity);
385 | if(mShowAlphaPanel){ height += PANEL_SPACING + ALPHA_PANEL_HEIGHT; }
386 | return height;
387 | }
388 | @Override
389 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
390 | super.onSizeChanged(w, h, oldw, oldh);
391 | mDrawingRect = new RectF();
392 | mDrawingRect.left = mDrawingOffset + getPaddingLeft();
393 | mDrawingRect.right = w - mDrawingOffset - getPaddingRight();
394 | mDrawingRect.top = mDrawingOffset + getPaddingTop();
395 | mDrawingRect.bottom = h - mDrawingOffset - getPaddingBottom();
396 | setUpSatValRect();
397 | setUpHueRect();
398 | setUpAlphaRect();
399 | }
400 | private void setUpSatValRect(){
401 | final RectF dRect = mDrawingRect;
402 | float panelSide = dRect.height() - BORDER_WIDTH_PX * 2;
403 | if(mShowAlphaPanel){
404 | panelSide -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
405 | }
406 | float left = dRect.left + BORDER_WIDTH_PX;
407 | float top = dRect.top + BORDER_WIDTH_PX;
408 | float bottom = top + panelSide;
409 | float right = left + panelSide;
410 | mSatValRect = new RectF(left,top, right, bottom);
411 | }
412 | private void setUpHueRect(){
413 | final RectF dRect = mDrawingRect;
414 | float left = dRect.right - HUE_PANEL_WIDTH + BORDER_WIDTH_PX;
415 | float top = dRect.top + BORDER_WIDTH_PX;
416 | float bottom = dRect.bottom - BORDER_WIDTH_PX - (mShowAlphaPanel ? (PANEL_SPACING + ALPHA_PANEL_HEIGHT) : 0);
417 | float right = dRect.right - BORDER_WIDTH_PX;
418 | mHueRect = new RectF(left, top, right, bottom);
419 | }
420 | private void setUpAlphaRect() {
421 | if(!mShowAlphaPanel) return;
422 | final RectF dRect = mDrawingRect;
423 | float left = dRect.left + BORDER_WIDTH_PX;
424 | float top = dRect.bottom - ALPHA_PANEL_HEIGHT + BORDER_WIDTH_PX;
425 | float bottom = dRect.bottom - BORDER_WIDTH_PX;
426 | float right = dRect.right - BORDER_WIDTH_PX;
427 | mAlphaRect = new RectF(left, top, right, bottom);
428 | mAlphaPattern = new AlphaPatternDrawable((int) (5 * mDensity));
429 | mAlphaPattern.setBounds(
430 | Math.round(mAlphaRect.left),
431 | Math.round(mAlphaRect.top),
432 | Math.round(mAlphaRect.right),
433 | Math.round(mAlphaRect.bottom)
434 | );
435 | }
436 | public void setOnColorChangedListener(OnColorChangedListener listener){ mListener = listener; }
437 | public void setBorderColor(int color){
438 | mBorderColor = color;
439 | invalidate();
440 | }
441 | public int getBorderColor(){ return mBorderColor; }
442 | public int getColor(){ return Color.HSVToColor(mAlpha, new float[]{mHue,mSat,mVal}); }
443 | public void setColor(int color){ setColor(color, false); }
444 | public void setColor(int color, boolean callback){
445 | int alpha = Color.alpha(color);
446 | int red = Color.red(color);
447 | int blue = Color.blue(color);
448 | int green = Color.green(color);
449 | float[] hsv = new float[3];
450 | Color.RGBToHSV(red, green, blue, hsv);
451 | mAlpha = alpha;
452 | mHue = hsv[0];
453 | mSat = hsv[1];
454 | mVal = hsv[2];
455 | if(callback && mListener != null){ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal})); }
456 | invalidate();
457 | }
458 | public float getDrawingOffset(){ return mDrawingOffset; }
459 | public void setAlphaSliderVisible(boolean visible){
460 | if(mShowAlphaPanel != visible){
461 | mShowAlphaPanel = visible;
462 | mValShader = null;
463 | mSatShader = null;
464 | mHueShader = null;
465 | mAlphaShader = null;;
466 | requestLayout();
467 | }
468 | }
469 | public boolean getAlphaSliderVisible() { return mShowAlphaPanel; }
470 | public void setSliderTrackerColor(int color){
471 | mSliderTrackerColor = color;
472 | mHueTrackerPaint.setColor(mSliderTrackerColor);
473 | invalidate();
474 | }
475 | public int getSliderTrackerColor(){ return mSliderTrackerColor; }
476 | public void setAlphaSliderText(int res){
477 | String text = getContext().getString(res);
478 | setAlphaSliderText(text);
479 | }
480 | public void setAlphaSliderText(String text){
481 | mAlphaSliderText = text;
482 | invalidate();
483 | }
484 | public String getAlphaSliderText(){ return mAlphaSliderText; }
485 | }
--------------------------------------------------------------------------------