├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── amastigote
│ │ └── darker
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ ├── amastigote
│ │ │ └── darker
│ │ │ │ ├── activity
│ │ │ │ ├── AboutActivity.java
│ │ │ │ └── MainActivity.java
│ │ │ │ ├── model
│ │ │ │ ├── DarkerNotification.java
│ │ │ │ └── DarkerSettings.java
│ │ │ │ └── service
│ │ │ │ └── ScreenFilterService.java
│ │ │ └── rtugeek
│ │ │ └── android
│ │ │ └── colorseekbar
│ │ │ └── ColorSeekBar.java
│ └── res
│ │ ├── drawable
│ │ ├── selector_turn_on_button.xml
│ │ ├── shape_checked_toggle_button.xml
│ │ ├── shape_text_tag.xml
│ │ └── shape_unchecked_toggle_button.xml
│ │ ├── layout
│ │ ├── activity_about.xml
│ │ ├── activity_license.xml
│ │ ├── activity_main.xml
│ │ ├── content_main.xml
│ │ ├── control_panel.xml
│ │ └── screen_filter.xml
│ │ ├── menu
│ │ └── menu_main.xml
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_settings_white_24dp.png
│ │ └── night_128.png
│ │ ├── values-v21
│ │ └── styles.xml
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── amastigote
│ └── darker
│ └── ExampleUnitTest.java
├── build.gradle
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | gradlew
9 | gradlew.bat
10 | gradle.properties
11 | gradle/wrapper
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | screen-filter: dims your screen further to protect eyes in complete darkness
2 | Copyright (C) 2016 hwding
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 |
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # screen filter
2 | **dims your screen further to protect eyes in complete darkness**
3 |
4 | [](https://github.com/hwding/make-it-darker/blob/master/LICENSE)
5 | [](https://www.android.com/)
6 | [](http://www.coolapk.com/apk/com.amastigote.darker)
7 | [](http://www.wandoujia.com/apps/com.amastigote.darker)
8 |
9 | ## UPDATE LOG
10 |
11 | ##### 2019-01-23
12 | - fix the problem that filter could not cover the whole screen after orientation
13 |
14 | ##### 2019-01-17
15 | - fix the problem that filter could not cover navigation bar
16 | - update libraries
17 |
18 | ##### 2017-02-06
19 | - remove snack-bars
20 | - optimize activity switching
21 | - change logo
22 | - update libraries
23 | - several UI improvements (string, layout, etc.)
24 |
25 | ##### 2016-10-16
26 | - add auto brightness option
27 | - add brightness & alpha indicator
28 | - optimize third party ColorSeekBar
29 | - several UI improvements (layout, style, animation, etc.)
30 |
31 | ##### 2016-10-10
32 | - fix the problem that filter could not cover the whole screen after orientation
33 | - update google libraries
34 | - several code adjustments
35 |
36 | ##### 2016-08-23
37 | - update libraries
38 | - fix the problem of over scrolling
39 | - change a third party library for circular seekBar
40 |
41 | ##### 2016-08-13
42 | - set fullscreen flag for screen filter
43 |
44 | ##### 2016-08-09
45 | - remove splash page to simplify apk
46 | - remove useless codes
47 | - fix the bug that screen will dim and lock down even when you are watch videos after activating screen filter, so the 'keep screen on' function is removed
48 | - improve UI
49 |
50 | ##### 2016-08-07
51 | - improve service persistence
52 | - change icon
53 |
54 | ##### 2016-08-06
55 | - remove duplicated methods
56 | - remove unused codes
57 |
58 | ##### 2016-08-04
59 | - fix a bug that screen filter can not cover status bar and lock screen
60 | - fix a bug that your wallpaper will go black when screen filter is activated
61 | - improve code structure
62 | - more power-saving when service is running in background
63 | - more bug fixes
64 | - adjust some indicative information
65 | - adjust UI lightly
66 |
67 | ##### 2016-08-03
68 | - new feature: now you can (/de)activate screen filter through tapping the notification, you can also jump directly onto control panel with our new notification
69 |
70 | ##### 2016-08-01
71 | - redesign UI and interaction
72 | - add splash page
73 | - add quit notification
74 |
75 | ##### 2016-07-30
76 | - add feedback function
77 | - redesign UI and interaction
78 |
79 | ##### 2016-07-28
80 | - update a library to fix the bug that seekBar's pointer won't change its position along with its value
81 | - fix a bug that screen filter will be activated unexpectedly when 'restore default settings' button is pressed
82 |
83 | ##### 2016-07-27
84 | - new feature: now you can adjust the screen filter dynamically as long as it is activated
85 | - fix a bug in 'keep screen on' function
86 | - fix a bug that 'restore default settings' function is not working when screen filter is activated
87 | - change background
88 |
89 | ##### 2016-07-26
90 | - new feature: now you can keep screen on when screen filter is activated
91 | - ui improve, more friendly
92 | - several bug fixes
93 |
94 | ##### 2016-07-25
95 | - improve color picker function
96 | - fix a bug that preference of filter color can not be restored
97 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | //noinspection GroovyMissingReturnStatement
4 | android {
5 | compileSdkVersion 25
6 | buildToolsVersion '28.0.3'
7 | //aaptOptions.cruncherEnabled = false
8 | //aaptOptions.useNewCruncher = false
9 |
10 | defaultConfig {
11 | applicationId "com.amastigote.darker"
12 | minSdkVersion 19
13 | targetSdkVersion 25
14 | versionCode 16
15 | versionName "0.2.2"
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 |
24 | lintOptions {
25 | checkReleaseBuilds false
26 | // Or, if you prefer, you can continue to check for errors in release builds,
27 | // but continue the build even when errors are found:
28 | abortOnError false
29 | }
30 | }
31 |
32 | dependencies {
33 | implementation fileTree(include: ['*.jar'], dir: 'libs')
34 | testImplementation 'junit:junit:4.12'
35 | implementation 'com.android.support:appcompat-v7:25.4.0'
36 | implementation 'com.android.support:design:25.4.0'
37 | implementation 'com.android.support:support-v4:25.4.0'
38 | implementation 'me.tankery.lib:circularSeekBar:1.1.7'
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/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\lenovo\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 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/amastigote/darker/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.amastigote.darker;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
15 |
16 |
17 |
18 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/amastigote/darker/activity/AboutActivity.java:
--------------------------------------------------------------------------------
1 | package com.amastigote.darker.activity;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.content.pm.PackageInfo;
6 | import android.content.pm.PackageManager;
7 | import android.net.Uri;
8 | import android.os.Bundle;
9 | import android.support.v7.app.AlertDialog;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.view.MenuItem;
12 | import android.view.View;
13 | import android.widget.Button;
14 | import android.widget.TextView;
15 |
16 | import com.amastigote.darker.R;
17 |
18 | public class AboutActivity extends AppCompatActivity {
19 | TextView versionCodeTextView;
20 | Button licenseButton;
21 | Button feedbackButton;
22 |
23 | public static String getVersionCode(Context context) {
24 | try {
25 | PackageManager packageManager = context.getPackageManager();
26 | PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_GIDS);
27 | return packageInfo.versionName;
28 | } catch (Exception ignored) {
29 | }
30 | return null;
31 | }
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.activity_about);
37 |
38 | if (null != getSupportActionBar()) {
39 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
40 | }
41 |
42 | versionCodeTextView = (TextView) findViewById(R.id.aa_versionCode);
43 | licenseButton = (Button) findViewById(R.id.aa_licenseButton);
44 | feedbackButton = (Button) findViewById(R.id.aa_feedBackButton);
45 |
46 | versionCodeTextView.setText(getVersionCode(AboutActivity.this));
47 |
48 | licenseButton.setOnClickListener(new View.OnClickListener() {
49 | @Override
50 | public void onClick(View view) {
51 | new AlertDialog.Builder(AboutActivity.this)
52 | .setTitle(R.string.license)
53 | .setView(R.layout.activity_license)
54 | .setPositiveButton(R.string.positive, null)
55 | .create()
56 | .show();
57 | }
58 | });
59 |
60 | feedbackButton.setOnClickListener(new View.OnClickListener() {
61 | @Override
62 | public void onClick(View view) {
63 | Intent intent = new Intent(Intent.ACTION_SENDTO);
64 | //noinspection SpellCheckingInspection
65 | intent.setData(Uri.parse("mailto:m@amastigote.com"));
66 | intent.putExtra(Intent.EXTRA_SUBJECT, "Feedback from ScreenFilter " + getVersionCode(AboutActivity.this));
67 | startActivity(intent);
68 | }
69 | });
70 | }
71 |
72 | @Override
73 | public boolean onOptionsItemSelected(MenuItem item) {
74 | if (item.getItemId() == android.R.id.home)
75 | finish();
76 | return super.onOptionsItemSelected(item);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/amastigote/darker/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.amastigote.darker.activity;
2 |
3 | import android.animation.ArgbEvaluator;
4 | import android.animation.ValueAnimator;
5 | import android.annotation.SuppressLint;
6 | import android.content.BroadcastReceiver;
7 | import android.content.Context;
8 | import android.content.DialogInterface;
9 | import android.content.Intent;
10 | import android.content.IntentFilter;
11 | import android.content.res.ColorStateList;
12 | import android.net.Uri;
13 | import android.os.Build;
14 | import android.os.Bundle;
15 | import android.provider.Settings;
16 | import android.support.v4.content.ContextCompat;
17 | import android.support.v7.app.AlertDialog;
18 | import android.support.v7.app.AppCompatActivity;
19 | import android.support.v7.widget.AppCompatButton;
20 | import android.support.v7.widget.Toolbar;
21 | import android.view.KeyEvent;
22 | import android.view.Menu;
23 | import android.view.MenuItem;
24 | import android.view.View;
25 | import android.view.animation.AlphaAnimation;
26 | import android.widget.CompoundButton;
27 | import android.widget.Switch;
28 | import android.widget.TextView;
29 |
30 | import com.amastigote.darker.R;
31 | import com.amastigote.darker.model.DarkerNotification;
32 | import com.amastigote.darker.model.DarkerSettings;
33 | import com.amastigote.darker.service.ScreenFilterService;
34 | import com.rtugeek.android.colorseekbar.ColorSeekBar;
35 |
36 | import me.tankery.lib.circularseekbar.CircularSeekBar;
37 |
38 | public class MainActivity extends AppCompatActivity {
39 | DarkerSettings currentDarkerSettings = new DarkerSettings();
40 | DarkerNotification darkerNotification;
41 | TextView brightness_indicator;
42 | TextView alpha_indicator;
43 | CircularSeekBar circleSeekBar_brightness;
44 | CircularSeekBar circleSeekBar_alpha;
45 | ColorSeekBar colorSeekBar;
46 | Switch aSwitch;
47 | Switch bSwitch;
48 | AppCompatButton appCompatButton;
49 | Intent intent;
50 | View view;
51 | BroadcastReceiver broadcastReceiver;
52 | boolean isServiceRunning = false;
53 |
54 | @Override
55 | protected void onDestroy() {
56 | doCleanBeforeExit();
57 | super.onDestroy();
58 | }
59 |
60 | @Override
61 | protected void onCreate(Bundle savedInstanceState) {
62 | super.onCreate(savedInstanceState);
63 | setContentView(R.layout.activity_main);
64 |
65 | //getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
66 |
67 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
68 | toolbar.setTitle(getResources().getString(R.string.app_name));
69 | toolbar.setTitleMarginStart(100);
70 | toolbar.setLogo(R.mipmap.night_128);
71 | setSupportActionBar(toolbar);
72 |
73 | DarkerSettings.initializeContext(getApplicationContext());
74 |
75 | checkPermissions();
76 |
77 | darkerNotification = new DarkerNotification(MainActivity.this);
78 | darkerNotification.updateStatus(isServiceRunning);
79 |
80 | view = findViewById(R.id.cm);
81 |
82 | circleSeekBar_brightness = (CircularSeekBar) findViewById(R.id.cp_brightness_circleSeekBar);
83 | circleSeekBar_alpha = (CircularSeekBar) findViewById(R.id.cp_alpha_circleSeekBar);
84 |
85 | brightness_indicator = (TextView) findViewById(R.id.cp_brightness_indicator);
86 | alpha_indicator = (TextView) findViewById(R.id.cp_alpha_indicator);
87 |
88 | colorSeekBar = (ColorSeekBar) findViewById(R.id.cp_colorSeekBar);
89 |
90 | aSwitch = (Switch) findViewById(R.id.cp_useColor_switch);
91 | bSwitch = (Switch) findViewById(R.id.cp_useBrightness_switch);
92 |
93 | appCompatButton = (AppCompatButton) findViewById(R.id.cm_toggle_button);
94 |
95 | restoreLatestSettings();
96 |
97 | setButtonState(false);
98 | appCompatButton.setOnClickListener(new View.OnClickListener() {
99 | @Override
100 | public void onClick(View view) {
101 | if (!isServiceRunning) {
102 | collectCurrentDarkerSettings();
103 | setButtonState(true);
104 | isServiceRunning = true;
105 | } else {
106 | ScreenFilterService.removeScreenFilter();
107 | setButtonState(false);
108 | isServiceRunning = false;
109 | }
110 | darkerNotification.updateStatus(isServiceRunning);
111 | }
112 | });
113 |
114 | broadcastReceiver = new BroadcastReceiver() {
115 | @Override
116 | public void onReceive(Context context, Intent intent) {
117 | if (DarkerNotification.PRESS_BUTTON.equals(intent.getAction())) {
118 | if (!isServiceRunning) {
119 | collectCurrentDarkerSettings();
120 | setButtonState(true);
121 | isServiceRunning = true;
122 | } else {
123 | ScreenFilterService.removeScreenFilter();
124 | setButtonState(false);
125 | isServiceRunning = false;
126 | }
127 | darkerNotification.updateStatus(isServiceRunning);
128 | }
129 | }
130 | };
131 |
132 | IntentFilter intentFilter = new IntentFilter();
133 | intentFilter.addAction(DarkerNotification.PRESS_BUTTON);
134 | registerReceiver(broadcastReceiver, intentFilter);
135 |
136 | aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
137 | @Override
138 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
139 | if (isChecked) {
140 | AlphaAnimation alphaAnimation_0 = new AlphaAnimation(0, 1);
141 | alphaAnimation_0.setDuration(300);
142 | colorSeekBar.startAnimation(alphaAnimation_0);
143 | colorSeekBar.setVisibility(View.VISIBLE);
144 | currentDarkerSettings.setUseColor(true);
145 | } else {
146 | AlphaAnimation alphaAnimation_1 = new AlphaAnimation(1, 0);
147 | alphaAnimation_1.setDuration(300);
148 | colorSeekBar.startAnimation(alphaAnimation_1);
149 | colorSeekBar.setVisibility(View.INVISIBLE);
150 | currentDarkerSettings.setUseColor(false);
151 | }
152 | if (isServiceRunning)
153 | collectCurrentDarkerSettings();
154 | }
155 | });
156 |
157 | bSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
158 | @Override
159 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
160 | if (isChecked) {
161 | AlphaAnimation alphaAnimation_0 = new AlphaAnimation(0, 1);
162 | alphaAnimation_0.setDuration(300);
163 | circleSeekBar_brightness.startAnimation(alphaAnimation_0);
164 | circleSeekBar_brightness.setVisibility(View.VISIBLE);
165 | brightness_indicator.setText(String.valueOf((int) circleSeekBar_brightness.getProgress()));
166 | currentDarkerSettings.setUseBrightness(true);
167 | } else {
168 | AlphaAnimation alphaAnimation_1 = new AlphaAnimation(1, 0);
169 | alphaAnimation_1.setDuration(300);
170 | circleSeekBar_brightness.startAnimation(alphaAnimation_1);
171 | circleSeekBar_brightness.setVisibility(View.INVISIBLE);
172 | brightness_indicator.setText(R.string.auto_brightness);
173 | currentDarkerSettings.setUseBrightness(true);
174 | }
175 | if (isServiceRunning)
176 | collectCurrentDarkerSettings();
177 | }
178 | });
179 |
180 | circleSeekBar_brightness.setOnSeekBarChangeListener(new CircularSeekBar.OnCircularSeekBarChangeListener() {
181 | @Override
182 | public void onProgressChanged(CircularSeekBar circularSeekBar, float progress, boolean fromUser) {
183 | brightness_indicator.setText(String.valueOf((int) progress));
184 | if (isServiceRunning)
185 | collectCurrentDarkerSettings();
186 | }
187 |
188 | @Override
189 | public void onStopTrackingTouch(CircularSeekBar seekBar) {
190 | }
191 |
192 | @Override
193 | public void onStartTrackingTouch(CircularSeekBar seekBar) {
194 | }
195 | });
196 |
197 | circleSeekBar_alpha.setOnSeekBarChangeListener(new CircularSeekBar.OnCircularSeekBarChangeListener() {
198 | @Override
199 | public void onProgressChanged(CircularSeekBar circularSeekBar, float progress, boolean fromUser) {
200 | alpha_indicator.setText(String.valueOf((int) progress));
201 | if (isServiceRunning)
202 | collectCurrentDarkerSettings();
203 | }
204 |
205 | @Override
206 | public void onStopTrackingTouch(CircularSeekBar seekBar) {
207 | }
208 |
209 | @Override
210 | public void onStartTrackingTouch(CircularSeekBar seekBar) {
211 | }
212 | });
213 |
214 | colorSeekBar.setOnColorChangeListener(new ColorSeekBar.OnColorChangeListener() {
215 | @Override
216 | public void onColorChangeListener(int i, int i1, int i2) {
217 | if (isServiceRunning)
218 | collectCurrentDarkerSettings();
219 | }
220 | });
221 | }
222 |
223 | @Override
224 | public boolean onCreateOptionsMenu(Menu menu) {
225 | getMenuInflater().inflate(R.menu.menu_main, menu);
226 | return true;
227 | }
228 |
229 | @Override
230 | public boolean onOptionsItemSelected(MenuItem item) {
231 | int id = item.getItemId();
232 | if (id == R.id.action_about)
233 | startActivity(new Intent(MainActivity.this, AboutActivity.class));
234 | else if (id == R.id.action_restoreDefaultSettings) {
235 | new AlertDialog.Builder(MainActivity.this)
236 | .setTitle("重置配置面板")
237 | .setMessage("将覆盖您的偏好配置并恢复为推荐配置")
238 | .setPositiveButton("确认重置", new DialogInterface.OnClickListener() {
239 | @Override
240 | public void onClick(DialogInterface dialogInterface, int i) {
241 | currentDarkerSettings = DarkerSettings.getDefaultSettings();
242 | if (isServiceRunning) {
243 | doRestore();
244 | collectCurrentDarkerSettings();
245 | } else
246 | doRestore();
247 | }
248 | })
249 | .setNegativeButton("取消", null)
250 | .show();
251 | }
252 | return super.onOptionsItemSelected(item);
253 | }
254 |
255 | @SuppressLint("RestrictedApi")
256 | private void setButtonState(boolean isChecked) {
257 | if (isChecked) {
258 | final ValueAnimator valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(),
259 | ContextCompat.getColor(this, R.color.toggle_button_off),
260 | ContextCompat.getColor(this, R.color.toggle_button_on));
261 | valueAnimator.setDuration(500);
262 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
263 | @Override
264 | public void onAnimationUpdate(ValueAnimator animation) {
265 | int trans_color = (int) valueAnimator.getAnimatedValue();
266 | appCompatButton.setSupportBackgroundTintList(
267 | ColorStateList.valueOf(trans_color));
268 | }
269 | });
270 | valueAnimator.start();
271 | appCompatButton.setText(getResources().getString(R.string.is_on));
272 | } else {
273 | final ValueAnimator valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(),
274 | ContextCompat.getColor(this, R.color.toggle_button_on),
275 | ContextCompat.getColor(this, R.color.toggle_button_off));
276 | valueAnimator.setDuration(500);
277 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
278 | @Override
279 | public void onAnimationUpdate(ValueAnimator animation) {
280 | int trans_color = (int) valueAnimator.getAnimatedValue();
281 | appCompatButton.setSupportBackgroundTintList(
282 | ColorStateList.valueOf(trans_color));
283 | }
284 | });
285 | valueAnimator.start();
286 | appCompatButton.setText(getResources().getString(R.string.is_off));
287 | }
288 | }
289 |
290 | private void doRestore() {
291 | {
292 | boolean isCurrentServiceRunning = false;
293 | if (isServiceRunning) {
294 | isCurrentServiceRunning = true;
295 | isServiceRunning = false;
296 | }
297 | circleSeekBar_brightness.setProgress(currentDarkerSettings.getBrightness() * 100);
298 | circleSeekBar_alpha.setProgress(currentDarkerSettings.getAlpha() * 100);
299 | if (isCurrentServiceRunning)
300 | isServiceRunning = true;
301 | }
302 |
303 | if (aSwitch.isChecked()) {
304 | aSwitch.setChecked(false);
305 | AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
306 | alphaAnimation.setDuration(300);
307 | colorSeekBar.startAnimation(alphaAnimation);
308 | colorSeekBar.setVisibility(View.INVISIBLE);
309 | }
310 |
311 | if (bSwitch.isChecked()) {
312 | bSwitch.setChecked(false);
313 | AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
314 | alphaAnimation.setDuration(300);
315 | circleSeekBar_brightness.startAnimation(alphaAnimation);
316 | circleSeekBar_brightness.setVisibility(View.INVISIBLE);
317 | brightness_indicator.setText(R.string.auto_brightness);
318 | }
319 | invalidateOptionsMenu();
320 | }
321 |
322 | private void collectCurrentDarkerSettings() {
323 | currentDarkerSettings.setBrightness(circleSeekBar_brightness.getProgress() / 100);
324 | currentDarkerSettings.setAlpha(circleSeekBar_alpha.getProgress() / 100);
325 | currentDarkerSettings.setUseColor(aSwitch.isChecked());
326 | currentDarkerSettings.setUseBrightness(bSwitch.isChecked());
327 | currentDarkerSettings.setColorBarPosition(colorSeekBar.getColorPosition());
328 | currentDarkerSettings.setColor(colorSeekBar.getColor());
329 | currentDarkerSettings.saveCurrentSettings();
330 |
331 | if (isServiceRunning)
332 | ScreenFilterService.updateScreenFilter(currentDarkerSettings);
333 | else {
334 | try {
335 | ScreenFilterService.activateScreenFilter(currentDarkerSettings);
336 | } catch (IllegalStateException ignored) {
337 | }
338 | }
339 | }
340 |
341 | private void restoreLatestSettings() {
342 | currentDarkerSettings = DarkerSettings.getCurrentSettings();
343 | circleSeekBar_brightness.setProgress(currentDarkerSettings.getBrightness() * 100);
344 | circleSeekBar_alpha.setProgress(currentDarkerSettings.getAlpha() * 100);
345 | brightness_indicator.setText(String.valueOf((int) circleSeekBar_brightness.getProgress()));
346 | alpha_indicator.setText(String.valueOf((int) circleSeekBar_alpha.getProgress()));
347 | if (currentDarkerSettings.isUseColor()) {
348 | aSwitch.setChecked(true);
349 | colorSeekBar.setVisibility(View.VISIBLE);
350 | } else {
351 | aSwitch.setChecked(false);
352 | colorSeekBar.setVisibility(View.INVISIBLE);
353 | }
354 | if (currentDarkerSettings.isUseBrightness()) {
355 | bSwitch.setChecked(true);
356 | circleSeekBar_brightness.setVisibility(View.VISIBLE);
357 | } else {
358 | bSwitch.setChecked(false);
359 | circleSeekBar_brightness.setVisibility(View.INVISIBLE);
360 | brightness_indicator.setText(R.string.auto_brightness);
361 | }
362 | colorSeekBar.setColorBarValue((int) currentDarkerSettings.getColorBarPosition());
363 | }
364 |
365 | @Override
366 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
367 | if (requestCode == 0) {
368 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
369 | if (Settings.canDrawOverlays(this))
370 | prepareForService();
371 | else {
372 | doCleanBeforeExit();
373 | finish();
374 | System.exit(0);
375 | }
376 | }
377 | }
378 | super.onActivityResult(requestCode, resultCode, data);
379 | }
380 |
381 | @Override
382 | public boolean onKeyDown(int keyCode, KeyEvent event) {
383 | if (keyCode == KeyEvent.KEYCODE_BACK)
384 | moveTaskToBack(true);
385 | return super.onKeyDown(keyCode, event);
386 | }
387 |
388 | private void checkPermissions() {
389 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
390 | if (!Settings.canDrawOverlays(getApplicationContext())) {
391 | Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
392 | intent.setData(Uri.parse("package:" + getPackageName()));
393 | startActivityForResult(intent, 0);
394 | } else
395 | prepareForService();
396 | } else
397 | prepareForService();
398 | }
399 |
400 | private void prepareForService() {
401 | intent = new Intent(getApplicationContext(), ScreenFilterService.class);
402 | /*Display display = getWindowManager().getDefaultDisplay();
403 | Point point = new Point();
404 | display.getSize(point);
405 | intent.putExtra("height",point.y);*/
406 | startService(intent);
407 | }
408 |
409 | private void doCleanBeforeExit() {
410 | try {
411 | darkerNotification.removeNotification();
412 | unregisterReceiver(broadcastReceiver);
413 | stopService(intent);
414 | } catch (Exception ignored) {
415 | }
416 | }
417 | }
418 |
--------------------------------------------------------------------------------
/app/src/main/java/com/amastigote/darker/model/DarkerNotification.java:
--------------------------------------------------------------------------------
1 | package com.amastigote.darker.model;
2 |
3 | import android.app.Notification;
4 | import android.app.NotificationManager;
5 | import android.app.PendingIntent;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.support.v4.app.NotificationCompat;
9 |
10 | import com.amastigote.darker.R;
11 | import com.amastigote.darker.activity.MainActivity;
12 |
13 | public class DarkerNotification {
14 | private static NotificationManager notificationManager;
15 | private static NotificationCompat.Builder builder;
16 | private final static String IS_ON = "滤镜已激活 (•̀ᴗ•́)و";
17 | private final static String IS_OFF = "滤镜未激活 (˘•_•˘)";
18 | private final static String CLICK_TO_ACTIVATE = "轻触可启用";
19 | private final static String CLICK_TO_DEACTIVATE = "轻触可关闭";
20 | private final static String OPEN_PANEL = "设置面板";
21 | public final static String PRESS_BUTTON = "PRESS_BUTTON";
22 |
23 | public DarkerNotification(Context context) {
24 | notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
25 | builder = new NotificationCompat.Builder(context)
26 | .setSmallIcon(R.mipmap.night_128)
27 | .setAutoCancel(false);
28 | PendingIntent settingsPendingIntent = PendingIntent.getActivity(
29 | context,
30 | 0,
31 | new Intent(context, MainActivity.class),
32 | 0);
33 | builder.addAction(R.mipmap.ic_settings_white_24dp, OPEN_PANEL, settingsPendingIntent);
34 | PendingIntent changeStatusPendingIntent = PendingIntent.getBroadcast(
35 | context,
36 | 0,
37 | new Intent(PRESS_BUTTON),
38 | 0);
39 | builder.setContentIntent(changeStatusPendingIntent);
40 | }
41 |
42 | public void updateStatus(boolean isRunning) {
43 | if (isRunning) {
44 | builder.setContentTitle(IS_ON)
45 | .setContentText(CLICK_TO_DEACTIVATE);
46 | } else {
47 | builder.setContentTitle(IS_OFF)
48 | .setContentText(CLICK_TO_ACTIVATE);
49 | }
50 | Notification notification = builder.build();
51 | notification.flags |= Notification.FLAG_NO_CLEAR;
52 | notificationManager.notify(R.string.app_name, notification);
53 | }
54 |
55 | public void removeNotification() {
56 | notificationManager.cancel(R.string.app_name);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/src/main/java/com/amastigote/darker/model/DarkerSettings.java:
--------------------------------------------------------------------------------
1 | package com.amastigote.darker.model;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 | import android.view.WindowManager;
7 |
8 | public class DarkerSettings {
9 | private float brightness;
10 | private float alpha;
11 | private boolean useColor;
12 | private boolean useBrightness;
13 | private boolean useBar;
14 | private float colorBarPosition;
15 | private int color;
16 |
17 | @SuppressLint("StaticFieldLeak")
18 | private static Context context = null;
19 | private static SharedPreferences sharedPreferences_default = null;
20 | private static SharedPreferences sharedPreferences_current = null;
21 | private static final String BRIGHTNESS = "BRIGHTNESS";
22 | private static final String ALPHA = "ALPHA";
23 | private static final String COLOR_BAR_POSITION = "COLOR_BAR_POSITION";
24 | private static final String USE_COLOR = "USE_COLOR";
25 | private static final String USE_BRIGHTNESS = "USE_BRIGHTNESS";
26 | private static final float ALPHA_DEFAULT = 0.4F;
27 | private static final float COLOR_BAR_POSITION_DEFAULT = 0.0F;
28 | private static final boolean USE_STH_DEFAULT = false;
29 |
30 | public static void initializeContext(Context context) {
31 | DarkerSettings.context = context;
32 | initializeSharedPreferences();
33 | }
34 |
35 | private static void initializeSharedPreferences() {
36 | sharedPreferences_default = DarkerSettings.context
37 | .getSharedPreferences("user_settings_default",
38 | Context.MODE_PRIVATE);
39 | sharedPreferences_current = DarkerSettings.context
40 | .getSharedPreferences("user_settings_current",
41 | Context.MODE_PRIVATE);
42 | }
43 |
44 | public DarkerSettings() {
45 | }
46 |
47 | public static DarkerSettings getDefaultSettings() {
48 | return getSettings(sharedPreferences_default);
49 | }
50 |
51 | public static DarkerSettings getCurrentSettings() {
52 | return getSettings(sharedPreferences_current);
53 | }
54 |
55 | private static DarkerSettings getSettings(SharedPreferences sharedPreferences) {
56 | DarkerSettings thisDarkerSettings = new DarkerSettings();
57 |
58 | float thisBrightness = sharedPreferences.getFloat(BRIGHTNESS,
59 | WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF);
60 | float thisAlpha = sharedPreferences.getFloat(ALPHA,
61 | ALPHA_DEFAULT);
62 | float thisColorBarPosition = sharedPreferences.getFloat(COLOR_BAR_POSITION,
63 | COLOR_BAR_POSITION_DEFAULT);
64 | boolean thisUseColor = sharedPreferences.getBoolean(USE_COLOR,
65 | USE_STH_DEFAULT);
66 | boolean thisUseBrightness = sharedPreferences.getBoolean(USE_BRIGHTNESS,
67 | USE_STH_DEFAULT);
68 |
69 | thisDarkerSettings.setBrightness(thisBrightness);
70 | thisDarkerSettings.setAlpha(thisAlpha);
71 | thisDarkerSettings.setColorBarPosition(thisColorBarPosition);
72 | thisDarkerSettings.setUseColor(thisUseColor);
73 | thisDarkerSettings.setUseBrightness(thisUseBrightness);
74 |
75 | return thisDarkerSettings;
76 | }
77 |
78 | public void setBrightness(float brightness) {
79 | this.brightness = brightness;
80 | }
81 |
82 | public void setAlpha(float alpha) {
83 | this.alpha = alpha;
84 | }
85 |
86 | public float getColorBarPosition() {
87 | return colorBarPosition;
88 | }
89 |
90 | public void setColorBarPosition(float colorBarPosition) {
91 | this.colorBarPosition = colorBarPosition;
92 | }
93 |
94 | public void setUseColor(boolean useColor) {
95 | this.useColor = useColor;
96 | }
97 |
98 | public float getBrightness() {
99 | return brightness;
100 | }
101 |
102 | public float getAlpha() {
103 | return alpha;
104 | }
105 |
106 | public boolean isUseColor() {
107 | return useColor;
108 | }
109 |
110 | public int getColor() {
111 | return color;
112 | }
113 |
114 | public void setColor(int color) {
115 | this.color = color;
116 | }
117 |
118 | public boolean isUseBrightness() {
119 | return useBrightness;
120 | }
121 |
122 | public void setUseBrightness(boolean useBrightness) {
123 | this.useBrightness = useBrightness;
124 | }
125 |
126 | public void saveCurrentSettings() {
127 | SharedPreferences.Editor editor = sharedPreferences_current.edit();
128 | editor.putFloat(BRIGHTNESS, brightness);
129 | editor.putFloat(ALPHA, alpha);
130 | editor.putFloat(COLOR_BAR_POSITION, colorBarPosition);
131 | editor.putBoolean(USE_BRIGHTNESS, useBrightness);
132 | editor.putBoolean(USE_COLOR, useColor);
133 | editor.apply();
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/app/src/main/java/com/amastigote/darker/service/ScreenFilterService.java:
--------------------------------------------------------------------------------
1 | package com.amastigote.darker.service;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Service;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.graphics.Color;
8 | import android.graphics.PixelFormat;
9 | import android.os.IBinder;
10 | import android.support.annotation.Nullable;
11 | import android.util.DisplayMetrics;
12 | import android.view.LayoutInflater;
13 | import android.view.WindowManager;
14 | import android.widget.LinearLayout;
15 |
16 | import com.amastigote.darker.R;
17 | import com.amastigote.darker.model.DarkerSettings;
18 |
19 | //import android.support.v7.app.AppCompatActivity;
20 | //import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompatApi21.getWindow;
21 |
22 | public class ScreenFilterService extends Service {
23 | @SuppressLint("StaticFieldLeak")
24 | static LinearLayout linearLayout;
25 | static WindowManager.LayoutParams layoutParams;
26 | static WindowManager windowManager;
27 |
28 | @Override
29 | public void onCreate() {
30 | super.onCreate();
31 | createScreenFilter();
32 | }
33 |
34 | @Override
35 | public int onStartCommand(Intent intent, int flags, int startId) {
36 | return START_STICKY;
37 | }
38 |
39 | @Override
40 | public void onDestroy() {
41 | super.onDestroy();
42 | try {
43 | windowManager.removeViewImmediate(linearLayout);
44 | } catch (Exception ignored) {
45 | }
46 | }
47 |
48 | @Nullable
49 | @Override
50 | public IBinder onBind(Intent intent) {
51 | return null;
52 | }
53 |
54 | @SuppressWarnings(value = "all")
55 | private void createScreenFilter() {
56 | WindowManager windowManager_tmp = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
57 | layoutParams = new WindowManager.LayoutParams();
58 | windowManager = (WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE);
59 | layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
60 |
61 | int temp = getNavigationBarHeight(getApplicationContext());
62 | DisplayMetrics metrics = new DisplayMetrics();
63 | windowManager_tmp.getDefaultDisplay().getRealMetrics(metrics);
64 | layoutParams.width = metrics.heightPixels + temp;
65 | layoutParams.height = metrics.heightPixels + temp;
66 |
67 | layoutParams.format = PixelFormat.TRANSLUCENT;
68 |
69 | LayoutInflater layoutInflater = LayoutInflater.from(getApplication());
70 | linearLayout = (LinearLayout) layoutInflater.inflate(R.layout.screen_filter, null);
71 | }
72 |
73 | public static int getNavigationBarHeight(Context context) {
74 | int resourceId = 0;
75 | int rid = context.getResources().getIdentifier("config_showNavigationBar", "bool", "android");
76 | if (rid != 0) {
77 | resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
78 | return context.getResources().getDimensionPixelSize(resourceId);
79 | } else
80 | return 0;
81 | }
82 |
83 | public static void updateScreenFilter(DarkerSettings darkerSettings) {
84 | updateThisSettings(darkerSettings);
85 | windowManager.updateViewLayout(linearLayout, layoutParams);
86 | }
87 |
88 | public static void activateScreenFilter(DarkerSettings darkerSettings) {
89 | updateThisSettings(darkerSettings);
90 | windowManager.addView(linearLayout, layoutParams);
91 | }
92 |
93 | private static void updateThisSettings(DarkerSettings darkerSettings) {
94 | if (darkerSettings.isUseBrightness())
95 | layoutParams.screenBrightness = darkerSettings.getBrightness();
96 | else
97 | layoutParams.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
98 |
99 | layoutParams.alpha = darkerSettings.getAlpha();
100 |
101 | if (darkerSettings.isUseColor())
102 | linearLayout.setBackgroundColor(darkerSettings.getColor());
103 | else
104 | linearLayout.setBackgroundColor(Color.BLACK);
105 |
106 | layoutParams.flags =
107 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
108 | | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
109 | | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
110 | // | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
111 | | WindowManager.LayoutParams.FLAG_FULLSCREEN
112 | | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
113 | }
114 |
115 | public static void removeScreenFilter() {
116 | windowManager.removeViewImmediate(linearLayout);
117 | }
118 | /*
119 | protected void hideBottomUIMenu() {
120 | if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
121 | View v = this.getWindow().getDecorView();
122 | v.setSystemUiVisibility(View.GONE);
123 | } else if (Build.VERSION.SDK_INT >= 19) {
124 | //for new api versions.
125 | View decorView = getWindow().getDecorView();
126 | int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
127 | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN;
128 | decorView.setSystemUiVisibility(uiOptions);
129 | }
130 | }*/
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rtugeek/android/colorseekbar/ColorSeekBar.java:
--------------------------------------------------------------------------------
1 | package com.rtugeek.android.colorseekbar;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Bitmap;
6 | import android.graphics.Canvas;
7 | import android.graphics.Color;
8 | import android.graphics.LinearGradient;
9 | import android.graphics.Paint;
10 | import android.graphics.Rect;
11 | import android.graphics.RectF;
12 | import android.graphics.Shader;
13 | import android.util.AttributeSet;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 |
17 | import com.amastigote.darker.R;
18 |
19 | @SuppressWarnings(value = "all")
20 | public class ColorSeekBar extends View {
21 | private int mBackgroundColor = 0xffffffff;
22 | private int[] mColors = new int[]{0xFF000000, 0xFF9900FF, 0xFF0000FF, 0xFF00FF00, 0xFF00FFFF, 0xFFFF0000, 0xFFFF00FF, 0xFFFF6600, 0xFFFFFF00, 0xFFFFFFFF, 0xFF000000};
23 | private int c0, c1, mAlpha, mRed, mGreen, mBlue;
24 | private float x, y;
25 | private OnColorChangeListener mOnColorChangeLister;
26 | private Context mContext;
27 | private boolean mIsShowAlphaBar = false;
28 | private Bitmap mTransparentBitmap;
29 | private boolean mMovingColorBar;
30 | private boolean mMovingAlphaBar;
31 | private Rect mColorRect;
32 | private int mThumbHeight = 20;
33 | private int mBarHeight = 2;
34 | private LinearGradient mColorGradient;
35 | private Paint mColorRectPaint;
36 | private int realLeft;
37 | private int realRight;
38 | private int realTop;
39 | private int realBottom;
40 | private int mBarWidth;
41 | private int mMaxValue;
42 | private Rect mAlphaRect;
43 | private int mColorBarValue;
44 | private int mAlphaBarValue;
45 | private float mThumbRadius;
46 | private int mBarMargin = 5;
47 | private int mPaddingSize;
48 | private int mViewWidth;
49 | private int mViewHeight;
50 |
51 | public ColorSeekBar(Context context) {
52 | super(context);
53 | init(context, null, 0, 0);
54 | }
55 |
56 | public ColorSeekBar(Context context, AttributeSet attrs) {
57 | super(context, attrs);
58 | init(context, attrs, 0, 0);
59 | }
60 |
61 | public ColorSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
62 | super(context, attrs, defStyleAttr);
63 | init(context, attrs, defStyleAttr, 0);
64 | }
65 |
66 | // @TargetApi(Build.VERSION_CODES.LOLLIPOP)
67 | // public ColorSeekBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
68 | // super(context, attrs, defStyleAttr, defStyleRes);
69 | // init(context, attrs, defStyleAttr, defStyleRes);
70 | // }
71 |
72 | protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
73 | applyStyle(context, attrs, defStyleAttr, defStyleRes);
74 | }
75 |
76 | // public void applyStyle(int resId){
77 | // applyStyle(getContext(), null, 0, resId);
78 | // }
79 |
80 | @Override
81 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
82 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
83 | mViewWidth = widthMeasureSpec;
84 | mViewHeight = heightMeasureSpec;
85 |
86 | int speMode = MeasureSpec.getMode(heightMeasureSpec);
87 | if (speMode == MeasureSpec.AT_MOST || speMode == MeasureSpec.UNSPECIFIED) {
88 | if (mIsShowAlphaBar) {
89 | setMeasuredDimension(mViewWidth, mThumbHeight * 2 + mBarHeight * 2 + mBarMargin);
90 | } else {
91 | setMeasuredDimension(mViewWidth, mThumbHeight + mBarHeight);
92 | }
93 | }
94 | }
95 |
96 |
97 | protected void applyStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
98 | mContext = context;
99 | //get attributes
100 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ColorSeekBar, defStyleAttr, defStyleRes);
101 | int colorsId = a.getResourceId(R.styleable.ColorSeekBar_colors, 0);
102 | mMaxValue = a.getInteger(R.styleable.ColorSeekBar_maxValue, 100);
103 | mColorBarValue = a.getInteger(R.styleable.ColorSeekBar_colorBarValue, 0);
104 | mAlphaBarValue = a.getInteger(R.styleable.ColorSeekBar_alphaBarValue, 0);
105 | mIsShowAlphaBar = a.getBoolean(R.styleable.ColorSeekBar_showAlphaBar, false);
106 | mBackgroundColor = a.getColor(R.styleable.ColorSeekBar_bgColor, Color.TRANSPARENT);
107 | mBarHeight = (int) a.getDimension(R.styleable.ColorSeekBar_barHeight, (float) dp2px(2));
108 | mThumbHeight = (int) a.getDimension(R.styleable.ColorSeekBar_thumbHeight, (float) dp2px(30));
109 | mBarMargin = (int) a.getDimension(R.styleable.ColorSeekBar_barMargin, (float) dp2px(5));
110 | a.recycle();
111 |
112 | if (colorsId != 0) mColors = getColorsById(colorsId);
113 |
114 | setBackgroundColor(mBackgroundColor);
115 |
116 | init();
117 |
118 | //init color
119 | pickColor(mColorBarValue);
120 | setAlphaValue();
121 |
122 | }
123 |
124 | private int[] getColorsById(int id) {
125 | if (isInEditMode()) {
126 | String[] s = mContext.getResources().getStringArray(id);
127 | int[] colors = new int[s.length];
128 | for (int j = 0; j < s.length; j++) {
129 | colors[j] = Color.parseColor(s[j]);
130 | }
131 | return colors;
132 | } else {
133 | TypedArray typedArray = mContext.getResources().obtainTypedArray(id);
134 | int[] colors = new int[typedArray.length()];
135 | for (int j = 0; j < typedArray.length(); j++) {
136 | colors[j] = typedArray.getColor(j, Color.BLACK);
137 | }
138 | typedArray.recycle();
139 | return colors;
140 | }
141 | }
142 |
143 | private void init() {
144 | //init l r t b
145 | realLeft = getPaddingLeft() + mPaddingSize;
146 | realRight = getWidth() - getPaddingRight() - mPaddingSize;
147 | realTop = getPaddingTop() + mPaddingSize;
148 | realBottom = getHeight() - getPaddingBottom() - mPaddingSize;
149 |
150 | //init size
151 | mThumbRadius = mThumbHeight / 2;
152 | mPaddingSize = (int) mThumbRadius;
153 | mBarWidth = realRight - realLeft;
154 |
155 | //init rect
156 | mColorRect = new Rect(realLeft, realTop, realRight, realTop + mBarHeight);
157 |
158 | //init paint
159 | mColorGradient = new LinearGradient(0, 0, mColorRect.width(), 0, mColors, null, Shader.TileMode.MIRROR);
160 | mColorRectPaint = new Paint();
161 | mColorRectPaint.setShader(mColorGradient);
162 | mColorRectPaint.setAntiAlias(true);
163 |
164 | }
165 |
166 | @Override
167 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
168 | super.onSizeChanged(w, h, oldw, oldh);
169 | mTransparentBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);
170 | mTransparentBitmap.eraseColor(Color.TRANSPARENT);
171 | }
172 |
173 |
174 | // public ColorSeekBar(Context context, float x1, float x2) {
175 | // super(context);
176 | // }
177 |
178 | @Override
179 | protected void onDraw(Canvas canvas) {
180 | init();
181 | float colorPosition = (float) mColorBarValue / mMaxValue * mBarWidth;
182 |
183 | Paint colorPaint = new Paint();
184 | colorPaint.setAntiAlias(true);
185 | colorPaint.setColor(pickColor(colorPosition));
186 | // int[] toAlpha=new int[]{Color.argb(255, mRed, mGreen, mBlue),Color.argb(0, mRed, mGreen, mBlue)};
187 | //clear
188 | canvas.drawBitmap(mTransparentBitmap, 0, 0, null);
189 |
190 | //draw color bar
191 | // canvas.drawRect(mColorRect, mColorRectPaint);
192 | canvas.drawRoundRect(new RectF(mColorRect), mBarHeight / 2, mBarHeight / 2, mColorRectPaint);
193 |
194 | //draw color bar thumb
195 | float thumbX = colorPosition + realLeft;
196 | float thumbY = mColorRect.top + mColorRect.height() / 2;
197 | canvas.drawCircle(thumbX, thumbY, mBarHeight, colorPaint);
198 |
199 | // //draw color bar thumb radial gradient shader
200 | // RadialGradient thumbShader = new RadialGradient(thumbX, thumbY, mThumbRadius, toAlpha, null, Shader.TileMode.MIRROR);
201 | // Paint thumbGradientPaint = new Paint();
202 | // thumbGradientPaint.setAntiAlias(true);
203 | // thumbGradientPaint.setShader(thumbShader);
204 | // canvas.drawCircle(thumbX, thumbY, mThumbHeight / 2, thumbGradientPaint);
205 |
206 | // if(mIsShowAlphaBar){
207 | //
208 | // //init rect
209 | // int top = (int)(mThumbHeight+ mThumbRadius + mBarHeight + mBarMargin);
210 | // mAlphaRect = new Rect(realLeft,top,realRight,top + mBarHeight);
211 | //
212 | // //draw alpha bar
213 | // Paint alphaBarPaint = new Paint();
214 | // alphaBarPaint.setAntiAlias(true);
215 | // LinearGradient alphaBarShader = new LinearGradient(0, 0, mAlphaRect.width(), 0, toAlpha, null, Shader.TileMode.MIRROR);
216 | // alphaBarPaint.setShader(alphaBarShader);
217 | // canvas.drawRect(mAlphaRect,alphaBarPaint);
218 | //
219 | // //draw alpha bar thumb
220 | // float alphaPosition = (float) mAlphaBarValue / 255 * mBarWidth;
221 | // float alphaThumbX = alphaPosition + realLeft;
222 | // float alphaThumbY = mAlphaRect.top + mAlphaRect.height() / 2;
223 | // canvas.drawCircle(alphaThumbX, alphaThumbY, mBarHeight / 2 + 5, colorPaint);
224 | //
225 | // //draw alpha bar thumb radial gradient shader
226 | // RadialGradient alphaThumbShader = new RadialGradient(alphaThumbX, alphaThumbY, mThumbRadius, toAlpha, null, Shader.TileMode.MIRROR);
227 | // Paint alphaThumbGradientPaint = new Paint();
228 | // alphaThumbGradientPaint.setAntiAlias(true);
229 | // alphaThumbGradientPaint.setShader(alphaThumbShader);
230 | // canvas.drawCircle(alphaThumbX,alphaThumbY, mThumbHeight/2, alphaThumbGradientPaint);
231 | // }
232 |
233 | super.onDraw(canvas);
234 | }
235 |
236 |
237 | @Override
238 | public boolean onTouchEvent(MotionEvent event) {
239 | x = event.getX();
240 | y = event.getY();
241 | switch (event.getAction()) {
242 | case MotionEvent.ACTION_DOWN:
243 | if (isOnBar(mColorRect, x, y)) {
244 | mMovingColorBar = true;
245 | } else if (mIsShowAlphaBar) {
246 | if (isOnBar(mAlphaRect, x, y)) {
247 | mMovingAlphaBar = true;
248 | }
249 | }
250 | break;
251 | case MotionEvent.ACTION_MOVE:
252 | getParent().requestDisallowInterceptTouchEvent(true);
253 | if (mMovingColorBar) {
254 | float value = (x - realLeft) / mBarWidth * mMaxValue;
255 | mColorBarValue = (int) value;
256 | if (mColorBarValue < 0) mColorBarValue = 0;
257 | if (mColorBarValue > mMaxValue) mColorBarValue = mMaxValue;
258 | } else if (mIsShowAlphaBar) {
259 | if (mMovingAlphaBar) {
260 | float value = (x - realLeft) / mBarWidth * 255;
261 | mAlphaBarValue = (int) value;
262 | if (mAlphaBarValue < 0) mAlphaBarValue = 0;
263 | if (mAlphaBarValue > 255) mAlphaBarValue = 255;
264 | setAlphaValue();
265 | }
266 | }
267 | if (mOnColorChangeLister != null && (mMovingAlphaBar || mMovingColorBar))
268 | mOnColorChangeLister.onColorChangeListener(mColorBarValue, mAlphaBarValue, getColor());
269 | invalidate();
270 | break;
271 | case MotionEvent.ACTION_UP:
272 | mMovingColorBar = false;
273 | mMovingAlphaBar = false;
274 | break;
275 | }
276 | return true;
277 | }
278 |
279 | private boolean isOnBar(Rect r, float x, float y) {
280 | return r.left - mThumbRadius < x && x < r.right + mThumbRadius && r.top - mThumbRadius < y && y < r.bottom + mThumbRadius;
281 | }
282 |
283 | private int pickColor(float position) {
284 | float unit = position / mBarWidth;
285 | if (unit <= 0.0)
286 | return mColors[0];
287 |
288 | if (unit >= 1)
289 | return mColors[mColors.length - 1];
290 |
291 | float colorPosition = unit * (mColors.length - 1);
292 | int i = (int) colorPosition;
293 | colorPosition -= i;
294 | c0 = mColors[i];
295 | c1 = mColors[i + 1];
296 | // mAlpha = mix(Color.alpha(c0), Color.alpha(c1), colorPosition);
297 | mRed = mix(Color.red(c0), Color.red(c1), colorPosition);
298 | mGreen = mix(Color.green(c0), Color.green(c1), colorPosition);
299 | mBlue = mix(Color.blue(c0), Color.blue(c1), colorPosition);
300 | return Color.rgb(mRed, mGreen, mBlue);
301 | }
302 |
303 | private int mix(int start, int end, float position) {
304 | return start + Math.round(position * (end - start));
305 | }
306 |
307 | public int getColor() {
308 | if (mIsShowAlphaBar) return Color.argb(mAlpha, mRed, mGreen, mBlue);
309 | return Color.rgb(mRed, mGreen, mBlue);
310 | }
311 |
312 | //
313 | // public int getAlphaValue(){
314 | // return mAlpha;
315 | // }
316 | //
317 | //
318 | // /**
319 | // * @return color with alpha value
320 | // */
321 | // public int getColorWithAlpha(){
322 | // return Color.argb(mAlpha, mRed, mGreen, mBlue);
323 | // }
324 |
325 |
326 | public interface OnColorChangeListener {
327 | /**
328 | * @param colorBarValue between 0-maxValue
329 | * @param alphaValue between 0-255
330 | * @param color return the color contains alpha value whether showAlphaBar is true or without alpha value
331 | */
332 | void onColorChangeListener(int colorBarValue, int alphaValue, int color);
333 | }
334 |
335 | public void setOnColorChangeListener(OnColorChangeListener onColorChangeListener) {
336 | this.mOnColorChangeLister = onColorChangeListener;
337 | }
338 |
339 |
340 | public int dp2px(float dpValue) {
341 | final float scale = mContext.getResources().getDisplayMetrics().density;
342 | return (int) (dpValue * scale + 0.5f);
343 | }
344 |
345 | // /**
346 | // * Set colors by resource id. The resource's type must be color
347 | // * @param resId
348 | // */
349 | // public void setColors(int resId){
350 | // setColors(getColorsById(resId));
351 | // }
352 | //
353 | // public void setColors(int[] colors){
354 | // mColors = colors;
355 | // invalidate();
356 | // setAlphaValue();
357 | // if(mOnColorChangeLister != null)
358 | // mOnColorChangeLister.onColorChangeListener(mColorBarValue, mAlphaBarValue,getColor());
359 | // }
360 | //
361 | // public int[] getColors(){
362 | // return mColors;
363 | // }
364 | //
365 | // public boolean isShowAlphaBar(){
366 | // return mIsShowAlphaBar;
367 | // }
368 | //
369 | // private void refreshLayoutParams(){
370 | // mThumbHeight = mThumbHeight < 2? 2:mThumbHeight;
371 | // mBarHeight = mBarHeight < 2? 2:mBarHeight;
372 | //
373 | // int singleHeight = mThumbHeight + mBarHeight;
374 | // int doubleHeight = mThumbHeight *2 + mBarHeight * 2 + mBarMargin;
375 | //
376 | // if(getLayoutParams().height == -2) {
377 | // if(mIsShowAlphaBar){
378 | // getLayoutParams().height = doubleHeight;
379 | // setLayoutParams(getLayoutParams());
380 | // }else{
381 | // getLayoutParams().height = singleHeight ;
382 | // setLayoutParams(getLayoutParams());
383 | // }
384 | // }else if (getLayoutParams().height >= 0){
385 | // if(mIsShowAlphaBar){
386 | // getLayoutParams().height = doubleHeight;
387 | // setLayoutParams(getLayoutParams());
388 | // }else{
389 | // getLayoutParams().height = singleHeight;
390 | // setLayoutParams(getLayoutParams());
391 | // }
392 | // }
393 | // }
394 | //
395 | // public void setShowAlphaBar(boolean show){
396 | // mIsShowAlphaBar = show;
397 | // refreshLayoutParams();
398 | // invalidate();
399 | // if(mOnColorChangeLister != null)
400 | // mOnColorChangeLister.onColorChangeListener(mColorBarValue, mAlphaBarValue,getColor());
401 | // }
402 | //
403 | // /**
404 | // * @param dp
405 | // */
406 | // public void setBarHeight(float dp){
407 | // mBarHeight = dp2px(dp);
408 | // refreshLayoutParams();
409 | // invalidate();
410 | // }
411 | //
412 | // /**
413 | // * @param px
414 | // */
415 | // public void setBarHeightPx(int px){
416 | // mBarHeight = px;
417 | // refreshLayoutParams();
418 | // invalidate();
419 | // }
420 |
421 | private void setAlphaValue() {
422 | mAlpha = 255 - mAlphaBarValue;
423 | }
424 |
425 | // public void setAlphaBarValue(int value) {
426 | // this.mAlphaBarValue = value;
427 | // setAlphaValue();
428 | // invalidate();
429 | // }
430 | //
431 | // public int getMaxValue() {
432 | // return mMaxValue;
433 | // }
434 | //
435 | // public void setMaxValue(int value) {
436 | // this.mMaxValue = value;
437 | // invalidate();
438 | // }
439 | //
440 | // /**
441 | // * set margin between bars
442 | // * @param mBarMargin
443 | // */
444 | // public void setBarMargin(float mBarMargin) {
445 | // this.mBarMargin = dp2px(mBarMargin);
446 | // refreshLayoutParams();
447 | // invalidate();
448 | // }
449 | //
450 | // /**
451 | // * set margin between bars
452 | // * @param mBarMargin
453 | // */
454 | // public void setBarMarginPx(int mBarMargin) {
455 | // this.mBarMargin = mBarMargin;
456 | // refreshLayoutParams();
457 | // invalidate();
458 | // }
459 |
460 | public void setColorBarValue(int value) {
461 | this.mColorBarValue = value;
462 | invalidate();
463 | if (mOnColorChangeLister != null)
464 | mOnColorChangeLister.onColorChangeListener(mColorBarValue, mAlphaBarValue, getColor());
465 | }
466 |
467 | // /**
468 | // * set thumb's height by dpi
469 | // * @param dp
470 | // */
471 | // public void setThumbHeight(float dp) {
472 | // this.mThumbHeight = dp2px(dp);
473 | // refreshLayoutParams();
474 | // invalidate();
475 | // }
476 | //
477 | // /**
478 | // * set thumb's height by pixels
479 | // * @param px
480 | // */
481 | // public void setThumbHeightPx(int px) {
482 | // this.mThumbHeight = px;
483 | // refreshLayoutParams();
484 | // invalidate();
485 | // }
486 | //
487 | // public int getBarHeight() {
488 | // return mBarHeight;
489 | // }
490 | //
491 | // public int getThumbHeight() {
492 | // return mThumbHeight;
493 | // }
494 | //
495 | // public int getBarMargin() {
496 | // return mBarMargin;
497 | // }
498 | //
499 | public float getColorPosition() {
500 | return mColorBarValue;
501 | }
502 |
503 |
504 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_turn_on_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | -
7 |
8 |
9 |
12 |
13 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_checked_toggle_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_text_tag.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_unchecked_toggle_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_about.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
20 |
21 |
28 |
29 |
35 |
36 |
42 |
43 |
48 |
49 |
54 |
55 |
60 |
61 |
62 |
67 |
68 |
73 |
74 |
79 |
80 |
81 |
87 |
88 |
95 |
96 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_license.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
21 |
22 |
30 |
31 |
38 |
39 |
40 |
47 |
48 |
55 |
56 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
29 |
30 |
31 |
32 |
36 |
37 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/control_panel.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
22 |
23 |
28 |
29 |
42 |
43 |
48 |
49 |
50 |
55 |
56 |
67 |
68 |
75 |
76 |
77 |
78 |
79 |
83 |
84 |
99 |
100 |
104 |
105 |
112 |
113 |
127 |
128 |
129 |
130 |
131 |
136 |
137 |
144 |
145 |
157 |
158 |
164 |
165 |
166 |
176 |
177 |
178 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/screen_filter.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwding/screen-filter/2456d05545788f1acbdd6bdf194b58bbf70dab21/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_settings_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwding/screen-filter/2456d05545788f1acbdd6bdf194b58bbf70dab21/app/src/main/res/mipmap-xxxhdpi/ic_settings_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/night_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwding/screen-filter/2456d05545788f1acbdd6bdf194b58bbf70dab21/app/src/main/res/mipmap-xxxhdpi/night_128.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000000
4 | #52838383
5 | #9c9c9c
6 | #b39c9c9c
7 | #529c9c9c
8 | #700600
9 | #00700b
10 | #4a89fe
11 |
12 | - #F44336
13 | - #9C27B0
14 | - #3F51B5
15 | - #03A9F4
16 | - #009688
17 | - #8BC34A
18 | - #FFEB3B
19 | - #FF9800
20 | - #795548
21 | - #607D8B
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 屏幕滤镜
3 | • 黑暗 -> 启用无色滤镜可进一步降低亮度\n• 日常 -> 启用暖色系滤镜可抗蓝光
4 | 屏幕亮度
5 | 滤镜浓度
6 | 滤镜颜色
7 | 遮挡导航栏
8 | 屏幕常亮
9 | 滤镜未激活 (˘•_•˘)
10 | 滤镜已激活 ( •̀ᴗ•́)و
11 | 重置
12 | 自动
13 | 第三方开源许可
14 | 邮件反馈
15 | 关于
16 | 确定
17 | 高度可定制的轻量级屏幕滤镜
18 | https://github.com/hwding/screen-filter/tree/master/app/src/main
19 | 源码:
20 | 日志:
21 | https://github.com/hwding/screen-filter/blob/master/README.md
22 |
23 |
24 | ColorSeekBar (Modified)
25 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE\nVersion 2, December 2004\nCopyright © 2004 Leon Fu [rtugeek@gmail.com]\nEveryone is permitted to copy and distribute verbatim or modified\ncopies of this license document, and changing it is allowed as long as the name is changed.\nDO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE\nTERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n0. You just DO WHAT THE FUCK YOU WANT TO.
26 | CircularSeekBar
27 | Apache License 2.0
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/test/java/com/amastigote/darker/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.amastigote.darker;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.assertEquals;
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 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.3.0'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | google()
20 | maven { url "https://jitpack.io" }
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------