Суббота, 09.08.2025
Скачай бесплатно и быстро
Меню сайта
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Форма входа
Главная » 2010 » Январь » 12 » Скроллинг акселерометром
23:17
Скроллинг акселерометром

http://pyobjc.ru/2008/09/30/skrolling-pri-pomoshi-akselerometra/?reply_to=367

Одной из самых "вкусных” функциональностей, которые предоставляет iPhone/iPod Touch, безусловно является акселерометр. Его реализация в устройствах от Apple не первая в мире — попытки внедрения модуля определения положения аппарата были и раньше, например, в телефонах от Sony Ericsson и Nokia, но действительно удачное применение удалось найти именно Apple, сделав акселерометр одной из главных отличительных черт своих телефонов и плееров.

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

Как и большинство классов, с которыми нам довелось познакомиться, API акселерометра прост до безобразия. Для его использования в своих программах нужно быть знакомым всего с двумя классами и одним делегатом. Но прежде чем приступить к знакомству с ними, создайте новый проект на основе шаблона "Window based application” в XCode. Я назвал его "accelerometer”.

Хочу заранее предупредить, что без сертификата разработчика попробовать в действии это приложение вам не удастся, как и любые примеры с сайта developer.apple.com, работающие с информацией о положении аппарата в пространстве, так как в симуляторе нет возможности эмулировать вращение устройства. Но информации в статье достаточно, чтобы составить представление о функционировании акселерометра, знания о работе с которым пригодятся вам в будущем и позволят писать приложения, использующие его функциональность, уже сейчас.

Первым делом нам потребуется создать в нашей программе Table View и заполнить его буквами алфавита. Для этих целей воспользуемся готовым объектом UITableViewController, который немного упростит нам дальнейшую работу с таблицей. Для тех, кто еще не был знаком с UITableView, отправляю к статье Вездесущий UITableView, а остальные откройте MainWindow.xib и добавьте на форму объект UITableViewController.

UITableViewController в Interface Builder

dataSource и delegate для нашей таблицы автоматически установлены на объект UITableViewController. Чтобы описать методы, ответственные за наполнение таблицы данными, измените класс UITableViewController на tableViewController, сгенерируйте файлы класса и включите их в состав проекта.

Чтобы наша таблица отображалась в окне приложение, добавьте outlet переменную viewController класса tableViewController в класс accelerometerAppDelegate, и свяжите ее с объектом tableViewController на форме через Interface Builder. А в методе applicationDidFinishLaunching: добавьте следующую строчку:


[window addSubview:viewController.view];

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

В accelerometerAppDelegate.h объявите переменную list класса NSMutableArray, в которую мы поместим сгенерированный нами алфавит. В этом нам поможет метод stringWithFormat класса NSString, в котором мы будем формировать символы по кодам из нижней части ACSII таблицы. Код поместим во все тот же applicationDidFinishLaunching:.


list = [[NSMutableArray alloc] init];

for (int i = 65; i < 65+26; i++) {
 [list addObject:[NSString stringWithFormat:@"%c", i]];
}

Не забудьте освободить переменную list в dealloc.

Нам осталось сформировать код, ответственный за заполнение таблицы данными. Подробно останавливаться на нем не буду, лишь приведу исходный текст tableViewController.m.


#import "tableViewController.h"
#import "accelerometerAppDelegate.h"

@implementation tableViewController

— (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
 return 1;
}

— (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
 accelerometerAppDelegate *appDelegate = (accelerometerAppDelegate *)[[UIApplication sharedApplication] delegate];
 return [appDelegate.list count];
}

— (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
 
 if (cell == nil) {
 cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"] autorelease];
 }
 
 accelerometerAppDelegate *appDelegate = (accelerometerAppDelegate *)[[UIApplication sharedApplication] delegate];
 cell.text = (NSString *)[appDelegate.list objectAtIndex:indexPath.row];
 
 return cell;
}

@end

