Processing:Библиотеки/Processing for Android/Руководства/Циферблаты: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки
 
Нет описания правки
 
(не показана 1 промежуточная версия этого же участника)
Строка 4: Строка 4:
{{Myagkij-редактор}}
{{Myagkij-редактор}}


{{Черновик}}
 


=Циферблаты<ref>[https://android.processing.org/tutorials/watchfaces/index.html android.processing.org - Watch Faces]</ref>=
=Циферблаты<ref>[https://android.processing.org/tutorials/watchfaces/index.html android.processing.org - Watch Faces]</ref>=
Строка 26: Строка 26:
Давайте создадим максимально простой циферблат, который будет просто показывать время при помощи текста. Структура этого скетча проста:
Давайте создадим максимально простой циферблат, который будет просто показывать время при помощи текста. Структура этого скетча проста:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
void setup() {
void setup() {
   fullScreen();
   fullScreen();
Строка 53: Строка 53:
Мы можем генерировать паттерны и фигуры, меняющиеся по мере истечения определенного времени – часов, минут и секунд. В коде ниже мы постепенно закрашиваем экран черным цветом слева направо по мере того, как время течет от одной полуночи к другой. Мы также можем нажать на экран, добавив на еще «непоглощенную» часть экрана точку, которая исчезнет, если до нее в течение дня доберется эта неумолимо двигающаяся черная «пелена времени».
Мы можем генерировать паттерны и фигуры, меняющиеся по мере истечения определенного времени – часов, минут и секунд. В коде ниже мы постепенно закрашиваем экран черным цветом слева направо по мере того, как время течет от одной полуночи к другой. Мы также можем нажать на экран, добавив на еще «непоглощенную» часть экрана точку, которая исчезнет, если до нее в течение дня доберется эта неумолимо двигающаяся черная «пелена времени».


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
ArrayList<PVector> dots;
ArrayList<PVector> dots;
int totalMin = 24 * 60;
int totalMin = 24 * 60;
Строка 104: Строка 104:
Импортировав классы Vibrator и Context, инициализируем в блоке setup() экземпляр класса Vibrator:
Импортировав классы Vibrator и Context, инициализируем в блоке setup() экземпляр класса Vibrator:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
import android.os.Vibrator;
import android.os.Vibrator;
import android.content.Context;
import android.content.Context;
Строка 123: Строка 123:
Метод vibrator() позволяет нам задать вибрацию на определенное время (в миллисекундах). Делаем вибрацию длиной в полсекунды:
Метод vibrator() позволяет нам задать вибрацию на определенное время (в миллисекундах). Делаем вибрацию длиной в полсекунды:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
for (int i = dots.size()-1; i >= 0; i--) {
for (int i = dots.size()-1; i >= 0; i--) {
     PVector d = dots.get(i);
     PVector d = dots.get(i);
Строка 137: Строка 137:
Большинство устройств Android, включая смарт-часы, оснащены [https://developer.android.com/guide/topics/sensors/sensors_motion.html#sensors-motion-stepcounter шагомером], доступ к которому можно получить тем же способом, которым мы пользовались в предыдущих руководствах для доступа к данным других датчиков. «Скелет» этого скетча будет выглядеть следующим образом:
Большинство устройств Android, включая смарт-часы, оснащены [https://developer.android.com/guide/topics/sensors/sensors_motion.html#sensors-motion-stepcounter шагомером], доступ к которому можно получить тем же способом, которым мы пользовались в предыдущих руководствах для доступа к данным других датчиков. «Скелет» этого скетча будет выглядеть следующим образом:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
import android.content.Context;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.Sensor;
Строка 182: Строка 182:
В этом коде мы задаем менеджера, датчик и слушателя так же, как и в предыдущих похожих скетчах-примерах. Значение, хранящее в себе данные о насчитанных шагах – это event.values[0], которое мы можем сохранить в нашу собственную переменную.
В этом коде мы задаем менеджера, датчик и слушателя так же, как и в предыдущих похожих скетчах-примерах. Значение, хранящее в себе данные о насчитанных шагах – это event.values[0], которое мы можем сохранить в нашу собственную переменную.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
int offset = -1;
int offset = -1;
int steps;
int steps;
Строка 199: Строка 199:
Наконец, мы можем добавить в блок setup() инициализацию шрифта, а затем воспользоваться данными о посчитанных шагах в блоке draw(). К примеру, ниже они просто печатаются как текст:
Наконец, мы можем добавить в блок setup() инициализацию шрифта, а затем воспользоваться данными о посчитанных шагах в блоке draw(). К примеру, ниже они просто печатаются как текст:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
void setup() {
void setup() {
   fullScreen();
   fullScreen();
Строка 251: Строка 251:
|Высота логотипа издателя для schemaNewsArticle=45
|Высота логотипа издателя для schemaNewsArticle=45
}}
}}
{{Навигационная таблица/Справочник языка Processing}}
{{Навигационная таблица/Портал/Processing}}

Текущая версия от 11:56, 20 мая 2023


Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.



Циферблаты[1]

В этом руководстве рассказывается, как использовать режим программирования Android для разработки интерактивных циферблатов.

Циферблаты

Операционная система Android Wear позволяет создавать кастомные циферблаты для смарт-часов, которые, используя возможности дисплея и интерактивные функции этих устройств, могут показывать время каким-либо нестандартным образом. Кроме того, вы можете считывать данные датчиков тела (шагомеров, пульсометров и т.д.), чтобы визуализировать физическую активность пользователя. Разработка циферблатов, впрочем, требует определенных опыта и знаний – из-за ограничений этих устройств, связанных с размером экрана и максимальным зарядом батареи. Руководства Google по созданию циферблатов можно почитать тут.

Подготовка

Во-первых, разработка циферблатов требует двух устройств – смарт-часов и смартфона, который будет служить «мостиком» между компьютером, на котором запущен Processing, и смарт-часами. Для этого вам нужно настроить в устройствах отладку через Bluetooth, и о том, как это сделать, можно почитать тут. Разобравшись с этим, кликните в PDE на Android > Watch Face.

После того, как вы настроите отладку Bluetooth и выберите в PDE опцию Watch Face, смарт-часов в списке подключенных устройств по-прежнему не будет. Это нормально, потому что циферблаты не устанавливаются в смарт-часы напрямую – сначала они устанавливаются на телефон, с которым сопряжены смарт-часы, а затем через Bluetooth автоматически копируются на смарт-часы.

Создание очень простого циферблата

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

void setup() {
  fullScreen();
  frameRate(1);
  textFont(createFont("SansSerif", 30 * displayDensity));
  fill(255);
}

void draw() {
  background(0);
  translate(0, +wearInsets().bottom/2);
  if (!wearAmbient()) {
    String str = hour() + ":" + minute() + ":" + second();
    float w = textWidth(str);
    text(str, (width - w)/2, height/2 + 24);     
  }
}

В этом коде есть несколько любопытных вещей. Во-первых, это частота кадров в размере «1», поскольку текст будет меняться только раз в секунду и обновлять его чаще нет никакого смысла (тем более, что это будет расходовать заряд батареи). Кроме того, циферблат будет нарисован, только если встроенная функция wearAmbient() вернет false. Причина в том, что если она вернет true, то это значит, что человек, носящий эти смарт-часы, на них не смотрит, в результате чего они переключаются в режим ожидания (англ. «ambient mode»), чтобы сэкономить заряд батареи. В режиме ожидания дисплей обновляется только раз в минуту, и рекомендуется, чтобы большая часть экрана была черной и показывала только упрощенную версию циферблата.

Кроме того, мы используем в этом коде функцию wearInsets(), чтобы получить данные о вставках на экране. В частности, нижняя вставка позволяет правильно отцентрировать графику скетча на циферблатах с «подбородком» в нижней части экрана (вроде Moto 360) и в результате весь кадр, чтобы получить правильную отцентровку, сдвигается вниз на половину этого значения. Есть еще одна важная встроенная переменная, которую мы здесь не используем – это isRound, которая сообщает форму циферблата (т.е. квадратную или круглую). Полный список встроенных переменных для циферблатов смотрите в справочнике библиотеки Android for Processing.

Время показа

Мы можем генерировать паттерны и фигуры, меняющиеся по мере истечения определенного времени – часов, минут и секунд. В коде ниже мы постепенно закрашиваем экран черным цветом слева направо по мере того, как время течет от одной полуночи к другой. Мы также можем нажать на экран, добавив на еще «непоглощенную» часть экрана точку, которая исчезнет, если до нее в течение дня доберется эта неумолимо двигающаяся черная «пелена времени».

ArrayList<PVector> dots;
int totalMin = 24 * 60;

void setup() {
  fullScreen();
  frameRate(1);
  dots = new ArrayList<PVector>();
}

void draw() {
  int time = hour() * 60 + minute();
  if (time == 0) dots.clear();
  float x = map(time, 0, totalMin, 0, width);
  if (wearAmbient()) {
    background(0);
    noFill();
    stroke(255);    
    line(x, 0, x, height);
    for (PVector d: dots) {
      ellipse(d.x, d.y, 10, 10);
    }    
  } else {
    background(255);
    fill(0);
    noStroke();
    rect(0, 0, x, height);
    for (PVector d: dots) {
      ellipse(d.x, d.y, 10, 10);
    }    
  }
  
  for (int i = dots.size()-1; i >= 0; i--) {
    PVector d = dots.get(i);
    if (d.x < x) {
      dots.remove(i);
    }
  }  
} 

void mousePressed() {
  dots.add(new PVector(mouseX, mouseY));
}

Теперь давайте сделаем так, чтобы смарт-часы вибрировали с каждым разом, когда черная «пелена» поглощает добавленную пользователем точку! Чтобы получить доступ к вибрирующему механизму в смарт-часах, вам нужно включить соответствующее разрешение. Для этого в среде разработки Processing нужно нажать на Android > Sketch Permissions, а затем поставить галочку у опции VIBRATE.

Импортировав классы Vibrator и Context, инициализируем в блоке setup() экземпляр класса Vibrator:

import android.os.Vibrator;
import android.content.Context;
  
ArrayList<PVector> dots;
int totalMin = 24 * 60;
Vibrator vibrator;

void setup() {
  fullScreen();
  frameRate(1);
  dots = new ArrayList<PVector>();
  Context context = getContext();
  vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
}

Метод vibrator() позволяет нам задать вибрацию на определенное время (в миллисекундах). Делаем вибрацию длиной в полсекунды:

for (int i = dots.size()-1; i >= 0; i--) {
    PVector d = dots.get(i);
    if (d.x < x) {
      dots.remove(i);
      vibrator.vibrate(500);
    }
  }

Счетчик шагов

Большинство устройств Android, включая смарт-часы, оснащены шагомером, доступ к которому можно получить тем же способом, которым мы пользовались в предыдущих руководствах для доступа к данным других датчиков. «Скелет» этого скетча будет выглядеть следующим образом:

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;

SensorManager manager;
Sensor sensor;
SensorListener listener;

void setup() {
  fullScreen();
  frameRate(1);
  
  Context context = getContext();
  manager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
  sensor = manager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);  
  listener = new SensorListener();  
  manager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);  
}

void draw() {
}

public void resume() {
  if (manager != null) {
    manager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
  }
}

public void pause() {
  if (manager != null) {
    manager.unregisterListener(listener);
  }
}

class SensorListener implements SensorEventListener {
  public void onSensorChanged(SensorEvent event) { }
  public void onAccuracyChanged(Sensor sensor, int accuracy) { }
}

В этом коде мы задаем менеджера, датчик и слушателя так же, как и в предыдущих похожих скетчах-примерах. Значение, хранящее в себе данные о насчитанных шагах – это event.values[0], которое мы можем сохранить в нашу собственную переменную.

int offset = -1;
int steps;

...

class SensorListener implements SensorEventListener {
  public void onSensorChanged(SensorEvent event) {
    if (offset == -1) offset = (int)event.values[0]; 
    steps = (int)event.values[0] - offset;
  }
  public void onAccuracyChanged(Sensor sensor, int accuracy) { }
}

Наконец, мы можем добавить в блок setup() инициализацию шрифта, а затем воспользоваться данными о посчитанных шагах в блоке draw(). К примеру, ниже они просто печатаются как текст:

void setup() {
  fullScreen();
  frameRate(1);

  textFont(createFont("SansSerif", 30 * displayDensity));
  textAlign(CENTER, CENTER);
  fill(255);  
  
  Context context = getContext();
  manager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
  sensor = manager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);  
  listener = new SensorListener();  
  manager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);  
}

void draw() {
  background(0);
  translate(0, +wearInsets().bottom/2);
  if (!wearAmbient()) {
    String str = steps + " steps";
    float w = textWidth(str);
    text(str, 0, 0, width, height);     
  }
}

Вы, возможно, захотите сохранить данные о посчитанных шагах, чтобы отслеживать профиль активности пользователя. В языке Processing есть несколько функций для сохранения и загрузки данных в циферблат – к примеру, saveStrings() и loadStrings(). Впрочем, вам также нужно удостовериться, что у вас включено разрешение WRITE_EXTERNAL_STORAGE.

Примечание: Если вы имеете дело с опасным разрешением (вроде WRITE_EXTERNAL_STORAGE), то его запрос в коде нужно сделать явно – как объясняется в этом руководстве. После этого вам также надо дать соответствующее разрешение в самом устройстве – либо через уведомление, которое будет запущено циферблатом, либо перейдя в настройки разрешений для циферблата (о том, как это сделать, можно прочесть тут).

См.также

Внешние ссылки