Pull to refresh

Как Android-разработчик тайм-менеджментом увлёкся, и что и из этого вышло

Reading time15 min
Views22K
Привет, Хабр. Хочу вам признаться. Я — Лентяй. Эта тёмная тайна, тщательно скрывается от окружающих. Поэтому, чур никому ни слова.
Чтобы никто из окружающих не догадался про это, приходится постоянно работать. Но частенько во время работы, отвлекаюсь на всякие посторонние вещи. Новости почитать, посмотреть почту, историю сообщений. В результате, отвлекающие занятия, занимают слишком много времени, и страдает имидж. Иногда, я близок к разоблачению.
Но однажды я нашел методику управления своим рабочим временем, под названием «Pomodoro». И написал приложение «Таймер Трудового Человека». Потому, что я — Android-Разработчик!


Итак, ниже под катом я расскажу о творческих метаниях, головоломаниях, и прочих сопуствующих творческому процессу прелестях.

Часть первая (задумчивая)


Вкратце о системе «Pomodoro». Всё наше рабочее время разделим на определенные отрезки работы и отдыха, называемые «Помидор» (название пошло от формы кухонного таймера, которым пользовался изобретатель метода Франческо Чирилло). Общепринято соотношение 25 минут на работу и 5 на отдых.
Основная идея заключается в том, что рабочее время (25 минут) вы работаете/учитесь по-настоящему, не отвлекаясь ни на что (вот совсем-совсем ни на что). Затем вы 5 минут делаете что хотите (в рамках УК и общественной морали).
Перед началом работы, вы составляете список сколько «помидоров» вы хотите потратить на каждую задачу. Например: подготовка к экзамену — 3 штуки, изучение нового материала — 4 и т.д.
По своему опыту, могу сказать, что эта методика очень эффективная (естественно, что не стал бы я советовать, не испытав на себе).
Изобретатель методики использовал кухонный таймер в виде помидора, откуда собственно и пошло название. Но использовать его в офисе, и пугать коллег странным тиканьем и неожиданными звоночками — не комильфо. Поэтому раньше я использовал секундомер на телефоне, и блокнот. Но это тоже оказалось не удобно.

В Android Market, очень много таймеров работающих по помидорной технике. Мне же хотелось чего-то своего, теплого, и лампового, без дополнительных функций (по выражению моего бывшего начальника — «Свистелки, перделки и фантики»), без рекламы и прочих сомнительных прелестей. Плюс, я сам хотел настраивать свои собственные временные промежутки.

Да и что уж там, я хотел написать своё собственное приложение, как у взрослых.

Часть вторая (экспериментальная)


Первая версия выглядела просто и примитивно. Таймер, кнопка, меню настройки. Начальное состояние:


В процессе работы:


В меню настройки можно выбрать цвета шкалы, и продолжительность этапов работы/отдыха.


Таймер отрисовывался на Canvas.
Но избавившись от таймера, я не ушел от листочков с расписанием. Поэтому решил сделать полную перестройку.

Часть третья (перестроечная)


Итак, в оригинальной системе тайм-менеджмента «Pomodoro», основная идея состоит в том, что вы заранее планируете сколько времени у вас, уйдет на ту или иную задачу. Поэтому, решил добавить список задач. Но людям уже понравилась возможность работы в режиме «нон-стоп». Поэтому старый функционал должен был выжить. Вот так теперь выглядит сейчас главное меню:


Для тех, же кто хочет работать с обычным таймером, без заморочек с расписанием – я оставил классическую версию, доступную по кнопке «Работать без списка задач» (на начальном экране). Сразу выбираете время работы/отдыха и работаете, как в первой версии.


Также под нож пошла возможность выбирать цвета для шкалы времени. Вместо этого было создано несколько гармоничных цветовых схем, и возможность выбирать одну из них. Со схемами у меня был дикий танец с бубнами, благополучно решенный (об этом смотрите ниже).


Итак, если вы хотите создать новое расписание задач на день, то нажав на кнопку «Создать/загрузить список задач», вы можете распланировать свой рабочий день.
Кнопка «Добавить рабочий цикл» — добавляет задачу, разбитую на несколько этапов. Причем каждый этап включает в себя время для работы, и небольшого перерыва.


Через каждые четыре «помидора», рекомендуется устраивать большой перерыв на полчаса-час. Поэтому была добавлена кнопка «Добавить перерыв».


Создав свой список задач, вы можете подкорректировать его и сохранить.


Так вы можете создать себе несколько расписаний, сразу на неделю.


Долгое нажатие на пункт списка позволяет либо отредактировать список заданий, либо начать с ним работать. Рабочий экран выглядит так:


