symbian s60 3rd 橫屏豎屏切換

原文:http://blog.sina.com.cn/s/blog_491e04500100dg85.html

設備, 軟件 版本:
S60 3rd Edition

S60 3rd Edition, FP1

S60 3rd Edition, FP2

詳細描述:

缺省情況下,程序是根據手機屏幕的當前方向開始啓動的。如果要強制程序以橫屏或豎屏的模式啓動,那我們在CAknAppUi::ConstructL()方法中調用BaseConstructL()時就要傳遞相應的flag值:

定義如下:

        EAknEnableSkin = EAknEnableSkinFlag,
        EAppOrientationPortrait     = EAppOrientationSpecifiedFlag,
        EAppOrientationLandscape    = EAppOrientationSpecifiedFlag
                                      | EAppOrientationLandscapeFlag,
        EAppOrientationAutomatic    = EAppOrientationSpecifiedFlag
                                      | EAppOrientationAutomaticFlag,
        // Since 3.0
        EAknDisableHighlightAnimation = EAknDisableHighlightAnimationFlag,

使用方式:

void CMyAppUi::ConstructL()

{

BaseConstructL( EAknEnableSkin | EAppOrientationLandscape );    // start in landscape mode

...

}

如果要在程序運行期間改變方向,則需要調用:void CAknAppUiBase::SetOrientationL( TAppUiOrientation aOrientation );
例:在HandleCommandL(TInt aCommand)函數中:        case ES60ExCmdRotate:
         {
         iForcedRotateState = ETrue;
     
       if( !ScreenState() )
            {
            SetOrientationL(CAknViewAppUi::EAppUiOrientationPortrait); //豎屏         
            }
          else
            {        
            SetOrientationL(CAknViewAppUi::EAppUiOrientationLandscape); //橫屏    
            }         
         break;
            }
這裏的參數爲EAppUiOrientationLandscape和EAppUiOrientationPortrait,注意這種情況下的調用就不要再向BaseConstructL()中傳遞相同的參數了。

注意

橫屏(landscape),前者是橫幅,一般多用在風景照,所以叫"landscape"。 
豎屏(portrait),後者是直幅,一般多用在肖像上,所以叫"portrait"。 
實例代碼:S60_Platform_Custom_UI_and_Screen_Rotation_Example_v1_0_en.zip

測試機型:nokia 5320 xpressmusic

不過在3rd mr模擬器上測試屏幕旋轉沒效果,這個模擬器不支持旋轉,只能手動設置屏幕大小。屏幕旋轉需要真機測試。

旋轉屏幕
2.8,3.0 SDK支持屏幕旋轉,程序裏面可以捕獲該消息,然而使UI自定義的改變位置
繼承的函數爲:Container::HandleResourceChange,原先的SizeChange這個函數不會響應

在該函數內不要使用AppUi->ClientRect函數來獲取工作區範圍,數據會有偏差(這個問題鬱悶了好久),可以使用
TRect rect;
AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane,rect );
來獲取RECT

徹底解決Symbian全屏顯示問題
原文:http://blog.csdn.net/Max__Payne/archive/2009/02/18/3906734.aspx

最近總有同行問我Symbian全屏顯示的問題,說是參考了網上的方法也無法設置成全屏。其實,歸根結底還是不明白Symbian框架的調用機制。這篇文章裏我就來徹底研究一下Symbian全屏的機制。

首先,我們可以利用Carbide.vs嚮導建一個項目,名字就叫"TestScreen",選擇基於Eikon的傳統控件架構。

那麼在CTestScreenAppUi的二階構造函數裏就有如下代碼:

void CTestScreenAppUi::ConstructL()

{

BaseConstructL();

iAppContainer = new (ELeave) CTestScreenContainer;

iAppContainer->SetMopParent( this );

iAppContainer->ConstructL( ClientRect() );

AddToStackL(iAppContainer);

}

