diff --git a/app/src/main/java/com/hippo/ehviewer/Settings.java b/app/src/main/java/com/hippo/ehviewer/Settings.java index 3581d6ef6..d407dc613 100644 --- a/app/src/main/java/com/hippo/ehviewer/Settings.java +++ b/app/src/main/java/com/hippo/ehviewer/Settings.java @@ -459,6 +459,28 @@ public class Settings { putBoolean(KEY_VOLUME_PAGE, value); } + private static final String KEY_CUSTOM_SCREEN_LIGHTNESS = "custom_screen_lightness"; + private static final boolean DEFAULT_CUSTOM_SCREEN_LIGHTNESS = false; + + public static boolean getCustomScreenLightness() { + return getBoolean(KEY_CUSTOM_SCREEN_LIGHTNESS, DEFAULT_CUSTOM_SCREEN_LIGHTNESS); + } + + public static void putCustomScreenLightness(boolean value) { + putBoolean(KEY_CUSTOM_SCREEN_LIGHTNESS, value); + } + + private static final String KEY_SCREEN_LIGHTNESS = "screen_lightness"; + private static final int DEFAULT_SCREEN_LIGHTNESS = 50; + + public static int getScreenLightness() { + return getInt(KEY_SCREEN_LIGHTNESS, DEFAULT_SCREEN_LIGHTNESS); + } + + public static void putScreenLightness(int value) { + putInt(KEY_SCREEN_LIGHTNESS, value); + } + /******************** ****** Download ********************/ diff --git a/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java index 70b458b3e..5a01cda37 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java @@ -36,8 +36,10 @@ import android.text.TextUtils; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; +import android.view.Window; import android.view.WindowManager; import android.webkit.MimeTypeMap; +import android.widget.CompoundButton; import android.widget.FrameLayout; import android.widget.SeekBar; import android.widget.Spinner; @@ -63,8 +65,10 @@ import com.hippo.gl.view.GLRootView; import com.hippo.image.Image; import com.hippo.unifile.UniFile; import com.hippo.util.SystemUiHelper; +import com.hippo.widget.ColorView; import com.hippo.yorozuya.AnimationUtils; import com.hippo.yorozuya.ConcurrentPool; +import com.hippo.yorozuya.MathUtils; import com.hippo.yorozuya.SimpleAnimatorListener; import com.hippo.yorozuya.SimpleHandler; import com.hippo.yorozuya.ViewUtils; @@ -105,6 +109,8 @@ public class GalleryActivity extends EhActivity private SystemUiHelper mSystemUiHelper; private boolean mShowSystemUi; + @Nullable + private ColorView mMaskView; @Nullable private View mClock; @Nullable @@ -261,6 +267,7 @@ public class GalleryActivity extends EhActivity mSystemUiHelper.hide(); mShowSystemUi = false; + mMaskView = (ColorView) ViewUtils.$$(this, R.id.mask); mClock = ViewUtils.$$(this, R.id.clock); mBattery = ViewUtils.$$(this, R.id.battery); mClock.setVisibility(Settings.getShowClock() ? View.VISIBLE : View.GONE); @@ -300,6 +307,9 @@ public class GalleryActivity extends EhActivity } setRequestedOrientation(orientation); + // Screen lightness + setScreenLightness(Settings.getCustomScreenLightness(), Settings.getScreenLightness()); + if (Settings.getGuideGallery()) { FrameLayout mainLayout = (FrameLayout) ViewUtils.$$(this, R.id.main); mainLayout.addView(new GalleryGuideView(this)); @@ -320,6 +330,9 @@ public class GalleryActivity extends EhActivity mGalleryProvider = null; } + mMaskView = null; + mClock = null; + mBattery = null; mSeekBarPanel = null; mLeftText = null; mRightText = null; @@ -667,6 +680,34 @@ public class GalleryActivity extends EhActivity } } + /** + * @param lightness 0 - 200 + */ + private void setScreenLightness(boolean enable, int lightness) { + if (null == mMaskView) { + return; + } + + Window w = getWindow(); + WindowManager.LayoutParams lp = w.getAttributes(); + if (enable) { + lightness = MathUtils.clamp(lightness, 0, 200); + if (lightness > 100) { + mMaskView.setColor(0); + // Avoid BRIGHTNESS_OVERRIDE_OFF, + // screen may be off when lp.screenBrightness is 0.0f + lp.screenBrightness = Math.max((lightness - 100) / 100.0f, 0.01f); + } else { + mMaskView.setColor(MathUtils.lerp(0xde, 0x00, lightness / 100.0f) << 24); + lp.screenBrightness = 0.01f; + } + } else { + mMaskView.setColor(0); + lp.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE; + } + w.setAttributes(lp); + } + private class GalleryMenuHelper implements DialogInterface.OnClickListener { private final View mView; @@ -678,6 +719,8 @@ public class GalleryActivity extends EhActivity private final SwitchCompat mShowClock; private final SwitchCompat mShowBattery; private final SwitchCompat mVolumePage; + private final SwitchCompat mCustomScreenLightness; + private final SeekBar mScreenLightness; @SuppressLint("InflateParams") public GalleryMenuHelper(Context context) { @@ -690,6 +733,8 @@ public class GalleryActivity extends EhActivity mShowClock = (SwitchCompat) mView.findViewById(R.id.show_clock); mShowBattery = (SwitchCompat) mView.findViewById(R.id.show_battery); mVolumePage = (SwitchCompat) mView.findViewById(R.id.volume_page); + mCustomScreenLightness = (SwitchCompat) mView.findViewById(R.id.custom_screen_lightness); + mScreenLightness = (SeekBar) mView.findViewById(R.id.screen_lightness); mScreenRotation.setSelection(Settings.getScreenRotation()); mReadingDirection.setSelection(Settings.getReadingDirection()); @@ -699,6 +744,16 @@ public class GalleryActivity extends EhActivity mShowClock.setChecked(Settings.getShowClock()); mShowBattery.setChecked(Settings.getShowBattery()); mVolumePage.setChecked(Settings.getVolumePage()); + mCustomScreenLightness.setChecked(Settings.getCustomScreenLightness()); + mScreenLightness.setProgress(Settings.getScreenLightness()); + mScreenLightness.setEnabled(Settings.getCustomScreenLightness()); + + mCustomScreenLightness.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mScreenLightness.setEnabled(isChecked); + } + }); } public View getView() { @@ -715,6 +770,8 @@ public class GalleryActivity extends EhActivity boolean showClock = mShowClock.isChecked(); boolean showBattery = mShowBattery.isChecked(); boolean volumePage = mVolumePage.isChecked(); + boolean customScreenLightness = mCustomScreenLightness.isChecked(); + int screenLightness = mScreenLightness.getProgress(); Settings.putScreenRotation(screenRotation); Settings.putReadingDirection(layoutMode); @@ -724,6 +781,8 @@ public class GalleryActivity extends EhActivity Settings.putShowClock(showClock); Settings.putShowBattery(showBattery); Settings.putVolumePage(volumePage); + Settings.putCustomScreenLightness(customScreenLightness); + Settings.putScreenLightness(screenLightness); int orientation; switch (screenRotation) { @@ -755,6 +814,7 @@ public class GalleryActivity extends EhActivity if (mBattery != null) { mBattery.setVisibility(showBattery ? View.VISIBLE : View.GONE); } + setScreenLightness(customScreenLightness, screenLightness); // Update slider mLayoutMode = layoutMode; diff --git a/app/src/main/java/com/hippo/preference/SeekBarPreference.java b/app/src/main/java/com/hippo/preference/SeekBarPreference.java new file mode 100644 index 000000000..4183518bf --- /dev/null +++ b/app/src/main/java/com/hippo/preference/SeekBarPreference.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.preference; + +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Parcel; +import android.os.Parcelable; +import android.preference.Preference; +import android.util.AttributeSet; +import android.view.View; +import android.widget.SeekBar; + +import com.hippo.ehviewer.R; + +public class SeekBarPreference extends Preference implements SeekBar.OnSeekBarChangeListener { + + private int mProgress; + private int mMax; + private boolean mTrackingTouch; + + public SeekBarPreference(Context context) { + super(context); + init(context, null, 0, 0); + } + + public SeekBarPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs, 0, 0); + } + + public SeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs, defStyleAttr, 0); + } + + private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SeekBarPreference, defStyleAttr, defStyleRes); + setMax(a.getInt(R.styleable.SeekBarPreference_max, mMax)); + a.recycle(); + + setLayoutResource(R.layout.preference_widget_seekbar); + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + SeekBar seekBar = (SeekBar) view.findViewById(R.id.seekbar); + seekBar.setOnSeekBarChangeListener(this); + seekBar.setMax(mMax); + seekBar.setProgress(mProgress); + seekBar.setEnabled(isEnabled()); + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + setProgress(restoreValue ? getPersistedInt(mProgress) + : (Integer) defaultValue); + } + + @Override + protected Object onGetDefaultValue(TypedArray a, int index) { + return a.getInt(index, 0); + } + + public void setMax(int max) { + if (max != mMax) { + mMax = max; + notifyChanged(); + } + } + + public void setProgress(int progress) { + setProgress(progress, true); + } + + private void setProgress(int progress, boolean notifyChanged) { + if (progress > mMax) { + progress = mMax; + } + if (progress < 0) { + progress = 0; + } + if (progress != mProgress) { + mProgress = progress; + persistInt(progress); + if (notifyChanged) { + notifyChanged(); + } + } + } + + public int getProgress() { + return mProgress; + } + + /** + * Persist the seekBar's progress value if callChangeListener + * returns true, otherwise set the seekBar's progress to the stored value + */ + void syncProgress(SeekBar seekBar) { + int progress = seekBar.getProgress(); + if (progress != mProgress) { + if (callChangeListener(progress)) { + setProgress(progress, false); + } else { + seekBar.setProgress(mProgress); + } + } + } + + @Override + public void onProgressChanged( + SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser && !mTrackingTouch) { + syncProgress(seekBar); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + mTrackingTouch = true; + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + mTrackingTouch = false; + if (seekBar.getProgress() != mProgress) { + syncProgress(seekBar); + } + } + + @Override + protected Parcelable onSaveInstanceState() { + /* + * Suppose a client uses this preference type without persisting. We + * must save the instance state so it is able to, for example, survive + * orientation changes. + */ + + final Parcelable superState = super.onSaveInstanceState(); + if (isPersistent()) { + // No need to save instance state since it's persistent + return superState; + } + + // Save the instance state + final SavedState myState = new SavedState(superState); + myState.progress = mProgress; + myState.max = mMax; + return myState; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (!state.getClass().equals(SavedState.class)) { + // Didn't save state for us in onSaveInstanceState + super.onRestoreInstanceState(state); + return; + } + + // Restore the instance state + SavedState myState = (SavedState) state; + super.onRestoreInstanceState(myState.getSuperState()); + mProgress = myState.progress; + mMax = myState.max; + notifyChanged(); + } + + /** + * SavedState, a subclass of {@link BaseSavedState}, will store the state + * of MyPreference, a subclass of Preference. + *
+ * It is important to always call through to super methods.
+ */
+ private static class SavedState extends BaseSavedState {
+ int progress;
+ int max;
+
+ public SavedState(Parcel source) {
+ super(source);
+
+ // Restore the click counter
+ progress = source.readInt();
+ max = source.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+
+ // Save the click counter
+ dest.writeInt(progress);
+ dest.writeInt(max);
+ }
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ @SuppressWarnings("unused")
+ public static final Parcelable.Creator