屏幕自適應修改方案

 

屏幕自適應修改方案
 
    源:終端開發
關 鍵 詞:分辨率  屏幕 佈局
 
現象、問題描述
  爲了適應不一樣分辨率屏幕上iRead的正常顯示,在不替換圖片的前提下,對畫面進行縮放和位置調整是一種能夠知足全部屏幕變化的方案。iRead原先的繪圖方案是用Image::Draw方法來繪製png圖片,這個方法是能夠對圖片進行拉伸,那麼剩下的問題就是如何縮放和調整位置了。那麼何時該縮放,何時該調整位置,這個怎麼決定呢?下面對這些問題作幾點描述。
 
關鍵過程、根本緣由分析
 
1. 圖片的縮放和位置的調整      
屏幕自適應是爲了咱們的程序畫面可以知足不一樣的分辨率,如480x640,240x320,480x800等等。若是程序一開始是在480x640下寫的程序,換到240x320屏幕,咱們須要把圖片長寬都縮小一半就能夠了,膽識換到480x800下面就不一樣了,若是按x和y方向縮放比例拉伸的話,那麼圖片就會被拉長變形,畫面就會失真。因此咱們不能這麼處理。由於咱們的程序是在480x640開發的,那麼就以這個爲基準,來對其餘分辨率的圖片進行處理。在對圖片進行縮放以前,先得出X方向和Y方向的兩個縮放因子,dx=x/480,dy=y/640,而且取小的縮放因子,這樣圖片就能顯示完整,畫面再也不失真。
圖片縮放大小好了,還要考慮圖片的位置,原先的對齊方式都是以左上角的點爲原點,而後給出相對於這個點的位置座標。須要考慮圖片的對齊方式。
a. 置頂靠左對齊: 若是原先顯示圖片的區域是能夠滾動的,那麼就不須要更改,圖片仍是以左上角爲原點,各個圖片是從上往下,從左往右的順序,間距也不用調整
b. 居中對齊: 若是原先的圖片是要放在中間的,那麼區域擴大後,中點也跟着要改變,在480x800下就是Y方向向下偏移1.25倍距離,好比PopDlg對話框。
c. 靠底對齊和靠右對齊:這種狀況程序中不多出現,只有在個人設置裏面的幾個按鈕才須要靠右對齊,處理的話和第一種狀況同樣。
下面給出調整圖片位置和大小方案的代碼
CRect CDataProcessCtrl::GetRect( const string& strWinName, int iRectId, int iAnchorType)
{
    CRect rcTemp;
    (void)GetRect( strWinName, iRectId, rcTemp);
    int cx = GetSystemMetrics(SM_CXSCREEN);
    int cy = GetSystemMetrics(SM_CYSCREEN);
    double iMaxCx = (double)cx/(double)STD_SCREEN_CX;
    double iMaxCy = (double)cy/(double)STD_SCREEN_CY; 
    double dScale = iMaxCy - iMaxCx;
    double iTemp = 0;
 
    int iSrcWidth = rcTemp.Width();
    int iSrcHeight = rcTemp.Height();
 
    if( cx > cy )
    {
       iTemp = (double)rcTemp.left * iMaxCx;
       rcTemp.left =(int)iTemp;
       iTemp = (double)rcTemp.right * iMaxCx;
       rcTemp.right =(int)iTemp;
       iTemp = (double)rcTemp.top * iMaxCy;
       rcTemp.top =(int)iTemp;
       iTemp = (double)rcTemp.bottom * iMaxCy;
       rcTemp.bottom =(int)iTemp;
 
       return rcTemp;
    }
 
    //比例相等
    if( dScale == 0 )
    {
       iTemp = (double)rcTemp.left * iMaxCx;
       rcTemp.left =(int)iTemp;
       iTemp = (double)rcTemp.right * iMaxCx;
       rcTemp.right =(int)iTemp;
       iTemp = (double)rcTemp.top * iMaxCy;
       rcTemp.top =(int)iTemp;
       iTemp = (double)rcTemp.bottom * iMaxCy;
       rcTemp.bottom =(int)iTemp;
    }
    //CY比例大於 CX,豎屏狀況,以CX爲基準
    else if( dScale > 0 )
    {
       // 居中對齊, Y座標按Y方向作不等比縮放
       if( iAnchorType & ANCHOR_VCENTER )        {
           iTemp = (double)rcTemp.top * iMaxCy;
           rcTemp.top =(int)iTemp;
       }
       // 靠頂對齊, Y座標按X方向作等比縮放
       else if( iAnchorType & ANCHOR_TOP )   
       {
           iTemp = (double)rcTemp.top * iMaxCx;
           rcTemp.top =(int)iTemp;
       }
       //X座標作等比縮放
       iTemp = (double)rcTemp.left * iMaxCx;
       rcTemp.left =(int)iTemp;
       // 長寬作等比拉伸
       rcTemp.right = (int)(rcTemp.left + (double)(iSrcWidth * iMaxCx));
       rcTemp.bottom = (int)(rcTemp.top + (double)(iSrcHeight * iMaxCx));
    }
    //CY比例小於 CX,橫屏狀況,已CY爲基準
    else
    {
       // 居中對齊, X座標按X方向作不等比縮放
       if( iAnchorType & ANCHOR_HCENTER )        {
           iTemp = (double)rcTemp.left * iMaxCx;
           rcTemp.left =(int)iTemp;
       }
// 靠頂對齊, Y座標按X方向作等比縮放
       else if( iAnchorType & ANCHOR_LEFT )  
       {
           iTemp = (double)rcTemp.left * iMaxCy;
           rcTemp.left =(int)iTemp;
       }
       // Y座標只作等比拉伸
       iTemp = (double)rcTemp.top * iMaxCy;
       rcTemp.top =(int)iTemp;
       // 長寬作等比拉伸
       rcTemp.right = (int)(rcTemp.left + (double)(iSrcWidth * iMaxCy));
       rcTemp.bottom = (int)(rcTemp.top + (double)(iSrcHeight * iMaxCy));
    }
   
    return rcTemp;
}
 