Начав работать со списком, вверху вы видите название текущего этапа, его номер и количество этапов на данную задачу. Чуть ниже список всех циклов (в скобках указаны время работы и отдыха). Основное место занимает главный таймер, как из первой версии программы. Если вы справились с задачей досрочно, то можете нажать на кнопку «Завершить задачу досрочно», и тем самым удалить её из списка. В случае, если вы не уложились в расписание, то кнопка «Добавить цикл», добавит еще один цикл в задачу.

Часть четвертая (околотехническая)


Одним из головоломных моментов, для меня, было создать единые цветовые схемы для приложения. Всё хотелось сделать в стиле Material. Но при тестировании на разных устройствах полезли косяки. То, что выглядело прилично на версии Android 5.x, на 4.x версии смотрелось ужасно.

В конце концов я пришел к такому решению. Создал наборы Material-цветов:

Файл colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#64B5F6</color>
    <color name="colorPrimaryDark">#2196F3</color>
    <color name="colorAccent">#0D47A1</color>

    <color name="colorPrimaryTeal">#4DB6AC</color>
    <color name="colorPrimaryDarkTeal">#009688</color>
    <color name="colorAccentTeal">#004D40</color>

    <color name="colorPrimaryGreen">#8BC34A</color>
    <color name="colorPrimaryDarkGreen">#689F38</color>
    <color name="colorAccentGreen">#33691E</color>

    <color name="colorPrimaryRed">#e57373</color>
    <color name="colorPrimaryDarkRed">#f44336</color>
    <color name="colorAccentRed">#b71c1c</color>

    <color name="colorPrimaryOrange">#FF5722</color>
    <color name="colorPrimaryDarkOrange">#E64A19</color>
    <color name="colorAccentOrange">#BF360C</color>

    <color name="colorPrimaryAmber">#FFD54F</color>
    <color name="colorPrimaryDarkAmber">#FFC107</color>
    <color name="colorAccentAmber">#FF6F00</color>

    <color name="colorPrimaryAutumn">#FF5722</color>
    <color name="colorPrimaryDarkAutumn">#4CAF50</color>
    <color name="colorAccentAutumn">#E64A19</color>

    <color name="colorPrimaryIndigo">#7986CB</color>
    <color name="colorPrimaryDarkIndigo">#3F51B5</color>
    <color name="colorAccentIndigo">#1A237E</color>

    <color name="colorPrimaryBlack">#9E9E9E</color>
    <color name="colorPrimaryDarkBlack">#616161</color>
    <color name="colorAccentBlack">#212121</color>

    <color name="colorText">#ffffff</color>
    <color name="colorTextHint">#c8ffffff</color>

</resources>


И файл со стилями:

