2011年2月27日 星期日

[Android][筆記] 3.0 SDK - Orientation change design with Duo panel UI

關於這主題, Dianne Hackborn已經在這講的很詳細了, 這邊挑了一些要點

Duo panel的設計在iPad上已經是蠻常見的了, 這設計的一個特點是, 在Landscape模式時為了充分利用空間, 把Panel切割成兩部分, 但使用者轉換成Portrait時, 則會轉換成Single panel

不意外的, 在Android上實現Duo panel的方式是可以利用Fragment的

在Hackborn的範例中, 總共有兩個Fragment (TitlesFragment, DetailsFragment) 和兩個Activity (FragmentLayout - 這邊姑且稱之為main activity, DetailsActivity), 這部份的codes可以在ApiDemos裡面找到

在main activity的layout設計上面, 為了達到Portrait是single panel而Landscape是duo panel的設計, 其實是要portrait跟ladscape分開各一種layout, 在landscape是要包含左右兩邊的Fragment, 但portrait就只能包含左邊的

因此, 在portrait mode時main activity由於不會有右邊的panel的ID, 所以必須自行偵測右邊是否存在(或是偵測目前是不是在portrait), 然後決定按下list item的行為, 如果是portrait, 就不能使用DetailsFragment去取代右邊panel, 取而代之的必須呼叫DetailsActivity來顯示, 這作法其實頗為tricky, 而且在這作法下, 懶惰的programmer再也不能overrride onConfigurationChange來偷懶了, 對於習慣不好的programmer應該是蠻容易在Orientation change這邊產生side effects

上面就是利用不同的Orientation方向判斷到底是用DetailsFragment取代右邊Panel還是呼叫DeatilsActivity, 而DetailsActivity其實就只是一個DetailsFragment一個包裝, 也就是當在landscape時, 本來就只有main activity左右兩個Fragment, 在portrait時, 這兩個Fragment被拆開成兩個Activities, 但如果這時候從portrait的DetailActivity轉回landscape要怎回到原本main activity的duo panel型態呢? 作法很簡單(也有點tricky), 在lands cape mode時, DetailsActivity就把自己給finish掉了, 不過這邊要能夠確定history stack的前一個的確是main activity, 不然也會很怪的(一般應該都會是才對)

在Hackborn的範例中, 每次都得重新建立一個新的DetailsFragment, 這樣的缺點是, 每次花在DetailsFragment初始化還有inflat layout的時間會有點浪費, 如果是在複雜的layout跟Fragment, 這樣容易造成許多不必要的垃圾, 當然能夠reuse最好, 如果把她用的replace換成這個replace, 自己給個tag, 那之後就可以用FragmentManager.findFragmentByTag將這個Fragment instance給取出重複利用, 但, Fragment是不可以被重複加入的, 你可以拿instance出來重複使用但如果試圖把這個instance重複給FragmentTranscaction, 那是會發生錯誤的

附記: 如果沒去設定target sdk version是11的話, 那這個應用程式會被當做是小螢幕的而不是一個tablet application, 此時你看到的會是在中間一個縮小版的(學iPad也不要學這麼像嘛... = =")