這裏面有很關鍵的一句,就是我用紅色顯示的那段代碼。它把當前UI的ClientRect()傳遞給Container類,我們都知道Container類是控件類,負責整個程序的界面顯示,那麼 UI傳遞給Container的這個ClientRect()到底是什麼東東呢?我們看看SDK HELP:

ClientRect()

TRect ClientRect() const;

Description

Gets the area of the screen available to the application for drawing, not including the space that is available for any of the following, where required: non-application areas which should always be displayed, an application status pane, an application button group, an application menu bar, an application title band and an application tool bar.

Importantly, the co-ordinates of the rectangle are relative to the whole screen area so, for example, the co-ordinate for the top, left point of the area available for drawing may be (0, 45).

Return value

TRect The area of the screen available to the application for drawing.

從Description我們可以看到:ClientRect()獲得應用程序繪製的有效屏幕區域,但是這個區域不包括那些總是顯示的非應用程序區域,比如:應用程序狀態面板 (application status pane)、按鈕(button group)、應用程序的菜單bar、標題、工具條。

而且更重要的是從下面一行可以看出,這個ClientRect()所獲得區域的top-left座標是(0,45)。

通過上面的分析我們知道,UI在構造我們的Container時傳遞一個所謂的"客戶矩形區域",這個"客戶矩形區域"的top-left座標是(0,45),從而也就知道如果要讓我們的程序全屏顯示,那麼我們需要改變的是構造Container的時候傳遞的矩形大小。

那麼就有如下幾種方法:

①如果我們知道屏幕尺寸,那麼就可以把iAppContainer->ConstructL( );裏面的參數改爲TRect (0,0,176,208)。

②上面的程序不具有適配性,因爲我們把屏幕的寬度和高度寫死了。

我們來看Symbian給我們提供的一個方法

ApplicationRect()

TRect ApplicationRect() const;

Description

Gets the total area of the screen available to the application. This includes the space that is available for a toolbar, toolband or title band, if the application requires them.

Return value

TRect The total area of the screen available to the application.

Description寫的很明顯了,我就不翻譯了。這個方法可以獲得屏幕的整個尺寸,我們把程序可以改爲:

iAppContainer->ConstructL( ApplicationRect() );從而實現程序的全屏顯示。

③第三中方法是最笨的方法了,那就是不改變UI所傳遞的"客戶矩形區域"的大小,傳遞的仍然是ClientRect()。但是到了Container後再採用"亡羊補牢"的做法!把status pane、menu bar等隱藏起來。

而且這種方法也容易出錯誤,下面是一個同行犯的錯誤,他在Container類裏寫入下面代碼:

void CTestScreenContainer::ConstructL(const TRect& aRect)

{

CreateWindowL();

iLabel = new (ELeave) CEikLabel;

iLabel->SetContainerWindowL( *this );

iLabel->SetTextL( _L("Example View") );

iToDoLabel = new (ELeave) CEikLabel;

iToDoLabel->SetContainerWindowL( *this );

iToDoLabel->SetTextL( _L("Add Your controls/n here") );

SetRect(aRect);

CEikStatusPane* statusp = iEikonEnv->AppUiFactory()->StatusPane();

if(statusp)

statusp->MakeVisible(EFalse);

iEikonEnv->AppUiFactory()->Cba()->MakeVisible(EFalse);

ActivateL();

}

爲了使用CEikStatusPane類要加入頭文件#include

爲了使用CEikButtonGroupContainer類要加入頭文件#include

其中iEikonEnv->AppUiFactory()是在Symbian中獲取UI實例常用的方法,這和MFC是一樣,你千萬不能new一個CTestScreenAppUi出來,因爲他們是由框架調用的,我們並不知道何時調用。

但是因爲他是在Container類裏調用這兩個方法,也就是說ClientRect()獲取"矩形區域"之後程序才設置status pane、Cba爲不可見!所以當然也沒什麼用,程序仍然無法全屏顯示。

所以說即使你在UI類裏寫下面的代碼,但因爲代碼是在獲取"矩形區域"之後才設置status pane、Cba爲不可見,程序仍然無法全屏顯示!

