簡體   English   中英

片段設計:通過在單個 Activity 中顯示/隱藏片段來適應多種屏幕布局?

[英]Fragment design: Adapting to multiple screen layouts by showing/hiding fragments within a single Activity?

我試圖了解如何使用片段來創建能夠很好地適應多種屏幕和布局的應用程序。 我研究了幾個例子:

  1. Android 開發人員指南上的片段文檔。
  2. 谷歌 IO 應用程序
  3. 來自ActionBar Sherlock的片段示例。

所有這些都提倡多Activity方法:

  • 在大屏幕上,顯示單個Activity和多個Fragment
  • 在較小的屏幕上,將Fragment拆分到多個Activity中。

我想到了另一種方法 - 一個單一的Activity

  • 擁有一個包含所有FragmentActivity
  • 根據屏幕大小和方向,顯示/隱藏適當的Fragment (使用FragmentTransaction.show() / FragmentTransaction.hide() )。

以 Android 開發人員指南使用的相同“新聞文章列表/文章內容”示例進行說明:

  • News活動同時包含ArticleListFragmentArticleReaderFragment
  • 在選項卡上,始終顯示兩個片段。
  • 在手機上, ArticleReaderFragment最初是隱藏的。 從列表中選擇文章時,隱藏ArticleListFragment並顯示ArticleReaderFragment

有人使用過類似的方法嗎? 這種方法可能有任何實際的缺點嗎? 與多活動方式相比,它看起來更好/更差嗎? 例如,不能在 XML 中顯示/隱藏片段 - 為此必須使用FragmentTransaction


編輯 1:假設場景的描述

想象一個可以在屏幕上同時顯示最多三個“窗格”的應用程序。 此外,這些是要考慮的因素:

  • 手機一次只能顯示一個窗格(無論縱向/橫向)
  • 一個 7 英寸的平板電腦可以顯示 2 個面板,在縱向模式下垂直分割,在橫向模式下水平分割。
  • 一個 10 英寸以上的平板電腦可以顯示 2 個窗格,縱向拆分; 3 個窗格在橫向上水平分割。

為簡單起見,讓我們將電視屏幕排除在討論之外。

現在,將其轉化為設計:

  • 我們有三個片段:Frag1、Frag2 和 Frag3。
  • 在最簡單的情況下,所有三個片段都在一個 Activity 中(我們稱之為 ActivityA)。 這是 10 英寸橫向表殼。
  • 另一種“簡單”的情況是每個 Fragment 都在自己的 Activity 中——ActivityA 包含 Frag1; ActivityB 包含 Frag2,ActivityC 包含 Frag3。

到目前為止,我們還沒有考慮任何與 Android 開發人員指南中提供的新聞閱讀器示例有顯着不同的地方。 唯一的主要區別是有三個片段而不是兩個。

現在,7 英寸的表殼只能容納 2 個碎片。 這將如何工作? 請注意,這里有兩種可能的組合:

  1. 正在顯示 Frag1 和 Frag2。
  2. 正在顯示 Frag2 和 Frag3。

我只是無法解決這個問題。 我是否在 ActivityA 中執行所有這些操作? 我只是創建一個全新的 ActivityD 嗎? 我需要創建多少個布局(我數了數大約 8 個)? 是不是排列太多了?

我確實意識到我上面提出的單一活動方法可能也不適合這種情況——因為顯示/隱藏片段本身是非常重要的。

關於如何在不被布局和組合淹沒的情況下處理這個問題的任何建議?

@Taylor Clark 的回答非常有用。 但是,這並不是我在原始問題中提出的使用單一活動方法的實際經驗分享。 我着手修改 Android 開發人員指南中的新聞閱讀器示例以使用單活動方法,並提出了一個可行的解決方案。

還有待觀察的是,在哪些用例中這種方法比多活動方法更可取(或者是否存在任何此類情況)。 此外,我還沒有詳細查看我的問題的編輯 1 中描述的 3 窗格場景。

我希望盡快發布我的整個項目,但這里是我如何進行的快速概述:

  • 單一Activity :NewsActivity
  • 兩個片段: TitlesListFragmentDetailsFragment
  • 這兩個片段始終存在於NewsActivity中。 根據當前的雙窗格,我顯示/隱藏適當的片段。

我遇到的一些問題:

是否將布局指定為雙窗格:

在原始新聞閱讀器示例中,雙窗格布局有一個FrameLayout用於保存新聞詳細信息。 我們通過測試此框架布局的存在來確定我們當前是否處於雙窗格布局中。

但是,在我的解決方案中,這兩個片段始終存在於所有布局中。 dualPane View android:visibility="gone"的視圖並在單窗格布局中省略這個視圖來解決這個問題。 然后,這是一個問題

mDualPane = findViewById(R.id.dualPane);=null;

編輯:

有比虛擬視圖更好的方法來指定雙窗格。 我更喜歡的方法是創建一個 boolean 資源。 比如我有一個config.xml如下:

<resources>
    <bool name="dual_pane">false</bool>
</resources>

然后,我可以將其他config.xml文件放在values-xlarge-landvalues-portvalues-sw600dp等文件夾中,並根據需要將 boolean 值調整為truefalse

然后,在代碼中是getResources().getBoolean(R.bool.dual_pane);的問題。

