Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1799dca7 authored by Justin Klaassen's avatar Justin Klaassen
Browse files

Refactor dynamic background color to BaseActivity

Bug: 17426658
Change-Id: I0d1a847e5154bbf21489bfcd3d8cbdf3f7875a9b
parent bfd29036
Loading
Loading
Loading
Loading
+123 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.android.deskclock;

import android.animation.ObjectAnimator;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.text.format.DateUtils;

/**
 * Base activity class that changes with window's background color dynamically based on the
 * current hour.
 */
public class BaseActivity extends AppCompatActivity {

    /**
     * Key used to save/restore the current background color from the saved instance state.
     */
    private static final String KEY_BACKGROUND_COLOR = "background_color";

    /**
     * Frequency to check if the background color needs to be updated.
     */
    private static final long BACKGROUND_COLOR_CHECK_DELAY_MILLIS = DateUtils.MINUTE_IN_MILLIS;

    /**
     * Duration in millis to animate changes to the background color.
     */
    private static final long BACKGROUND_COLOR_ANIMATION_DURATION = 3000L;

    /**
     * {@link Handler} used to post the {@link #mBackgroundColorChanger} runnable.
     */
    private final Handler mHandler = new Handler();

    /**
     * {@link Runnable} posted periodically to update the background color.
     */
    private final Runnable mBackgroundColorChanger = new Runnable() {
        @Override
        public void run() {
            setBackgroundColor(Utils.getCurrentHourColor(), true /* animate */);
            mHandler.postDelayed(this, BACKGROUND_COLOR_CHECK_DELAY_MILLIS);
        }
    };

    /**
     * {@link ColorDrawable} used to draw the window's background.
     */
    private ColorDrawable mBackground;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final int backgroundColor = savedInstanceState == null ? Utils.getCurrentHourColor()
                : savedInstanceState.getInt(KEY_BACKGROUND_COLOR, Utils.getCurrentHourColor());
        setBackgroundColor(backgroundColor, false /* animate */);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Update the current background color periodically.
        mHandler.post(mBackgroundColorChanger);
    }

    @Override
    protected void onPause() {
        super.onPause();

        // Stop updating the background color when not active.
        mHandler.removeCallbacks(mBackgroundColorChanger);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        // Save the background color so we can animate the change when the activity is restored.
        outState.putInt(KEY_BACKGROUND_COLOR, mBackground.getColor());
    }

    /**
     * Sets the current background color to the provided value and animates the change if desired.
     *
     * @param color the ARGB value to set as the current background color
     * @param animate {@code true} if the change should be animated
     */
    protected void setBackgroundColor(int color, boolean animate) {
        if (mBackground == null) {
            mBackground = new ColorDrawable(color);
            getWindow().setBackgroundDrawable(mBackground);
        }

        if (mBackground.getColor() != color) {
            if (animate) {
                ObjectAnimator.ofObject(mBackground, "color", AnimatorUtils.ARGB_EVALUATOR, color)
                        .setDuration(BACKGROUND_COLOR_ANIMATION_DURATION)
                        .start();
            } else {
                mBackground.setColor(color);
            }
        }
    }
}
+40 −113
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package com.android.deskclock;

import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
@@ -29,7 +27,6 @@ import android.content.res.Configuration;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
@@ -38,7 +35,6 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.Tab;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -66,73 +62,40 @@ import java.util.TimeZone;
/**
 * DeskClock clock view for desk docks.
 */
