{"id":1737,"date":"2021-07-22T12:03:54","date_gmt":"2021-07-22T19:03:54","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=1737"},"modified":"2021-09-02T15:10:56","modified_gmt":"2021-09-02T22:10:56","slug":"jetpack-window-manager-ebook-sample","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/jetpack-window-manager-ebook-sample\/","title":{"rendered":"eBook sample with Jetpack Window Manager"},"content":{"rendered":"<p>\n  Hello Android developers!\n<\/p>\n<p>\n  Reading books on Microsoft Surface Duo can be a great take on the classic reading experience. In this blog, we will walk through an eBook reader sample I created as an internship project. This <a href=\"https:\/\/github.com\/microsoft\/surface-duo-window-manager-samples\/tree\/main\/EBookReader\">eBook sample<\/a> demonstrates how the Two Page layout for foldable devices can naturally spread content across multiple screens.\n<\/p>\n<h2>Base functionality<\/h2>\n<p>\n  This project is designed to load plain text files and present them in book form. The text is parsed into chapters according to some basic rules, and chapters are cached as arrays of strings (one string per paragraph). To build pages, the code uses the app\u2019s current layout information and the chapter cache to organize the strings into pages.\n<\/p>\n<p>\n  <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/07\/ebook-sections-800.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/07\/ebook-sections-800.png\" alt=\"Surface Duo ebook showing two pages of text and the section menu\" width=\"800\" height=\"620\" class=\"alignnone size-full wp-image-1761\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/07\/ebook-sections-800.png 800w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/07\/ebook-sections-800-300x233.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/07\/ebook-sections-800-768x595.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><br \/><em>Figure 1: Paging through a book<\/em>\n<\/p>\n<p>\n  To display sliding pages, this app uses <a href=\"https:\/\/developer.android.com\/training\/animation\/vp2-migration\">ViewPager2<\/a>. ViewPager2 is an upgraded RecyclerView developed by Android to slide efficiently between Views. To support dual-screen devices, the app uses different ViewHolders based on the current app layout.\n<\/p>\n<h2>Dual-screen enhancements<\/h2>\n<p>\n  Enhancing the book reading activity for two-page design required only a few extra lines of code. <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/platform\/jetpack-window-manager\">Jetpack Window Manager<\/a> collects a list of display features. If folding features are detected, the ViewPager2 ViewHolders inflate \u201csplit\u201d page layouts instead of \u201cnormal\u201d page layouts. The position and width of the fold are used to calculate new Rects for the book to adhere to. \n<\/p>\n<pre>return when(layoutStateContainer.layoutMode) {\r\n    BookActivity.LayoutMode.NORMAL -> {\r\n        val view = LayoutInflater.from(parent.context).inflate(R.layout.book_page_layout_normal, parent, false)\r\n        view.findViewById<TextView>(R.id.caption_view).text = book.chapterTitle\r\n        PageViewHolder(view, book.fontSize)\r\n    }\r\n    \/\/ Setting view holder to two-page layout\r\n    BookActivity.LayoutMode.SPLIT_HORIZONTAL -> {\r\n        val view = LayoutInflater.from(parent.context).inflate(R.layout.book_page_layout_split_horizontal, parent, false)\r\n        view.findViewWithTag<View>(\"page_container_0\").layoutParams = LinearLayout.LayoutParams(book.pageRects[0].width(),\r\n            LinearLayout.LayoutParams.MATCH_PARENT)\r\n        view.findViewWithTag<View>(\"page_container_1\").layoutParams = LinearLayout.LayoutParams(book.pageRects[1].width(),\r\n            LinearLayout.LayoutParams.MATCH_PARENT)\r\n\r\n        view.findViewById<TextView>(R.id.caption_view).text = book.chapterTitle\r\n        view.findViewById<TextView>(R.id.caption_view2).text = book.chapterTitle\r\n        SplitPageViewHolder(view, book.fontSize)\r\n    }<\/pre>\n<p>\n  For the main menu activity, where users choose a book to read, Android Jetpack\u2019s <a href=\"https:\/\/developer.android.com\/reference\/androidx\/slidingpanelayout\/widget\/SlidingPaneLayout\">SlidingPaneLayout<\/a> keeps the book selection UI on one side of a fold or hinge. An empty 0-width view on the right pane of the SlidingPaneLayout ensures that the left pane fills non-folded screens.\n<\/p>\n<p>\n  <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/07\/ebook-index-800.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/07\/ebook-index-800.png\" alt=\"Surface Duo ebook index view\" width=\"800\" height=\"620\" class=\"alignnone size-full wp-image-1762\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/07\/ebook-index-800.png 800w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/07\/ebook-index-800-300x233.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/07\/ebook-index-800-768x595.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><br\/><em>Figure 2: Book list view adapted to being spanned<\/em>\n<\/p>\n<p>\n  The sample comes with a copy of some of our developer documentation as the default book content. You can add additional \u201cbooks\u201d as plain text files in the project\u2019s <strong>assets\/books<\/strong> folder. As long as each chapter has four preceding linefeeds and paragraphs are separated by two linefeeds, the content should be rendered in a readable way and populate the chapter menu.\n<\/p>\n<h2>Feedback and resources<\/h2>\n<p>\n  The <a href=\"https:\/\/github.com\/microsoft\/surface-duo-window-manager-samples\/tree\/main\/EBookReader\">sample code is available on GitHub<\/a> along with other Jetpack Window Manager dual-screen apps.\n<\/p>\n<p>\n  Check out the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/\">Surface Duo developer documentation<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/\">past blog posts<\/a> for links and details on all our samples. You can find our samples on GitHub.\n<\/p>\n<p>\n  If you have any questions, or would like to tell us about your apps, use the <a href=\"http:\/\/aka.ms\/SurfaceDuoSDK-Feedback\">feedback forum<\/a> or message us on Twitter <a href=\"https:\/\/twitter.com\/surfaceduodev\">@surfaceduodev<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello Android developers! Reading books on Microsoft Surface Duo can be a great take on the classic reading experience. In this blog, we will walk through an eBook reader sample I created as an internship project. This eBook sample demonstrates how the Two Page layout for foldable devices can naturally spread content across multiple screens. [&hellip;]<\/p>\n","protected":false},"author":65068,"featured_media":1743,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[706,473,46],"class_list":["post-1737","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk","tag-jetpack-window-manager","tag-kotlin","tag-surface-duo"],"acf":[],"blog_post_summary":"<p>Hello Android developers! Reading books on Microsoft Surface Duo can be a great take on the classic reading experience. In this blog, we will walk through an eBook reader sample I created as an internship project. This eBook sample demonstrates how the Two Page layout for foldable devices can naturally spread content across multiple screens. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/1737","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/users\/65068"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=1737"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/1737\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/1743"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=1737"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=1737"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=1737"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}