Статьи

Создание средства просмотра миниатюр Panoramio во Flex

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

Чтобы собрать все это вместе, мы будем использовать API Panoramio и создадим динамический просмотрщик миниатюр изображений.


Вот просмотрщик миниатюр, над которым мы работаем:

С момента появления графических операционных систем появилось несколько стандартных элементов управления пользовательского интерфейса, таких как кнопки, метки, текстовые поля и списки. Эти элементы управления хорошо справились со своей работой, но хотя Vista, Windows 7, MacOS, KDE и Gnome приносят нам новые новые визуальные разработки, разработчики довольно часто застряли в разработке собственных приложений с элементами управления, которые не изменили свою основную функцию за 20 лет ,

Неважно, делаете ли вы веб-страницу, программируете приложение для Windows с VB.Net или создаете RIA с Flex; когда вы переходите к нему, список остается списком, а кнопка — кнопкой.

К счастью, Flex предлагает разработчикам удобный способ настройки скромного списка, предоставляя гораздо более интересные дизайны, чем стандартные строки текста. Мы будем использовать эту функциональность для создания программы просмотра изображений Panoramio.

Создайте новый проект Flex. Поскольку мы будем извлекать фотографии из Panoramio (который возвращает объект JSON), нам нужно обратиться к библиотеке AS3CoreLib (которая может преобразовывать текст JSON в объект ActionScript), которую вы можете скачать здесь . Извлеките архив, а затем добавьте ссылку на него в «Путь сборки Flex».

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

Новые состояния можно добавлять с помощью кнопки «Новое состояние» на панели инструментов «Состояния».

Мы хотим добавить два состояния. Первый будет называться «Миниатюры». Нажмите кнопку «New State» и заполните диалоговое окно, как показано на скриншоте ниже. Обратите внимание, что мы отметили «Установить как начальное состояние», что говорит Flex, что это состояние будет отображаться первым.

Нам также нужно состояние под названием «Деталь». Снова, нажмите кнопку «New State» и заполните диалоговое окно, как на скриншоте ниже.

Выберите состояние «Миниатюры» на панели инструментов «Состояния».

Теперь нарисуйте новый компонент TileList на GUI. Этот компонент будет использоваться для отображения миниатюр фотографий.

Присвойте TileList идентификатор «thumbnails» и установите для «Data Provider» значение {images} . Flex позволяет писать код ActionScript в атрибутах элемента MXML, заключая код в фигурные скобки, и мы используем эту функцию здесь, чтобы установить коллекцию изображений (которую мы создадим позже) в качестве источника данных для TileList.

Выберите состояние «Сведения» на панели инструментов «Состояния».

Нарисуйте элемент управления изображением с идентификатором «photo», который занимает большую часть экрана. Затем внизу добавьте две метки с идентификаторами «photoTitle» и «photoLocation» и кнопку с меткой «Back».

Нам также нужно установить для свойства «On click» кнопки значение {this.currentState = ‘Thumbnails’} . Изменение значения, присвоенного свойству «currentState», — это то, как мы меняемся между состояниями во Flex, и точно так же, как и со свойством «Data Provider» в TileList на шаге 3, мы встраиваем некоторый код ActionScript в атрибут, заключая его в фигурные скобки. , Присваивая строку «Миниатюры» свойству «currentState», мы инструктируем Flex вернуться в состояние «Миниатюры».

Ваш окончательный интерфейс для состояния Detail должен выглядеть как на скриншоте ниже.

Компоненты MXML можно использовать для определения того, как отдельные плитки отображаются в компоненте TileList. Нажмите Файл> Создать> Компонент MXML.

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

Когда вы закончите, вы попадете на экран проектирования, где вы сможете рисовать компоненты так же, как и в основном приложении Flex.

Этот MXML-компонент будет использоваться для рисования отдельных фотографий в TileList. Как видите, у вас почти неограниченная свобода в дизайне плиток. Каждая плитка может быть разработана с любым элементом управления Flex в любом макете, который вам нравится.

Свобода конструировать каждую плитку индивидуально — вот что делает TileList и другие элементы управления, такие как «DataGrid», «HorizontalList», «List», «Menu» и «Tree», такими мощными. Фактически, я никогда не видел, чтобы какой-либо другой инструментарий GUI давал разработчикам такой уровень настройки без необходимости разрабатывать новый элемент управления с нуля.

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