Файл styles.xml
<resources>
    <style name="MyDialogStyle" parent="Theme.AppCompat.Dialog.Alert">
        <item name="android:windowFrame">@null</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:textSize">30sp</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowTitleStyle">@null</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
        <item name="android:background">@android:color/transparent</item>
    </style>

    <style name="BlueButtonStyle" parent="Base.Widget.AppCompat.Button">
        <item name="android:background">@drawable/button_shape</item>
    </style>

    <style name="GreenButtonStyle" parent="Base.Widget.AppCompat.Button">
        <item name="android:background">@drawable/button_shape_green</item>
    </style>

    <style name="TealButtonStyle" parent="Base.Widget.AppCompat.Button">
        <item name="android:background">@drawable/button_shape_teal</item>
    </style>

    <style name="AmberButtonStyle" parent="Base.Widget.AppCompat.Button">
        <item name="android:background">@drawable/button_shape_amber</item>
    </style>

    <style name="BlackButtonStyle" parent="Base.Widget.AppCompat.Button">
        <item name="android:background">@drawable/button_shape_black</item>
    </style>

    <style name="IndigoButtonStyle" parent="Base.Widget.AppCompat.Button">
        <item name="android:background">@drawable/button_shape_indigo</item>
    </style>

    <style name="LightBlueButtonStyle" parent="Base.Widget.AppCompat.Button">
        <item name="android:background">@drawable/button_shape_autumn</item>
    </style>

    <style name="OrangeButtonStyle" parent="Base.Widget.AppCompat.Button">
        <item name="android:background">@drawable/button_shape_orange</item>
    </style>

    <style name="RedButtonStyle" parent="Base.Widget.AppCompat.Button">
        <item name="android:background">@drawable/button_shape_red</item>
    </style>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowBackground">@color/colorPrimaryDark</item>
        <item name="android:itemBackground">@color/colorPrimaryDark</item>
        <item name="android:itemTextAppearance">@android:style/TextAppearance.Large</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:textColorHint">@color/colorTextHint</item>
        <item name="buttonStyle">@style/BlueButtonStyle</item>
        <item name="dialogTheme">@style/MyDialogStyle</item>
        <item name="alertDialogTheme">@style/MyDialogStyle</item>

    </style>
    
    <style name="AppTheme.Launcher">
        <item name="android:windowBackground">@color/colorPrimaryDarkBlack</item>
    </style>


    <style name="TealTheme" parent="AppTheme">
        <item name="colorPrimary">@color/colorPrimaryTeal</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDarkTeal</item>
        <item name="colorAccent">@color/colorAccentTeal</item>
        <item name="android:windowBackground">@color/colorPrimaryDarkTeal</item>
        <item name="android:itemBackground">@color/colorPrimaryDarkTeal</item>
        <item name="android:itemTextAppearance">@android:style/TextAppearance.Large</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:textColorHint">@color/colorTextHint</item>
        <item name="buttonStyle">@style/TealButtonStyle</item>
        <item name="dialogTheme">@style/MyDialogStyle</item>
        <item name="alertDialogTheme">@style/MyDialogStyle</item>
    </style>

    <style name="GreenTheme" parent="AppTheme">
        <item name="colorPrimary">@color/colorPrimaryGreen</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDarkGreen</item>
        <item name="colorAccent">@color/colorAccentGreen</item>
        <item name="android:windowBackground">@color/colorPrimaryDarkGreen</item>
        <item name="android:itemBackground">@color/colorPrimaryDarkGreen</item>
        <item name="android:itemTextAppearance">@android:style/TextAppearance.Large</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:textColorHint">@color/colorTextHint</item>
        <item name="buttonStyle">@style/GreenButtonStyle</item>
        <item name="dialogTheme">@style/MyDialogStyle</item>
        <item name="alertDialogTheme">@style/MyDialogStyle</item>
    </style>

    <style name="AmberTheme" parent="AppTheme">
        <item name="colorPrimary">@color/colorPrimaryAmber</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDarkAmber</item>
        <item name="colorAccent">@color/colorAccentAmber</item>
        <item name="android:windowBackground">@color/colorPrimaryDarkAmber</item>
        <item name="android:itemBackground">@color/colorPrimaryDarkAmber</item>
        <item name="android:itemTextAppearance">@android:style/TextAppearance.Large</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:textColorHint">@color/colorTextHint</item>
        <item name="buttonStyle">@style/AmberButtonStyle</item>
        <item name="dialogTheme">@style/MyDialogStyle</item>
        <item name="alertDialogTheme">@style/MyDialogStyle</item>
    </style>

    <style name="BlackTheme" parent="AppTheme">
        <item name="colorPrimary">@color/colorPrimaryBlack</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDarkBlack</item>
        <item name="colorAccent">@color/colorAccentBlack</item>
        <item name="android:windowBackground">@color/colorPrimaryDarkBlack</item>
        <item name="android:itemBackground">@color/colorPrimaryDarkBlack</item>
        <item name="android:itemTextAppearance">@android:style/TextAppearance.Large</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:textColorHint">@color/colorTextHint</item>
        <item name="buttonStyle">@style/BlackButtonStyle</item>
        <item name="dialogTheme">@style/MyDialogStyle</item>
        <item name="alertDialogTheme">@style/MyDialogStyle</item>
    </style>

    <style name="IndigoTheme" parent="AppTheme">
        <item name="colorPrimary">@color/colorPrimaryIndigo</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDarkIndigo</item>
        <item name="colorAccent">@color/colorAccentIndigo</item>
        <item name="android:windowBackground">@color/colorPrimaryDarkIndigo</item>
        <item name="android:itemBackground">@color/colorPrimaryDarkIndigo</item>
        <item name="android:itemTextAppearance">@android:style/TextAppearance.Large</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:textColorHint">@color/colorTextHint</item>
        <item name="buttonStyle">@style/IndigoButtonStyle</item>
        <item name="dialogTheme">@style/MyDialogStyle</item>
        <item name="alertDialogTheme">@style/MyDialogStyle</item>
    </style>

    <style name="AutumnTheme" parent="AppTheme">
        <item name="colorPrimary">@color/colorPrimaryAutumn</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDarkAutumn</item>
        <item name="colorAccent">@color/colorAccentAutumn</item>
        <item name="android:windowBackground">@color/colorPrimaryDarkAutumn</item>
        <item name="android:itemBackground">@color/colorPrimaryDarkAutumn</item>
        <item name="android:itemTextAppearance">@android:style/TextAppearance.Large</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:textColorHint">@color/colorTextHint</item>
        <item name="buttonStyle">@style/LightBlueButtonStyle</item>
        <item name="dialogTheme">@style/MyDialogStyle</item>
        <item name="alertDialogTheme">@style/MyDialogStyle</item>
    </style>

    <style name="OrangeTheme" parent="AppTheme">
        <item name="colorPrimary">@color/colorPrimaryOrange</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDarkOrange</item>
        <item name="colorAccent">@color/colorAccentOrange</item>
        <item name="android:windowBackground">@color/colorPrimaryDarkOrange</item>
        <item name="android:itemBackground">@color/colorPrimaryDarkOrange</item>
        <item name="android:itemTextAppearance">@android:style/TextAppearance.Large</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:textColorHint">@color/colorTextHint</item>
        <item name="buttonStyle">@style/OrangeButtonStyle</item>
        <item name="dialogTheme">@style/MyDialogStyle</item>
        <item name="alertDialogTheme">@style/MyDialogStyle</item>
    </style>

    <style name="RedTheme" parent="AppTheme">
        <item name="colorPrimary">@color/colorPrimaryRed</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDarkRed</item>
        <item name="colorAccent">@color/colorAccentRed</item>
        <item name="android:windowBackground">@color/colorPrimaryDarkRed</item>
        <item name="android:itemBackground">@color/colorPrimaryDarkRed</item>
        <item name="android:itemTextAppearance">@android:style/TextAppearance.Large</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:textColorHint">@color/colorTextHint</item>
        <item name="buttonStyle">@style/RedButtonStyle</item>
        <item name="dialogTheme">@style/MyDialogStyle</item>
        <item name="alertDialogTheme">@style/MyDialogStyle</item>
    </style>