public class DeskClock extends AppCompatActivity implements
public class DeskClock extends BaseActivity implements
        LabelDialogFragment.TimerLabelDialogHandler, LabelDialogFragment.AlarmLabelDialogHandler {

    private static final boolean DEBUG = false;
    private static final String LOG_TAG = "DeskClock";

    // Alarm action for midnight (so we can update the date display).
    private static final String KEY_SELECTED_TAB = "selected_tab";
    private static final String KEY_LAST_HOUR_COLOR = "last_hour_color";
    // Check whether to change background every minute
    private static final long BACKGROUND_COLOR_CHECK_DELAY_MILLIS = DateUtils.MINUTE_IN_MILLIS;
    private static final int BACKGROUND_COLOR_INITIAL_ANIMATION_DURATION_MILLIS = 3000;
    private static final int UNKNOWN_COLOR_ID = 0;
    public static final String SELECT_TAB_INTENT_EXTRA = "deskclock.select.tab";

    private boolean mIsFirstLaunch = true;
    private ActionBar mActionBar;
    private Tab mAlarmTab;
    private Tab mClockTab;
    private Tab mTimerTab;
    private Tab mStopwatchTab;
    private Menu mMenu;
    private ViewPager mViewPager;
    private TabsAdapter mTabsAdapter;
    private Handler mHander;
    private ImageButton mFab;
    private ImageButton mLeftButton;
    private ImageButton mRightButton;
    private int mSelectedTab;
    private int mLastHourColor = UNKNOWN_COLOR_ID;
    private final Runnable mBackgroundColorChanger = new Runnable() {
        @Override
        public void run() {
            setBackgroundColor();
            mHander.postDelayed(this, BACKGROUND_COLOR_CHECK_DELAY_MILLIS);
        }
    };
    // Request code used when SettingsActivity is launched.
    private static final int REQUEST_CHANGE_SETTINGS = 1;

    public static final int ALARM_TAB_INDEX = 0;
    public static final int CLOCK_TAB_INDEX = 1;
    public static final int TIMER_TAB_INDEX = 2;
    public static final int STOPWATCH_TAB_INDEX = 3;

    // Tabs indices are switched for right-to-left since there is no
    // native support for RTL in the ViewPager.
    public static final int RTL_ALARM_TAB_INDEX = 3;
    public static final int RTL_CLOCK_TAB_INDEX = 2;
    public static final int RTL_TIMER_TAB_INDEX = 1;
    public static final int RTL_STOPWATCH_TAB_INDEX = 0;
    public static final String SELECT_TAB_INTENT_EXTRA = "deskclock.select.tab";

    // Request code used when SettingsActivity is launched.
    private static final int REQUEST_CHANGE_SETTINGS = 1;

    // TODO(rachelzhang): adding a broadcast receiver to adjust color when the timezone/time
    // changes in the background.

    @Override
    protected void onStart() {
        super.onStart();
        if (mHander == null) {
            mHander = new Handler();
        }
        mHander.postDelayed(mBackgroundColorChanger, BACKGROUND_COLOR_CHECK_DELAY_MILLIS);
    }
    private ActionBar mActionBar;
    private Menu mMenu;
    private ViewPager mViewPager;
    private ImageButton mFab;
    private ImageButton mLeftButton;
    private ImageButton mRightButton;

    @Override
    protected void onStop() {
        super.onStop();
        mHander.removeCallbacks(mBackgroundColorChanger);
    }
    private TabsAdapter mTabsAdapter;
    private int mSelectedTab;

    @Override
    public void onNewIntent(Intent newIntent) {
@@ -198,30 +161,30 @@ public class DeskClock extends AppCompatActivity implements
            mActionBar.setDisplayOptions(0);
            mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

            mAlarmTab = mActionBar.newTab();
            final Tab alarmTab = mActionBar.newTab();

            mAlarmTab.setIcon(R.drawable.ic_tab_alarm);
            mAlarmTab.setContentDescription(R.string.menu_alarm);
            mTabsAdapter.addTab(mAlarmTab,
            alarmTab.setIcon(R.drawable.ic_tab_alarm);
            alarmTab.setContentDescription(R.string.menu_alarm);
            mTabsAdapter.addTab(alarmTab,
                    Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
                            ? AlarmClockFragmentPreL.class
                            : AlarmClockFragmentPostL.class,
                    ALARM_TAB_INDEX);

            mClockTab = mActionBar.newTab();
            mClockTab.setIcon(R.drawable.ic_tab_clock);
            mClockTab.setContentDescription(R.string.menu_clock);
            mTabsAdapter.addTab(mClockTab, ClockFragment.class, CLOCK_TAB_INDEX);
            final Tab clockTab = mActionBar.newTab();
            clockTab.setIcon(R.drawable.ic_tab_clock);
            clockTab.setContentDescription(R.string.menu_clock);
            mTabsAdapter.addTab(clockTab, ClockFragment.class, CLOCK_TAB_INDEX);

            mTimerTab = mActionBar.newTab();
            mTimerTab.setIcon(R.drawable.ic_tab_timer);
            mTimerTab.setContentDescription(R.string.menu_timer);
            mTabsAdapter.addTab(mTimerTab, TimerFragment.class, TIMER_TAB_INDEX);
            final Tab timerTab = mActionBar.newTab();
            timerTab.setIcon(R.drawable.ic_tab_timer);
            timerTab.setContentDescription(R.string.menu_timer);
            mTabsAdapter.addTab(timerTab, TimerFragment.class, TIMER_TAB_INDEX);

            mStopwatchTab = mActionBar.newTab();
            mStopwatchTab.setIcon(R.drawable.ic_tab_stopwatch);
            mStopwatchTab.setContentDescription(R.string.menu_stopwatch);
            mTabsAdapter.addTab(mStopwatchTab, StopwatchFragment.class, STOPWATCH_TAB_INDEX);
            final Tab stopwatchTab = mActionBar.newTab();
            stopwatchTab.setIcon(R.drawable.ic_tab_stopwatch);
            stopwatchTab.setContentDescription(R.string.menu_stopwatch);
            mTabsAdapter.addTab(stopwatchTab, StopwatchFragment.class, STOPWATCH_TAB_INDEX);

            mActionBar.setSelectedNavigationItem(selectedIndex);
            mTabsAdapter.notifySelectedPage(selectedIndex);
@@ -233,17 +196,15 @@ public class DeskClock extends AppCompatActivity implements
        super.onCreate(icicle);
        setVolumeControlStream(AudioManager.STREAM_ALARM);

        mIsFirstLaunch = (icicle == null);
        getWindow().setBackgroundDrawable(null);

        mIsFirstLaunch = true;
        mSelectedTab = CLOCK_TAB_INDEX;
        if (icicle != null) {
            mSelectedTab = icicle.getInt(KEY_SELECTED_TAB, CLOCK_TAB_INDEX);
            mLastHourColor = icicle.getInt(KEY_LAST_HOUR_COLOR, UNKNOWN_COLOR_ID);
            if (mLastHourColor != UNKNOWN_COLOR_ID) {
                getWindow().getDecorView().setBackgroundColor(mLastHourColor);
            }
        } else {
            mSelectedTab = CLOCK_TAB_INDEX;

            // Set the background color to initially match the theme value so that we can
            // smoothly transition to the dynamic color.
            setBackgroundColor(getResources().getColor(R.color.default_background),
                    false /* animate */);
        }

        // Timer receiver may ask the app to go to the timer fragment if a timer expired
@@ -266,8 +227,6 @@ public class DeskClock extends AppCompatActivity implements
    protected void onResume() {
        super.onResume();

        setBackgroundColor();

        // We only want to show notifications for stopwatch/timer when the app is closed so
        // that we don't have to worry about keeping the notifications in perfect sync with
        // the app.
@@ -303,7 +262,6 @@ public class DeskClock extends AppCompatActivity implements
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(KEY_SELECTED_TAB, mActionBar.getSelectedNavigationIndex());
        outState.putInt(KEY_LAST_HOUR_COLOR, mLastHourColor);
    }

    @Override
@@ -416,25 +374,6 @@ public class DeskClock extends AppCompatActivity implements
        }
    }

    private void setBackgroundColor() {
        final int duration;
        if (mLastHourColor == UNKNOWN_COLOR_ID) {
            mLastHourColor = getResources().getColor(R.color.default_background);
            duration = BACKGROUND_COLOR_INITIAL_ANIMATION_DURATION_MILLIS;
        } else {
            duration = getResources().getInteger(android.R.integer.config_longAnimTime);
        }
        final int currHourColor = Utils.getCurrentHourColor();
        if (mLastHourColor != currHourColor) {
            final ObjectAnimator animator = ObjectAnimator.ofInt(getWindow().getDecorView(),
                    "backgroundColor", mLastHourColor, currHourColor);
            animator.setDuration(duration);
            animator.setEvaluator(new ArgbEvaluator());
            animator.start();
            mLastHourColor = currHourColor;
        }
    }

    /**
     * Adapter for wrapping together the ActionBar's tab with the ViewPager
     */
@@ -554,15 +493,8 @@ public class DeskClock extends AppCompatActivity implements
            final int rtlSafePosition = getRtlPosition(position);
            mSelectedTab = position;

            if (mIsFirstLaunch && isClockTab(rtlSafePosition)) {
                mLeftButton.setVisibility(View.INVISIBLE);
                mRightButton.setVisibility(View.INVISIBLE);
                mFab.setVisibility(View.VISIBLE);
                mFab.setImageResource(R.drawable.ic_globe);
                mFab.setContentDescription(getString(R.string.button_cities));
                mIsFirstLaunch = false;
            } else {
                DeskClockFragment f = (DeskClockFragment) getItem(rtlSafePosition);
            final DeskClockFragment f = (DeskClockFragment) getItem(rtlSafePosition);
            if (f != null) {
                f.setFabAppearance();
                f.setLeftRightButtonAppearance();
            }
@@ -574,11 +506,6 @@ public class DeskClock extends AppCompatActivity implements
            // Do nothing
        }

        private boolean isClockTab(int rtlSafePosition) {
            final int clockTabIndex = isRtl() ? RTL_CLOCK_TAB_INDEX : CLOCK_TAB_INDEX;
            return rtlSafePosition == clockTabIndex;
        }

        public void notifySelectedPage(int page) {
            notifyPageChanged(page);
        }
+1 −9
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.support.v7.app.AppCompatActivity;
import android.text.format.DateUtils;
import android.view.Menu;
import android.view.MenuItem;
@@ -39,7 +38,7 @@ import java.util.TimeZone;
/**
 * Settings for the Alarm Clock.
 */
public class SettingsActivity extends AppCompatActivity {
public class SettingsActivity extends BaseActivity {

    public static final String KEY_ALARM_SNOOZE = "snooze_duration";
    public static final String KEY_VOLUME_BEHAVIOR = "volume_button_setting";
@@ -58,16 +57,9 @@ public class SettingsActivity extends AppCompatActivity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setVolumeControlStream(AudioManager.STREAM_ALARM);

        setContentView(R.layout.settings);
    }

    @Override
    protected void onResume() {
        super.onResume();
        getWindow().getDecorView().setBackgroundColor(Utils.getCurrentHourColor());
    }

    @Override
    public boolean onOptionsItemSelected (MenuItem item) {
        switch (item.getItemId()) {
+0 −5
Original line number Diff line number Diff line
@@ -638,11 +638,6 @@ public class Utils {
        return Color.parseColor(BACKGROUND_SPECTRUM[hourOfDay]);
    }

    public static int getNextHourColor() {
        final int currHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        return Color.parseColor(BACKGROUND_SPECTRUM[currHour < 24 ? currHour + 1 : 1]);
    }

    /**
     * @param firstDay is the result from getZeroIndexedFirstDayOfWeek
     * @return Single-char version of day name, e.g.: 'S', 'M', 'T', 'W', 'T', 'F', 'S'
+2 −4
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ package com.android.deskclock.timer;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
@@ -25,6 +24,7 @@ import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;

import com.android.deskclock.BaseActivity;
import com.android.deskclock.R;
import com.android.deskclock.Utils;
import com.android.deskclock.timer.TimerFullScreenFragment.OnEmptyListListener;
@@ -34,7 +34,7 @@ import com.android.deskclock.timer.TimerFullScreenFragment.OnEmptyListListener;
 * shows over the lock screen.
 * This activity re-uses TimerFullScreenFragment GUI
 */
public class TimerAlertFullScreen extends AppCompatActivity implements OnEmptyListListener {
public class TimerAlertFullScreen extends BaseActivity implements OnEmptyListListener {

    private static final String TAG = "TimerAlertFullScreen";
    private static final String FRAGMENT = "timer";
@@ -77,8 +77,6 @@ public class TimerAlertFullScreen extends AppCompatActivity implements OnEmptyLi
    protected void onResume() {
        super.onResume();

        getWindow().getDecorView().setBackgroundColor(Utils.getCurrentHourColor());

        // Only show notifications for times-up when this activity closed.
        Utils.cancelTimesUpNotifications(this);
    }
Loading