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

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

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

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

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

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

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

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

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

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

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

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

Начав работать со списком, вверху вы видите название текущего этапа, его номер и количество этапов на данную задачу. Чуть ниже список всех циклов (в скобках указаны время работы и отдыха). Основное место занимает главный таймер, как из первой версии программы. Если вы справились с задачей досрочно, то можете нажать на кнопку «Завершить задачу досрочно», и тем самым удалить её из списка. В случае, если вы не уложились в расписание, то кнопка «Добавить цикл», добавит еще один цикл в задачу.
Часть четвертая (околотехническая)
Одним из головоломных моментов, для меня, было создать единые цветовые схемы для приложения. Всё хотелось сделать в стиле Material. Но при тестировании на разных устройствах полезли косяки. То, что выглядело прилично на версии Android 5.x, на 4.x версии смотрелось ужасно.
В конце концов я пришел к такому решению. Создал наборы Material-цветов:
<?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>
И файл со стилями:
<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>
И для каждой схемы пришлось создать свою форму для кнопки. Например для схемы «Индиго»:
<?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 скачиваний.
Также, я пишу истории из своей жизни на Пикабу. Людям нравится, есть подписчики. Поэтому разместил два поста (о первой и второй версии соотвественно, последовательно по мере выхода версий). Но к сожалению, парочка троллей, решили «пошутить», и натравили модератора с жалобой, что «мол реклама приложения, и запрещено правилами». Модератор не разобравшись тему про первую версию удалил, и влепил бан на две недели. Но, письмо в поддержку, решило данную проблему, и админы разблокировали статью. Правда тролль не успокоился, и требовал «Забаньте его за неграмотный Русский язык и пунктуацию! », но нахватав минусов благополучно слился. Второй пост, про новую версию троллить уже не пытались. В общем, аудитория приняла приложение благосклонно, указали на несколько ошибок (исправлены).
Вот собственно и вся моя история написания приложения. Естественно, приложение доступно бесплатно и без рекламы. Никакой материальной выгоды, кроме морального удовлетворения (и немного, для удовлетворения мании величия), и желания поделиться полезным инструментом с сообществом, автор не получает.
Засим позвольте откланяться. Надеюсь кому-то это окажется полезным. Если у кого-то есть замечания или подсказки, с большим удовольствием их выслушаю.

