Пример работы с Adaptive Search - S60 Touch UI
Метаданные
Пример кода
Исходный файл: AdaptiveSearch.zip
Статья
Автор:
A.A.M.
(A.A.M.)
Последнее редактирование: hamishwillee
(09 Dec 2011)
Статья базируется на материалах англоязычной части Wiki, все они перечислены в разделе ссылки.
Contents |
Обзор
Адаптивный поиск - это совмещение возможностей сенсорного управления с существовавшим в предыдущих изданиях S60 интерфейсом CAknSearchField API. В данной статье мы рассмотрим пример работы с этим API.
Что такое адаптивный поиск
- При использовании адаптивного поиска, искомые символы изначально выводятся в виде сетки. С выбором каждого следующего символа, число оставшихся уменьшается в зависимости от количества совпадений, список фильтруется, сужая тем самым число возможных вариантов для следующего выбора и, соответственно, уменьшая общее время поиска.
- Адаптивный поиск интегрируется с CAknSearchField API.
- Обычно адаптивный поиск используется совместно с компонентом списка (List box).
- Системное приложение Контакты - это лучший пример наглядного использования функций адаптивного поиска в устройствах на S60 5-го издания.
Создание списка
- Прежде всего мы должны создать ресурсы для списка (listbox), который будет совмещен с CAknSearchField API и будет использован для демонстрации возможностей адаптивного поиска.
RESOURCE LISTBOX r_list_box
{
flags = EAknListBoxSelectionList;
array_id= r_list_box_item_array;
}
RESOURCE ARRAY r_list_box_item_array
{
items =
{
LBUF { txt = "\tAlbert Eienstein\t";},
LBUF { txt = "\tAlbert Makinstosh\t";},
LBUF { txt = "\tVikram Sarabhai\t";},
LBUF { txt = "\tSarabhai Anand\t";}
};
}
Реализация функционала адаптивного поиска
AdaptiveSearchAppView.h
- Унаследуем класс от MAdaptiveSearchTextObserver и реализуем его виртуальную функцию AdaptiveSearchTextChanged() для получения символов, выбранных пользователем в сетке адаптивного поиска.
- Объявляем объект CAknSingleStyleListBox членом класса и используем его для отображения массива строк, хранящегося в ресурсах
- Объявляем объект CAknSearchField членом класса и интегрируем его со списком для реализации адаптивного поиска.
...
...
#include <aknlists.h> // For List Box
#include <barsread.h> //For Resource Reader
#include <aknsfld.h> // For SearchField
...
// CLASS DECLARATION
class CAdaptiveSearchAppView : public CCoeControl, public MAdaptiveSearchTextObserver
{
....
....
//For listbox
void CreateListBoxL();
TInt CountComponentControls() const;
CCoeControl* ComponentControl(TInt aIndex) const;
TKeyResponse OfferKeyEventL(const TKeyEvent &aKeyEvent, TEventCode aType);
//From MAdaptiveSearchTextObserver
virtual void AdaptiveSearchTextChanged (CAknSearchField *aSearchField);
private:
CAknSingleStyleListBox* iListBox;
CAknSearchField* iSearchField;
.....
};
AdaptiveSearchAppView.cpp
// -----------------------------------------------------------------------------
// CAdaptiveSearchAppView::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CAdaptiveSearchAppView::ConstructL(const TRect& aRect)
{
// Создаем окно
CreateWindowL();
// Создаем списк (listbox) и заполняем его строками из ресурсов
CreateListBoxL();
// Устанавливаем размеры окна
SetRect(aRect);
// Активизируем окно
ActivateL();
}
- Создаем список и заполняем его
- Указываем данный класс ("this") в качестве наблюдателя за событиями адаптивного поиска
void CAdaptiveSearchAppView::CreateListBoxL()
{
iListBox= new (ELeave) CAknSingleStyleListBox();
iListBox->SetContainerWindowL(*this);
TResourceReader rr;
iCoeEnv->CreateResourceReaderLC(rr, R_LIST_BOX);
iListBox->ConstructFromResourceL(rr);
iListBox->CreateScrollBarFrameL(ETrue);
iListBox->ScrollBarFrame()->SetScrollBarVisibilityL( CEikScrollBarFrame::EOn, CEikScrollBarFrame::EAuto );
CleanupStack::PopAndDestroy();//rr
// Создаем поле для поиска (SearchField) и включаем поддержку адаптивного поиска
iSearchField = CAknSearchField::NewL(*this, CAknSearchField::EAdaptive, NULL, 20);
STATIC_CAST(CAknFilteredTextListBoxModel*, iListBox->Model())->CreateFilterL(iListBox,iSearchField);
STATIC_CAST(CAknFilteredTextListBoxModel*, iListBox->Model())->Filter()->HandleOfferkeyEventL();
// Добавляем данный класс ("this") в качестве наблюдателя за событиями адаптивного поиска
iSearchField->AddAdaptiveSearchTextObserverL(this);
}
- Реализуем функцию AdaptiveSearchTextChanged для того, чтобы получить текст, введенный в поле адаптивного поиска.
void CAdaptiveSearchAppView::AdaptiveSearchTextChanged(CAknSearchField* aSearchFiled)
{
TBuf<50> buffer;
aSearchFiled->GetSearchText(buffer);
// добавлено для предотвращения исчезновения поля поиска после закрытия сетки адаптивного поиска
SizeChanged();
DrawNow();
}
- Корректно обрабатываем случаи изменения размеров отображения
// -----------------------------------------------------------------------------
// CAdaptiveSearchAppView::SizeChanged()
// Вызывается системой в случае изменения размеров отображения.
// -----------------------------------------------------------------------------
//
void CAdaptiveSearchAppView::SizeChanged()
{
if (iListBox)
{
if (iSearchField)
{
CAknColumnListBox* aknListBox = STATIC_CAST(CAknColumnListBox*, iListBox);
AknFind::HandleFixedFindSizeChanged(this, aknListBox, iSearchField);
}
else
{
iListBox->SetRect(Rect()); // Устанавливаем прямоугольную область, занимаемую объектом iListBox.
}
}
}
- Возвращаем число компонентов, содержащихся в контейнере, у нас их два - Listbox и SearchField
TInt CAdaptiveSearchAppView::CountComponentControls() const
{
return 2; // возвращаем число компонентов в контейнере
}
CCoeControl* CAdaptiveSearchAppView::ComponentControl(TInt aIndex) const
{
switch ( aIndex )
{
case 0:
return iListBox;
break;
case 1:
return iSearchField;
break;
default:
return NULL;
}
}
- Пример обработки событий от указателя в <tt>HandlePointerEventL:
// -----------------------------------------------------------------------------
// CAdaptiveSearchAppView::HandlePointerEventL()
// Вызывается фреймворком при получении событий от указателя (стилуса)
// -----------------------------------------------------------------------------
//
void CAdaptiveSearchAppView::HandlePointerEventL(
const TPointerEvent& aPointerEvent)
{
// Передаем событие от указателя в обработчик объекта iSearchField
iSearchField->HandlePointerEventL(aPointerEvent);
// Передаем событие базовому классу
CCoeControl::HandlePointerEventL(aPointerEvent);
}
- Обработка событий от клавиатуры происходит в функции OfferKeyEventL()
TKeyResponse CAdaptiveSearchAppView::OfferKeyEventL(const TKeyEvent &aKeyEvent, TEventCode aType)
{
TKeyResponse ret = EKeyWasNotConsumed;
switch (aKeyEvent.iCode)
{
case EKeyDevice3:
break;
default:
if(iListBox)
{
if ( iSearchField )
{
TBool needRefresh( EFalse );
// Обрабатываем нажатие, фильтруем список
if ( AknFind::HandleFindOfferKeyEventL( aKeyEvent, aType, this,
iListBox, iSearchField,
EFalse,
needRefresh ) ==EKeyWasConsumed )
{
if ( needRefresh )
{
SizeChanged();
DrawNow();
}
return EKeyWasConsumed;
}
}
ret = iListBox->OfferKeyEventL(aKeyEvent, aType);
}
return ret;
}
}
- Не забудьте удалить объект iSearchField и iListBox в деструкторе класса.
// -----------------------------------------------------------------------------
// CAdaptiveSearchAppView::~CAdaptiveSearchAppView()
// Деструктор.
// -----------------------------------------------------------------------------
//
CAdaptiveSearchAppView::~CAdaptiveSearchAppView()
{
.....
.....
if(iSearchField)
{
iSearchField->RemoveAdaptiveSearchTextObserver(this);
delete iSearchField;
iSearchField = NULL;
}
if(iListBox)
{
delete iListBox;
iListBox = NULL;
}
}
- Для получения событий в OfferKeyEventL необходимо при создании отображения в функции AppUi::ConstructL() поместить отображение в стэк.
- В деструкторе необходимо удалить из стэка отображение, помещенное туда ранее.
// -----------------------------------------------------------------------------
// CAdaptiveSearchAppUi::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CAdaptiveSearchAppUi::ConstructL()
{
// Initialise app UI with standard value.
BaseConstructL(CAknAppUi::EAknEnableSkin);
// Create view object
iAppView = CAdaptiveSearchAppView::NewL(ClientRect());
AddToStackL( iAppView ); // Добавляем отображение в стэк
....
....
....
}
// -----------------------------------------------------------------------------
// CAdaptiveSearchAppUi::~CAdaptiveSearchAppUi()
// Деструктор.
// -----------------------------------------------------------------------------
//
CAdaptiveSearchAppUi::~CAdaptiveSearchAppUi()
{
if (iAppView)
{
RemoveFromStack(iAppView); // Удаляем отображение из стэка
delete iAppView;
iAppView = NULL;
}
}
Полезные функции
CAknSearchField
- TSearchFieldStyle::EAdaptiveSearch
- GetSearchText()
- SetSearchTextL()
- HandlePointerEventL()
- ShowAdaptiveSearchGrid()
- SetAdaptiveGridChars()
MAdaptiveSearchTextObserver
- AdaptiveSearchTextChanged()
Ключевые моменты
Заголовочные файлы
- #include <aknsfld.h>
Классы
- CAknSearchField
- MAdaptiveSearchTextObserver
Библиотеки
- avkon.lib
Демонстрационное приложение
Связанные ссылки
- Примеры работы с S60 Touch UI
- Пример работы с Toolbar API - S60 Touch UI
- Пример работы с LongTapDetector API - S60 Touch UI
- Пример работы с Stylus Pop-up Menu API - S60 Touch UI
- Пример работы с Tactile Feedback Client API - S60 Touch UI
- Пример работы с ChoiceList API - S60 Touch UI
- Пример работы с Generic Button API - S60 Touch UI
- Пример работы с Hierarchical Lists API (SingleStyleTreeList) - S60 Touch UI
- Пример работы с Hierarchical Lists API (SingleColumnStyleTreeList) - S60 Touch UI
При подготовке статьи использованы следующие материалы:
Источники дополнительной информации
- S60 5th edition SDK help
- S60 5th Edition C++ Developer's Library v1.0


(no comments yet)