關閉詳細信息片段

這是區分Activity關閉和Fragment關閉的問題。 最后,我不得不重寫onBackPressed()如下:

  • 在雙窗格模式下,只需調用super.onBackPressed()
  • 在單窗格模式下,如果我們在TitlesListFragment中,調用super.onBackPressed()
  • 在單窗格模式下,如果我們在DetailsFragment中,則將其視為關閉片段。 這意味着隱藏它並顯示TitlesListFragment

這並不理想,但這是我能想到的最好的。

編輯

根據@SherifelKhatib 在評論中的建議,有一種更簡潔的方法來處理后退按鈕按下:只需將顯示/隱藏細節片段的事務添加到 Fragment backstack。 這樣,當您按下后退按鈕時,片段事務將被撤銷。 如果您希望在其他按鈕點擊時這樣做,您也可以手動彈出后退堆棧。

通常,應用程序被拆分為活動,因為每個活動都代表用戶可以執行的特定“事情”。 例如,在 email 應用程序中,定義的一組操作可以是:

  1. 查看消息列表
  2. 查看消息的詳細信息
  3. 撰寫對 email 的回復。

每個動作都可以是它自己的活動,顯示單個(或一組)片段。 但是,如果您有屏幕空間,那么將消息列表的查看和消息詳細信息合並到一個可以顯示/隱藏“詳細視圖”片段的活動中是有意義的。 本質上,片段允許您一次向用戶顯示多個“活動”。

做決定時要考慮的事項:

  1. 無法提供 xml 中指定的片段 arguments
  2. 如果您的決定是基於屏幕方向,您始終可以使用資源限定符指向另一個具有更多/更少片段的布局(例如 layout-land-large)
  3. 碎片無法維護 Activity
  4. Fragment 是否協同工作來為用戶提供簡化的體驗?
  5. 是否有某個時候您的某個 Fragments 會永遠消失? 如果是這樣,也許是時候進行新的活動了
  6. Go 用你的直覺。 如果您的應用程序換出片段是“自然的”,請使用 go。 請記住,如果您發現自己經常這樣做,也許單獨的 Activity 是更合適的解決方案

我通常對平板電腦版本的應用程序采用“多片段方法”,對手機采用“每個活動一個片段”,這聽起來與您列出的第一種方法一致。 並不是說第二個沒有時間和地點,但我可以看到實施很快變得一團糟!

抱歉冗長的回復? 也許您可以詳細說明您的具體用例? 希望這可以幫助!


對問題編輯一的回應


以下是我想象的如何設置您的應用程序項目:

源文件:

yourapp.package.phone: NewsActivity1, NewsActivity2, NewsActivity3

yourapp.package.tablet:NewsMultipaneActivity

資源

布局/

activity_news.xml- phone version, only includes Fragment1
activity_news_detail.xml- phone version, only includes Fragment2
activity_news_<something>.xml- phone version, only includes Fragment3

布局-大/

activity_news.xml- 7" tablet version, includes Fragment2 and an empty fragment container. Split vertically

布局大地/

activity_news.xml- same as layout-large, but with the split being horizontally

布局-xlarge-土地/

activity_news.xml- 10"+ tablet version, contains all three fragments split horizontally

那么這里發生了什么?

  • 如果您的應用程序在手機上運行,請啟動 NewsActivity1
  • 如果您的應用程序在平板電腦上運行,請啟動 NewsMultipaneActivity

只要文件名相同,Android 就會根據屏幕大小和方向為您交換布局。 因為 Fragment2 將始終顯示,您可以將其“硬編碼”到您的平板電腦布局中。 然后可以根據需要使用FragmentTransactions在容器中的Fragment1和Fragment3之間切換

請務必查看http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources了解如何利用資源限定符來減輕不同屏幕和方向的一些麻煩

感謝您提出這個問題和您的見解。 在遇到問題之前,我一直使用多活動方法。 我的應用程序就像文檔示例新聞閱讀器。 考慮這種情況:

  1. (初始狀態)我在橫向模式下使用平板電腦(雙窗格),活動 A 在左側顯示文章列表,在右側顯示一些文章。
  2. 我旋轉設備,現在 Activity A 處於單窗格模式並顯示文章列表。
  3. 我單擊一個列表項,活動 B 以打開的文章開始。
  4. 現在我將設備旋轉回橫向模式。

發生了什么? 活動 B 正在顯示全尺寸的文章,而我當然想 go 回到兩個窗格。 我不確定如何很好地解決這個問題。 當然,活動 B 可能會檢查多窗格模式並自行完成,活動 A 可能會檢查最后顯示的文章是什么……看起來很難看。 想法?

PS 我懷疑 GMail 應用程序使用單一活動方法。 當我從列表中發送電子郵件 select 時,我沒有看到任何活動轉換。 它在我描述的場景中也表現得很好。

在本文http://developer.android.com/guide/practices/tablets-and-handsets.html#Fragments Google 中說:

“你選擇的方法取決於你的設計和個人喜好。”

“然而,其他時候,為您的手機設計動態交換片段會使您的代碼更加復雜,因為您必須管理活動代碼中的所有片段組合(而不是使用替代布局資源來定義片段組合)並管理后台堆棧自己碎片化(而不是讓正常的活動堆棧處理返回導航)。”

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM