Смена View в приложении с использованием CAknViewAppUi и CAknView

Цель данной статьи дать небольшое пояснение к ViewSwitchingCAknViewAppUi.zip, далее называемый Пример. В примере показано как можно реализовать переключение между различными View унаследованными от CCoeControl с использованием CAknViewAppUi и CAknView.

Использование CAknViewAppUi и CAknView подразумевает, что архитектура вашего приложения будет являться примерно следующей:

 

CAknViewAppUi - UI контролер. В Примере это CTestAppUi. Его основные функции таковы:

  • Создание View контролеров, что наследуются от CAknView.
  • Обработка event'ов и команд меню, что не обрабатываются View контролерами.
  • Переключение между View'ами.

CAknView - View контролер. В Примере CTestViewMain, CTestViewAdd, CTestViewEdit:

  • Создание одного или несколько View.
  • Обработка event'ов и команд меню, им зарегистрированных.

View унаследованный от CCoeControl. В Примере CMainContainer, CAddContainer, CEditContainer:

  • собственно, он показывает данные приложения на экране.

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


Итак, обо всем по порядку.

1. Изменяем rss файл. Так как у нас теперь три View, то нам понадобится три AVKON_VIEW, по одному на каждый.

Вот так будет выглядеть описание меню для CTestViewMain.

//////////////Main View//////////////////
RESOURCE AVKON_VIEW r_test_view_main{
	menubar = r_test_menubar_main;
	cba = R_AVKON_SOFTKEYS_OPTIONS_BACK;
}
 
RESOURCE MENU_BAR r_test_menubar_main{
	titles=
	{
		MENU_TITLE {menu_pane=r_test_menu_main;}
	};
}
 
RESOURCE MENU_PANE r_test_menu_main{
	items =
	{
		MENU_ITEM {
			command=ETestMainAddCmd;
			txt=qtn_command_main_add;
			},
		MENU_ITEM {
			command=ETestMainEditCmd;
			txt=qtn_command_main_edit;
			},
		MENU_ITEM {
			command=EAknSoftkeyExit;
			txt=qtn_exit;
			}
	};
}

Для остальных View контролеров создание меню происходит аналогично.

2. Создаем в Test.hrh файле enum, что будет содержать Id для каждого отдельного View. По этим Id позже будет происходить переключение между View.

enum TTestViewId
    {
    EMainView = 0x7001,
    EAddView,
    EEditView
};


3. Создаем собственный UI контролер CTestAppUi : public CAknViewAppUi. Его особенностью будет метод ConstructL(), в котором будут создаваться View контролеры:

void CTestAppUi::ConstructL(){
	
	BaseConstructL();
	
	CTestViewMain* view_main = new (ELeave) CTestViewMain;
	view_main->ConstructL();
	AddViewL( view_main );
	iViewId1 = view_main->Id();
 
.............	
	
	SetDefaultViewL( *view_main );
	
}

4. Создаем View контролеры. Рассмотрим на примере CTestViewMain : public CAknView. Особенностями создания являются:

void CTestViewMain::ConstructL(){
        // тот самый AVKON_VIEW, что мы определили в Test.rss
	BaseConstructL(R_TEST_VIEW_MAIN);
}
 
TUid CTestViewMain::Id() const{
	return TUid::Uid(EMainView);// тот самый Id, что мы определили в Test.hrh
}
 

void CTestViewMain::HandleCommandL(TInt aCommand){
	switch( aCommand ){
	case ETestMainAddCmd:
		iEikonEnv->InfoMsg(R_TEST_MAIN_ADD);
                // переключение в CTestViewAdd
		AppUi()->ActivateLocalViewL(TUid::Uid(EAddView));
		break;
	case ETestMainEditCmd:
		iEikonEnv->InfoMsg(R_TEST_MAIN_EDIT);
                // переключение в CTestViewEdit
		AppUi()->ActivateLocalViewL(TUid::Uid(EEditView));
		break;
	case EAknSoftkeyExit:
	case EAknSoftkeyBack:
	default:
                // оставляем обработку незнакомых нам команд на совесть CTestAppUi
		AppUi()->HandleCommandL(aCommand);
		break;
		
	}
} 
/* 
   Здесь происходит переключение на один из View, подконтрольных данному View контролеру.
   Но поскольку в моем примере каждый View контролер имеет только один View, то
   параметры переключения(Id другого View и прочие) мне не нужны.
   Здесь же сразу происходит создание требуемого View, если он еще не создан.
*/
void CTestViewMain::DoActivateL( const TVwsViewId& /*aPrevViewId*/,TUid /*aCustomMessageId*/,
			   const TDesC8& /*aCustomMessage*/){
	if(!iContainer){
		iContainer = CMainContainer::NewL( ClientRect() ) ;
		iContainer->SetMopParent(this);
		AppUi()->AddToStackL( *this, iContainer );
	}
			   
}

5. Создаем View. Тут ничего особенного, все также как и в архитектуре с CAknAppUi. Также наследуем от CCoeControl и реализуем все те же методы, что и в традиционной UI архитектуре.

6. Вроде все. Выложенное здесь приложение тестировалось лишь на WINSCW эмуляторе для S60 3rd Edition. При написании активно использовалась C++ Developer's Library 1.4 и собственный код, основанный на коде пользователя A.A.M.


18.12.2009 Автор: Vogdb