</resources>


И для каждой схемы пришлось создать свою форму для кнопки. Например для схемы «Индиго»:

Файл button_shape_indigo.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="15dp"/>
    <solid
        android:color="@color/colorPrimaryIndigo"/>
    <stroke
        android:width="2dp"
        android:color="@color/colorPrimaryDarkIndigo"/>
    <padding
        android:left="40dp"
        android:right="40dp"
        android:bottom="10dp"
        android:top="10dp"/>
</shape>


В фрагменте настроек задавалось имя схемы, и при старте любой активности (в onCreate) отрабатывал такой код:

Функция выбора темы
 public static void  setNewTheme(Context mContext){
        SharedPreferences sp;
        sp = PreferenceManager.getDefaultSharedPreferences(mContext);
        String colorScheme = sp.getString("colorScheme", "blue");
        if(colorScheme.equals("blue"))
            mContext.setTheme(R.style.AppTheme);
        else if (colorScheme.equals("green"))
            mContext.setTheme(R.style.GreenTheme);
        else if (colorScheme.equals("teal"))
            mContext.setTheme(R.style.TealTheme);
        else if (colorScheme.equals("amber"))
            mContext.setTheme(R.style.AmberTheme);
        else if (colorScheme.equals("black"))
            mContext.setTheme(R.style.BlackTheme);
        else if (colorScheme.equals("indigo"))
            mContext.setTheme(R.style.IndigoTheme);
        else if (colorScheme.equals("autumn"))
            mContext.setTheme(R.style.AutumnTheme);
        else if (colorScheme.equals("orange"))
            mContext.setTheme(R.style.OrangeTheme);
        else if (colorScheme.equals("red"))
            mContext.setTheme(R.style.RedTheme);
    }


Часть пятая (околорекламная и немного скандальная)


Приложение изначально писал для себя. И поэтому делать какие-либо вложения в рекламную кампанию, не видел смысла. На всякий случай, перевел приложение на английский. И посидев в векторном редакторе, минут за 15 сваял иконку и главную картинку (та, что вверху поста). Разместил приложение на 4pda. Там в сумме вышло около 150 скачиваний.

Также, я пишу истории из своей жизни на Пикабу. Людям нравится, есть подписчики. Поэтому разместил два поста (о первой и второй версии соотвественно, последовательно по мере выхода версий). Но к сожалению, парочка троллей, решили «пошутить», и натравили модератора с жалобой, что «мол реклама приложения, и запрещено правилами». Модератор не разобравшись тему про первую версию удалил, и влепил бан на две недели. Но, письмо в поддержку, решило данную проблему, и админы разблокировали статью. Правда тролль не успокоился, и требовал «Забаньте его за неграмотный Русский язык и пунктуацию! », но нахватав минусов благополучно слился. Второй пост, про новую версию троллить уже не пытались. В общем, аудитория приняла приложение благосклонно, указали на несколько ошибок (исправлены).

Вот собственно и вся моя история написания приложения. Естественно, приложение доступно бесплатно и без рекламы. Никакой материальной выгоды, кроме морального удовлетворения (и немного, для удовлетворения мании величия), и желания поделиться полезным инструментом с сообществом, автор не получает.
Засим позвольте откланяться. Надеюсь кому-то это окажется полезным. Если у кого-то есть замечания или подсказки, с большим удовольствием их выслушаю.
Tags:
Hubs:
+11
Comments23

Articles