Теперь, когда подготовительная фаза завершена, мы можем приступить к знакомству с акселерометром. Но прежде немного теории.

Акселерометр — устройство, измеряющее проекцию силы тяжести. С его помощью можно также установить величину ускорения аппарата под действием внешних сил. Для получения информации о величине и направлении ускорения используются значения проекций на оси координат.

Оси координат в iPhone
* изображение взято с сайта http://www.forestgumpsays.com/?p=42

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

Заметьте, это именно ускорение, а не скорость движения устройства. То есть, если ваш iPhone начнет падать на землю, то проекции величины ускорения примут значение 0 по всем осям — ваш iPhone будет в невесомости :) А если вы поднимаетесь с должным ускорением на лифте вверх, то значение силы тяжести на время ускорения увеличится.

Чтобы было понятнее, пользуясь значением по оси Z можно определить в каком положении находится аппарат: лицом вверх (-1, при нулевых значениях по другим осям), в вертикальном положении (0) или лицом вниз (+1).

Проекция вектора силы тяжести на ось Z

Ось Y дает нам следующую информацию: iPhone находится в вертикальном положении (-1), лежит в горизонтальной плоскости (0) или находится в вертикальном положении, только вверх ногами (+1).

Проекция вектора силы тяжести на ось Y

И, наконец, ось X дает информацию о повороте аппарата влево (-1) или вправо (+1).

Проекция вектора силы тяжести на ось X

Для случая произвольной ориентации iPhone данные о величине ускорения распределяются по осям согласно проекции вектора ускорения.

Проекция вектора силы тяжести на оси координат в произвольном положении iPhone

Всю эту информацию аккумулирует объект класса UIAcceleration, возвращающий данные по всем осям, а также временной маркер, позволяющий определить относительное время замера указанных величин. Напрямую подступиться к данным этого класса нельзя, эту информацию можно получить только через делегат UIAccelerometerDelegate, предоставляющего для реализации один единственный метод accelerometer:didAccelerate:, в который возвращается объект класса UIAcceleration. Назначение делегата и инициализация вызовов метода accelerometer:didAccelerate: происходит при помощи класса UIAccelerometer. Пришло время написать код, реализующий описанный алгоритм.

В метод applicationDidFinishLaunching: добавьте следующие строки.


[[UIAccelerometer sharedAccelerometer] setUpdateInterval:0.5];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];

Первая назначает интервал в секундах, с которым будут посылаться данные от акселерометра в класс-делегат, назначенный в следующей строке. В заголовочном файле класса accelerometerAppDelegate укажите протокол UIAccelerometerDelegate.


@interface accelerometerAppDelegate : NSObject <UIApplicationDelegate, UIAccelerometerDelegate>

Нам осталось только добавить реализацию метода в класс accelerometerAppDelegate.


— (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
}

Но что же мы должны в нем написать, чтобы реализовать прокрутку списка? Возьмем за точку отсчета положение нашего устройства в пространстве, при котором угол между задней стенкой и землей составляет 45 градусов. В этом случае проекции силы тяжести на ось Y будет составлять -0.7. Если мы отклоняем аппарат чуть ближе к вертикальному положению, то примем, что при достижении угла в 30 градусов от вертикали мы должны перелистнуть список к концу. И наоборот, при достижении угла в 30 и менее градусов от горизонтального положения, мы должны перелистнуть список к началу.

В первом случае абсолютная величина проекции силы тяжести на ось Y, направленная вдоль аппарата, станет равна 0.86. Те, кто не понял откуда взялось это значение, вспоминаем геометрию и вычисление проекции на ось координат вектора единичной длины. Во втором случае это же значение равно 0.5. Для реализации прокрутки мы воспользуемся методом scrollToRowAtIndexPath:atScrollPosition:animated: класса UITableView.


— (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
 double absY = fabs(acceleration.y);
		
	 
Просмотров: 718 | Добавил: kjh | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Поиск
Друзья сайта
  • Все для ПК смартфонов и телефонов