2. 圖片的嵌套關係和相對位置
由於程序中有許多圖片都是有嵌套關係的,好比PopDlg是居中對齊的,而裏面的元素倒是置頂對齊,因此咱們須要給出元素所在窗口的相對位置。原先的程序中不少都是以屏幕的右上點爲原點給出的位置,那麼就要改爲使用相對父窗口爲原點的位置。
 
3 浮點數計算的優化和橫豎屏變換
在計算座標時,須要使用到float類型數據運算,若是在OnPaint中執行的話,會耗去不少時間,並且是重複的過程,因此將區域提取出來做爲成員變量,在OnSize中計算出些值,再在OnPaint中使用,同時OnSize也能夠知足窗口發生變化的狀況,若是橫豎屏的切換。
另外進行float計算的過程能夠用兩個 long型來代替,經過一個函數來執行iLength*zoomX的運算 ZoomX(iLength),ZoomY(iWidth)。在屏幕縮放中使用到得值目前最大隻是800,再多考慮點最大的值設爲10,000也就夠了,由於目前尚未這麼大像素的顯示屏,那麼兩個最大值相乘也就是100,000,000,long型也就足夠了。
 
4. 字體的縮放
程序的字體中使用的是系統的,不一樣的屏幕的系統都各自設置了合適的字體,因此一半不須要考慮字體的變化,除非是一些特殊的狀況,咱們能夠更改字體的高度來知足這種變化,固然字體最好要知足和屏幕的縮放比例一致,過小的話也會影響效果。
 
5. 計算的誤區
       在顯示文字的時候,常常要將文字放置在區域中間,而文字區域也須要根據文字的數量來肯定,那麼經過中心點來調整文字區域就很必要
    rcTip.left      = rc.CenterPoint().x - sizeTip.cx / 2;
    rcTip.top       = rc.CenterPoint().y - sizeTip.cy / 2;
    rcTip.right     = rc.CenterPoint().x + sizeTip.cx / 2;
    rcTip.bottom    = rc.CenterPoint().y + sizeTip.cy / 2;
 
上面的方法咋一看起來沒什麼問題,可要是sizeTip.cx和sizeTip.cy是個奇數就有問題了,算出來的區域會比原先會少了1個像素,在顯示換行文字的時候就會有問題。而下面的方法就能夠避免:       
    rcTip.left      = rc.CenterPoint().x - sizeTip.cx / 2;
    rcTip.top       = rc.CenterPoint().y - sizeTip.cy / 2;
    rcTip.right     = rcTip.left + sizeTip.cx;
    rcTip.bottom    = rcTip.top + sizeTip.cy;
 
  
結論、解決方案及效果
以上就是iRead中屏幕自適應修改方案的幾點描述,在使用了上面的方案後,對原先的代碼只須要更改部分基本上就能夠知足全部屏幕分辨率的需求。若是您還有更好的方案,請不吝賜教!
相關文章
相關標籤/搜索