void CTestScreenAppUi::ConstructL()

{

BaseConstructL();

iAppContainer = new (ELeave) CTestScreenContainer;

iAppContainer->SetMopParent( this );

iAppContainer->ConstructL( ClientRect() );

//在獲取"矩形區域"後設置status pane、Cba爲不見

CEikStatusPane* statusp = StatusPane();

if(statusp)

statusp->MakeVisible(EFalse);

Cba()->MakeVisible(EFalse);

AddToStackL( iAppContainer );

}

所以千萬記住:如果要通過設置status pane、Cba爲不可見的方法獲得全屏,千萬要在獲取"矩形區域"之前設置!

④上面集中方法都是通過在UI類設置"矩形區域"的大小,或者通過設置status pane、Cba不可見隱式改變"矩形區域"的大小實現全屏的。

這裏我們介紹一種在Container類裏,在UI設置完"矩形區域"後再改變屏幕爲全屏顯示的方法。void CTestScreenContainer::ConstructL(const TRect& aRect)

{

CreateWindowL();

iLabel = new (ELeave) CEikLabel;

iLabel->SetContainerWindowL( *this );

iLabel->SetTextL( _L("Example View") );

iToDoLabel = new (ELeave) CEikLabel;

iToDoLabel->SetContainerWindowL( *this );

iToDoLabel->SetTextL( _L("Add Your controls/n here") );

SetRect(aRect);

SetExtentToWholeScreen();

ActivateL();

}

但是要千萬記得:SetExtentToWholeScreen()一定要在SetRect(aRect)之後調用纔有效果。這點很容易理解,因爲如果 SetExtentToWholeScreen()改變屏幕爲全屏後,再調用SetRect(aRect)又把屏幕尺寸設置爲UI裏傳遞的"矩形區域"的大小了。

Dialog全屏實現:

RESOURCE DIALOG r_dialog_waitingbox0
{
    flags = EEikDialogFlagWait
            |EEikDialogFlagFillAppClientRect //client screen
            |EEikDialogFlagNoShadow
            |EEikDialogFlagNoBorder
            |EEikDialogFlagCbaButtons
            |EEikDialogFlagNotifyEsc //OkToExitL will catch "exit" event
            |EEikDialogFlagNoDrag;
    buttons = R_AVKON_SOFTKEYS_CANCEL;
}
void CUbWaitingBox::PostLayoutDynInitL()
{
#if 1 //dialog 全屏的實現
    // hide cba buttons
    CEikButtonGroupContainer* cba = CEikButtonGroupContainer::Current();
    cba->MakeVisible(EFalse);
    // hide status pane
    CEikStatusPaneBase* statusPane = CEikStatusPane::Current();
    statusPane->MakeVisible(EFalse);
    SetExtentToWholeScreen();
#endif
    CAknDialog::PostLayoutDynInitL();
}


屏幕相關事件:

void CAknAppUi::HandleResourceChangeL( TInt aType );

void CAknAppUi::HandleScreenDeviceChangedL();

void CAknAppUi::HandleForegroundEventL(TBool aForeground);

例如捕捉轉屏事件:

在appui的HandleResourceChangeL處理
HandleResourceChangeL( TInt aType )
{
CAknAppUi::HandleResourceChangeL( aType );
if ( aType==KEikDynamicLayoutVariantSwitch ) {
//TODO: handle screen switch
}
}

void CUbiLiveGC_SymbianAppUi::HandleForegroundEventL(TBool aForeground)
{
    TAppUiOrientation aOrientation = Orientation();
    if(aOrientation==EAppUiOrientationLandscape){
        
    }
}
void CUbiLiveGC_SymbianAppUi::HandleScreenDeviceChangedL()
{
    TAppUiOrientation aOrientation = Orientation();
    if(aOrientation==EAppUiOrientationLandscape){
        
    }
}

 

 

發佈了3 篇原創文章 · 獲贊 3 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章