Установите для свойства Текст метки значение {data.photo_title.length> 30? data.photo_title.substr (0, 27) + ‘…’: data.photo_title} . Здесь мы отображаем свойство «photo_title» объекта, который привязан к компоненту (мы увидим, как это связывание выполняется позже), используя тернарный оператор (в основном сокращенное выражение if..else).

Если это 30 символов или меньше, будет отображаться полная строка. В противном случае мы отображаем первые 27 символов, за которыми следуют 3 периода, чтобы указать, что заголовок был сокращен.

Установите для свойства «Источник» изображения значение {data.photo_file_url} . Мы снова используем ActionScript для извлечения свойства «photo_file_url» объекта, который связан с компонентом.

Вернитесь к основному файлу MXML и переключите редактор в представление «Источник».

Вы должны увидеть элемент состояний, добавленный к элементу Application. Это разметка, которая представляет состояния, которые мы определили на шаге 2.

Под элементом states должно быть два элемента State, а под каждым из них будут элементы AddChild. Они относятся к компонентам, которые мы добавили к каждому состоянию.

Под элементом State с именем «Thumbnails» вы должны увидеть элемент AddChild, который содержит элемент TileList. Это TileList, который мы добавили на шаге 3. Нам нужно добавить некоторые дополнительные атрибуты ниже, чтобы TileList отображал наш пользовательский компонент MXML.

1
itemRenderer=»ImageThumbnail» itemDoubleClick=»photoSelected()» doubleClickEnabled=»true»

Таким образом, весь элемент TileList должен читать:

1
<mx:TileList itemRenderer=»ImageThumbnail» itemDoubleClick=»photoSelected()» doubleClickEnabled=»true» dataProvider=»{images}» id=»thumbnails» bottom=»0″ top=»0″ left=»0″ right=»0″/>

Атрибут itemRenderer — это имя компонента MXML, который мы создали на шаге 5.

Атрибут itemDoubleClick устанавливает функцию «photoSelected», которая вызывается при двойном щелчке элемента.

Атрибут «doubleClickEnabled» указывает компоненту обрабатывать два щелчка мыши как один двойной щелчок. Без этого атрибута компонент будет обрабатывать двойной щелчок как два отдельных щелчка, и событие itemDoubleClick никогда не будет запущено.

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

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

1
2
3
<mx:transitions>
<!— Individual transitions go here —>
</mx:transitions>

Внутри элемента переходов мы добавим элемент Перехода.

1
2
3
<mx:Transition fromState=»*» toState=»*»>
<!— Transition effects go here —>
</mx:Transition>

Атрибуты fromState и toState определяют состояния, к которым будет применяться переход. Здесь мы использовали звездочку в качестве подстановочного знака, который соответствует всем состояниям, что означает, что эффект перехода будет применяться при переходе из любого старого состояния в любое новое состояние.

Внутри элемента Transition мы определяем эффект istelf.

1
<mx:Blur target=»{this}» duration=»500″ blurYFrom=»20.0″ blurYTo=»1.0″ blurXFrom=»20.0″ blurXTo=»1.0″ />

Атрибут «target» определяет, к какому компоненту (и его дочерним элементам) будет применен эффект размытия. В этом случае мы хотим, чтобы все элементы были размыты, поэтому мы устанавливаем цель так, чтобы она указывала на «это».

Атрибут «duration» определяет продолжительность применения эффекта размытия в миллисекундах. Мы использовали 500 здесь, что составляет полсекунды.

Атрибуты blurYFrom и blurXFrom определяют, насколько размытым будет эффект на начальном этапе. Большие значения делают начальный эффект более размытым.

Атрибуты blurYTo и blurXTo определяют, насколько размытым будет эффект в конце продолжительности. Мы хотим вернуть экран в четкую фокусировку, поэтому мы присваиваем значения 1 каждому атрибуту.

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

Добавьте следующий атрибут в элемент Application:

1
applicationComplete=»appComplete()»

Это устанавливает функцию appComplete, которая будет вызываться при инициализации приложения.

Добавьте элемент «Сценарий» в элемент приложения MXML. Это дает нам место для написания кода ActionScript.

1
2
3
4
5
6
<mx:Script>
<![CDATA[
 
// Code goes here
]]>
</mx:Script>

В элементе Script импортируйте следующие пакеты.

1
2
3
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import com.adobe.serialization.json.JSON;

По умолчанию Flex не позволяет загружать ресурсы из внешнего домена. Однако это поведение можно изменить, если в удаленном домене есть файл политики безопасности междоменного домена (обычно crossdomain.XML). К счастью, Panoramio имеет именно такой файл политики, который мы загружаем с помощью следующего кода:

1
Security.loadPolicyFile(«http://www.panoramio.com/crossdomain.xml»);

На шаге 3 мы устанавливаем свойство «Поставщик данных» TileList в коллекцию под названием «images». Именно здесь мы на самом деле определяем эту коллекцию. Используя тег «Bindable» для переменной, мы говорим Flex следить за любыми изменениями в коллекции и автоматически отображать эти изменения.

1
[Bindable] private var images:ArrayCollection = null;

Добавьте функцию под названием «appComplete».

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
private function appComplete():void
{
    var panoramioURL:String = «http://www.panoramio.com/map/get_panoramas.php?order=popularity&set=public&from=0&to=50&minx=-180&miny=-90&maxx=180&maxy=90&size=medium»;
    var request:URLRequest = new URLRequest(panoramioURL);
    var loader:URLLoader = new URLLoader(request);
    loader.addEventListener(Event.COMPLETE, loaderComplete);
    loader.addEventListener(
        IOErrorEvent.IO_ERROR,
        function(event:Event):void
        {
            Alert.show(«There was an IO error contacting Panoramio»);
        }
    );
    loader.addEventListener(
        SecurityErrorEvent.SECURITY_ERROR,
        function(event:Event):void
        {
            Alert.show(«There was a security error contacting Panoramio»);
        }
    );
}

Получение изображений из Panoramio на самом деле очень просто. В отличие от других сайтов с изображениями, таких как Flickr , Panoramio не требует от разработчика получения API или использования специального API. Вы просто делаете HTTP-запрос к специально отформатированному URL-адресу (на странице API Panoramio есть все детали) и используете возвращенный JSON для получения доступа к изображениям.

Во Flex это означает создание объекта «URLRequest» с URL Panoramio, затем создание нового «URLLoader», передавая этот запрос в конструктор. Затем нам нужно отслеживать три события из URLLoader: Event.COMPLETE , IOErrorEvent.IO_ERROR и SecurityErrorEvent.SECURITY_ERROR .

Событие Event.COMPLETE показывает, что все прошло хорошо, и что сервер Panoramio вернул нам необходимую информацию. В этом случае мы вызываем функцию «loaderComplete».

События IOErrorEvent.IO_ERROR и SecurityErrorEvent.SECURITY_ERROR указывают, что что-то пошло не так. В этом случае мы уведомляем пользователя о том, что не можем связаться с сервером Panoramio, и не идем дальше.

Теперь добавьте новую функцию с именем «loaderComplete».

1
private function loaderComplete(event:Event):void { var response:URLLoader = URLLoader(event.target);

Здесь мы берем JSON, возвращенный Panoramio, и преобразуем его в объект ActionScript, используя библиотеку AS3CoreLib из шага 1.

Один из приемов при работе с веб-сервисами — узнать, какие данные действительно были возвращены. Если вы используете Firefox, есть отличное дополнение JSONovich, которое будет форматировать код JSON в браузере. На снимке экрана ниже вы можете увидеть отформатированный файл JSON, который был возвращен из веб-службы Panoramio. Обратите внимание, что объект JSON имеет свойство «count» и массив «photos», который содержит объекты, которые, в свою очередь, содержат сведения об отдельных фотографиях.

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

Поскольку коллекция изображений имеет тег «Bindable», добавление этих объектов в коллекцию приведет к их отображению. Если вы вернетесь к шагу 5, то заметите, что значения метки и изображения были установлены в свойствах объекта с именем «данные». Этот объект данных на самом деле ссылается на элемент в коллекции изображений, и если вы посмотрите на скриншот выше, то увидите, откуда появились свойства photo_file_url и photo_title.

Последняя функция называется «photoSelected».

01
02
03
04
05
06
07
08
09
10
private function photoSelected():void
{
    this.currentState = «Detail»;
     
    var selectedPhoto:Object = this.thumbnails.selectedItem;
     
    this.photo.source = selectedPhoto.photo_file_url;
    this.photoTitle.text = selectedPhoto.photo_title;
    this.photoLocation.text = «Lat: » + selectedPhoto.latitude + » Long: » + selectedPhoto.longitude;
}

Эта функция вызывается, когда пользователь дважды щелкает элемент в TileList. Здесь мы устанавливаем текущее состояние «Подробно» и устанавливаем свойства изображения и меток, используя свойства выбранного элемента TileList.

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