Чтобы никто из окружающих не догадался про это, приходится постоянно работать. Но частенько во время работы, отвлекаюсь на всякие посторонние вещи. Новости почитать, посмотреть почту, историю сообщений. В результате, отвлекающие занятия, занимают слишком много времени, и страдает имидж. Иногда, я близок к разоблачению.
Но однажды я нашел методику управления своим рабочим временем, под названием «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 скачиваний.
Также, я пишу истории из своей жизни на Пикабу. Людям нравится, есть подписчики. Поэтому разместил два поста (о первой и второй версии соотвественно, последовательно по мере выхода версий). Но к сожалению, парочка троллей, решили «пошутить», и натравили модератора с жалобой, что «мол реклама приложения, и запрещено правилами». Модератор не разобравшись тему про первую версию удалил, и влепил бан на две недели. Но, письмо в поддержку, решило данную проблему, и админы разблокировали статью. Правда тролль не успокоился, и требовал «Забаньте его за неграмотный Русский язык и пунктуацию! », но нахватав минусов благополучно слился. Второй пост, про новую версию троллить уже не пытались. В общем, аудитория приняла приложение благосклонно, указали на несколько ошибок (исправлены).
Вот собственно и вся моя история написания приложения. Естественно, приложение доступно бесплатно и без рекламы. Никакой материальной выгоды, кроме морального удовлетворения (и немного, для удовлетворения мании величия), и желания поделиться полезным инструментом с сообществом, автор не получает.
Засим позвольте откланяться. Надеюсь кому-то это окажется полезным. Если у кого-то есть замечания или подсказки, с большим удовольствием их выслушаю.
Комментарии (21)
White_man
14.10.2016 17:23Спасибо за статью. Люблю технику pomodoro и сам пользуюсь 2мя приложениями на андроид.
А там есть какие-то сложности с бэкграунд работой и таймерами?
Надо логику выносить в сервис?Snakecatcher
14.10.2016 17:26Уточните, что вы имеете в виду под логикой в серисе?
Может ли работать на заднем фоне?
Я не делал извещений завязанных, на окончание/начало периода. Предусмотрена работа в реалтайме.
В планах добавить извещения со звуковым сигналом.
А какими приложениями вы пользуетесь? Что вам не хватает, а что хотелось бы добавить в них?
poxu
14.10.2016 18:23+2Я — Лентяй. Чтобы никто из окружающих не догадался про это, приходится постоянно работать.
Ничего вы не знаете о лени...
Snakecatcher
14.10.2016 18:27+3Я просто Маэстро Лени :) Великий Магистр :)
poxu
15.10.2016 09:29+1Каждый может с улыбкой говорить, что он Великий Магистр, когда для того, чтобы остальные об этом не узнали он постоянно работает. Какие проблемы то? Ещё очень удобно рассказывать, что ты вообще-то слабак, но чтобы это скрывать — каждый день жмёшь от груди сотку по 10 раз, чтобы никто не догадался. Только вот пробемы слабых людей такому человеку не более понятны, чем вам — проблемы ленивых.
Сообщения новые его отвлекают… Представьте себе, что пришли на работу, сели писать код, только не выходит ничего. И задача ясна и как код написать — понятно, но это же сейчас целый день надо его писать. И ещё каждую мелочь из не очень большого задания сделать и убедиться, что она действительно сделана. И вы просто не пишете. Смотрите в IDE иногда в перерывах между непонятно чем и ещё непонятно чем и всё.
Повторюсь — если вы можете скушать помидорку и всё проходит — ничего вы о лени не знаете.
masterL
15.10.2016 10:38Может быть очень скучная работа? Программирование этой задачи вызывает в вас отторжение? Если да, то это нормально, что не хочется этим заниматься.
Как насчет награды? Есть ли что-то желанное что можно прикрепить к успешному завершению работы над этой задачей в этот день?Snakecatcher
15.10.2016 10:48Не, в моём случае я прошел большой путь, чтобы хобби и работа совпали. )) С учетом почти полной творческой свободы, задания действительно интересные.
Единственный камень — это боязнь первого листа, когда надо начать писать большой модуль. Вот тут очень помогает.
Первую версию, я писал для прошлого себя, который учился в институте. И некоторые предметы были очень скучными.
А вторая, уже более продуманная с расписанием, сейчас используется.
Snakecatcher
15.10.2016 10:51Про лень. В глубине души я понимаю, что действительно могу сделать большее, чем делаю сейчас. Но иногда отвлекаюсь на посторонние вещи (в более глобальном смысле), на игры, на чтение художественной литературы.
n43jl
15.10.2016 11:20+1А что плохого в том, чтобы отвлекаться на чтение художественной литературы или игры? Переключение позволяет отдохнуть и книги и игры могут быть интересными и развивающими. А отдохнувшему мозгу легче быть креативным и продуктивным. Все хорошо в меру: работать, играть, читать и отдыхать.
Snakecatcher
15.10.2016 12:58Наверное неплохо, но когда куча литературы по специальности не прочитано — жалко времени.
Хотя, это может мои заморочки.
vrazrabotchik
15.10.2016 00:43К сожалению не сделал для айфона, очень хотелось. Не нашёл.
Snakecatcher
15.10.2016 00:45Увы, под iOS, пока не планирую работать.
Но если руки дойдут, обязательно сделаю приложение.
Из интереса, посдкажите разве под iOS, нет подобных приложений?vrazrabotchik
15.10.2016 12:23-1К сожалению нету, есть только будильники но есть одно такое нормальное, но оно платно.
Snakecatcher
15.10.2016 23:04Скорее всего это связано с высокой платой для разработчика. Поправьте меня, если неправ — около 100 долларов в год.
zyrik
15.10.2016 18:55Похоже приложение забирает wakelock и не отпускает его — активное всё время. Экран же очень быстро высаживает батарейку, так что если очень много работать, можно в конце остаться без рабочего телефона. Можно ли добавить какой-то звук или вибрацию в приложение, и гасить экран?
lohmatiyy
15.10.2016 23:03В Telegram есть достаточно удобный @pomodoro_timer_bot. Хорош тем, что реализована кастомная клавиатура, так что не нужно мучительно вспоминать его систему команд.
Antilopa-1
16.10.2016 14:02Если кому нужен для Windows — посмотрите бесплатный помодоро — TaskBoardTimer
Per_Ardua
Спасибо, а какое название у приложения? Можно в личку, если в комментах запрещено правилами =)
Snakecatcher
«Таймер трудового человека», как на картинке :)