Литмир - Электронная Библиотека
Содержание  
A
A

Представленный в листинге 13.1 код демонстрирует несколько полезных концепций построения гибких пользовательских интерфейсов мобильных устройств. Проектируя этот пользовательский интерфейс, я начал с идеи размещения элементов поверх игрового поля. Зная, что окончательный выбор подходящего пользовательского интерфейса определится лишь после его тестирования в реальных условиях и внесения соответствующих изменений, при написании кода было желательно использовать принципы централизации и абстрагирования кода таким образом, чтобы процесс его модифицирования не вызывал особых затруднений и не заставлял вносить сложные изменения в разных местах кода пользовательского интерфейса или логики приложения. Именно поэтому я решил поместить основную часть кода динамической компоновки в функцию конечного автомата, которая называется StateChangeForGameUI(). Любые изменения размеров или позиционирование элементов управления управляются этим кодом. Если нам необходимо немного подправить компоновку элементов или даже радикально изменить ее, мы знаем, что все необходимое осуществляется здесь; благодаря этому снижается объем работы по отслеживанию сложной и разбросанной по всему коду логики компоновки, а приложение становится более надежным. Возложив всю ответственность за поддержание компоновки пользовательского интерфейса на одну функцию (конечный автомат), мы значительно облегчили выполнение экспериментов с различными возможными вариантами компоновки, поскольку теперь это не сможет дестабилизировать работу остальной части кода пользовательского интерфейса и логики приложения.

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

Программирование мобильных устройств на платформе .NET Compact Framework - image092.jpg

Рис. 13.6. Отображение пользовательского интерфейса в верхней части формы

На рис. 13.7 текстовое окно динамически изменяет свои размеры, располагаясь ниже всех остальных кнопок, находящихся на экране. Так как в обоих случаях привязка расположения текстового окна к окружающим его элементам осуществляется по-разному, в приложении для каждого из этих случаев предусмотрена своя логика. Столь же легко реализовать и другие возможные варианты расположения и упорядочения элементов управления; поскольку код, ответственный за позиционирование, надежно абстрагирован и централизован в одном конечном автомате, мы можем получить любое желаемое расположение элементов на экране, выполняя ту логику пользовательского интерфейса, которая для этого нужна. Остальная часть логики пользовательского интерфейса и приложения нашими экспериментами не затрагивается.

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

Программирование мобильных устройств на платформе .NET Compact Framework - image094.jpg

Рис. 13.7. Отображение пользовательского интерфейса в нижней части формы

Такое сочетание абстрагирования и централизации значительно упрощает изменение конфигурации пользовательского интерфейса с целью использования тех или иных элементов управления в соответствии с необходимостью. Это важно не только с точки зрения того, чтобы интерфейс принял очертания, наиболее подходящие для устройств любого заданного класса, но и с точки зрения переносимости приложения с одного устройства на другое. Например, если наше мобильное приложение необходимо перенести на смартфон, то в нем, вероятно, следует использовать другой набор элементов управления пользовательского ввода-вывода. Поскольку в смартфонах сенсорный экран отсутствует, кнопки не являются наилучшим решением для выбора правильного варианта ответа из нескольких предложенных; в этом случае гораздо лучше использовать списки.

Переделка кода, приведенного в листинге 13.1, для использования списка вместо кнопок множественного выбора не составляет особого труда. Потребовалось бы внести еще и другие изменения в код пользовательского интерфейса, но в силу того, что логика приложения и код пользовательского интерфейса надежно инкапсулированы, а взаимодействие между ними централизовано в известном наборе функций, работа по переносу приложения не должна доставить особых затруднений. Тщательно продуманная инкапсуляция, абстрагирование и централизация обеспечивают возможность создания отличных пользовательских интерфейсов для любых классов устройств с гораздо большей легкостью, чем в случае децентрализованного кода и без использования конечного автомата.

Пример кода, демонстрирующий две различные модели компоновки для одного и того же приложения

Приведенный в листинге 13.1 код вносится в форму в проекте Pocket PC. Для создания и запуска приложения потребуется выполнить следующие действия:

1. Запустите Visual Studio .NET (2003 или более позднюю версию) и выберите в качестве типа приложения C# Smart Device Application.

2. Выберите в качестве целевой платформы Pocket PC. (Для вас будет автоматически создан проект, и на экране появится окно конструктора форм Pocket PC.)

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

 • TextBox; переименуйте его в textBoxAskQuestion, установите значение true для его свойств MultiLine и ReadOnly.

 • PictureBox; переименуйте его в pictureBoxGameBoard.

 • Button; переименуйте его в buttonShowAnswers_AdvancedVersion.

 • Button; переименуйте его в buttonShowAnswers_SimpleVersion.

 • Button; переименуйте его в buttonAskQuestion.

 • Button; переименуйте его в buttonAnswer0. 

 • Button; переименуйте его в buttonAnswer1. 

 • Button; переименуйте его в buttonAnswer2.

 • Button; переименуйте его в buttonAnswer3.

 • Button; переименуйте его в buttonAnswer4. 

 • Button; переименуйте его в buttonAnswer5. 

4. Дважды щелкните на пустом участке формы в окне конструктора форм и введите приведенный ниже код Form_Load в автоматически сгенерированную и подключенную функцию обработчика событий.

5. Поочередно переходя от одной из вышеперечисленных кнопок Button к другой, щелкните на кнопке в окне конструктора форм. Введите приведенный ниже код button<ИмяКнопки>_Click в автоматически сгенерированную и подключенную функцию обработчика событий.

6. Введите оставшуюся часть приведенного ниже кода.

7. Установите для свойства MinimizeBox формы значение false. Благодаря этому во время выполнения приложения в верхней правой части формы появится кнопка OK, с помощью которой вы сможете легко закрыть форму и выйти из приложения. Эта возможность оказывается очень полезной при многократном тестировании приложения

8. В самом верху файла кода формы введите в качестве первой строки #define PLAYFIELD_ON_BOTTOM. 

9. Дважды запустите приложение: один раз с подключенной директивой условной компиляции #define PLAYFIELD_ON_BOTTOM, а второй — с предварительным отключением этой же директивы при помощи символов комментария (то есть //#define PLAYFIELD_ON_BOTTOM), и отметьте для себя различия между двумя моделями компоновки. Запустите оба варианта на физическом устройстве и выясните, какая модель является более предпочтительной с точки зрения внешнего вида приложения и удобства работы с ним, а также возможностей обзора игрового поля.

142
{"b":"947732","o":1}