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.
Base functionality
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’s current layout information and the chapter cache to organize the strings into pages.
Figure 1: Paging through a book
To display sliding pages, this app uses ViewPager2. 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.
Dual-screen enhancements
Enhancing the book reading activity for two-page design required only a few extra lines of code. Jetpack Window Manager collects a list of display features. If folding features are detected, the ViewPager2 ViewHolders inflate “split” page layouts instead of “normal” page layouts. The position and width of the fold are used to calculate new Rects for the book to adhere to.
return when(layoutStateContainer.layoutMode) { BookActivity.LayoutMode.NORMAL -> { val view = LayoutInflater.from(parent.context).inflate(R.layout.book_page_layout_normal, parent, false) view.findViewById(R.id.caption_view).text = book.chapterTitle PageViewHolder(view, book.fontSize) } // Setting view holder to two-page layout BookActivity.LayoutMode.SPLIT_HORIZONTAL -> { val view = LayoutInflater.from(parent.context).inflate(R.layout.book_page_layout_split_horizontal, parent, false) view.findViewWithTag ("page_container_0").layoutParams = LinearLayout.LayoutParams(book.pageRects[0].width(), LinearLayout.LayoutParams.MATCH_PARENT) view.findViewWithTag ("page_container_1").layoutParams = LinearLayout.LayoutParams(book.pageRects[1].width(), LinearLayout.LayoutParams.MATCH_PARENT) view.findViewById (R.id.caption_view).text = book.chapterTitle view.findViewById (R.id.caption_view2).text = book.chapterTitle SplitPageViewHolder(view, book.fontSize) }
For the main menu activity, where users choose a book to read, Android Jetpack’s SlidingPaneLayout 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.
Figure 2: Book list view adapted to being spanned
The sample comes with a copy of some of our developer documentation as the default book content. You can add additional “books” as plain text files in the project’s assets/books 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.
Feedback and resources
The sample code is available on GitHub along with other Jetpack Window Manager dual-screen apps.
Check out the Surface Duo developer documentation and past blog posts for links and details on all our samples. You can find our samples on GitHub.
If you have any questions, or would like to tell us about your apps, use the feedback forum or message us on Twitter @surfaceduodev.
Great job.