Skip to content

Commit

Permalink
Merge pull request #13 from babydots/view-pager-for-book
Browse files Browse the repository at this point in the history
Swipe (or tap) to change pages + bump for release v0.8.0
  • Loading branch information
pserwylo committed May 14, 2022
2 parents 3bbe093 + 01224dc commit 711c502
Show file tree
Hide file tree
Showing 18 changed files with 239 additions and 109 deletions.
3 changes: 2 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions README.md
Expand Up @@ -45,3 +45,9 @@ Alternatively, you can import the project into Android Studio and build from the
## LICENSE

This program is Free Software: You can use, study share and improve it at your will. Specifically you can redistribute and/or modify it under the terms of the [GNU General Public License](https://www.gnu.org/licenses/gpl.html) as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

### Attribution

View attribution for each book from within the app.

Paper image background: https://unsplash.com/@marjan_blan
4 changes: 2 additions & 2 deletions android/build.gradle
Expand Up @@ -12,8 +12,8 @@ android {
applicationId "com.serwylo.babybook"
minSdk 21
targetSdk 31
versionCode 8
versionName "0.7.0"
versionCode 9
versionName "0.8.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

Expand Down
9 changes: 2 additions & 7 deletions android/src/main/java/com/serwylo/babybook/Changelog.kt
Expand Up @@ -22,13 +22,8 @@ object Changelog {

return WhatsNew.newInstance(
WhatsNewItem(
"Multi-language Wikipedia",
"Select from over 70 different Wikipedia sites from the settings. Once selected, all newly created books will fetch text and images from this Wiki. Currently supports all Wikipedia's with over 100,000 articles.",
R.drawable.ic_language,
),
WhatsNewItem(
"Volume buttons change pages",
"When reading a book, you can now press volume down to go to the next page, or up to go to the previous.",
"Swipe (or tap) to turn pages",
"Select your preferred option from the settings menu. Volume can still be used to change pages too.",
R.drawable.ic_book,
),
WhatsNewItem(
Expand Down
6 changes: 6 additions & 0 deletions android/src/main/java/com/serwylo/babybook/Preferences.kt
Expand Up @@ -8,6 +8,10 @@ object Preferences {

private const val KEY_ONBOARDING_COMPLETE = "onboarding_complete"
private const val KEY_HAS_SHOWN_CONTENT_WARNING_COMPLETE = "has_shown_content_warning"
private const val KEY_PAGE_TURN_TYPE = "page_turn_type"

const val PAGE_TURN_TYPE_SWIPING = "swipe"
const val PAGE_TURN_TYPE_BUTTONS_OVERLAYED = "buttons_overlayed"

private fun prefs(context: Context) = PreferenceManager.getDefaultSharedPreferences(context)

Expand All @@ -23,4 +27,6 @@ object Preferences {
putBoolean(KEY_HAS_SHOWN_CONTENT_WARNING_COMPLETE, true)
}

fun pageTurnType(context: Context) = prefs(context).getString(KEY_PAGE_TURN_TYPE, null) ?: PAGE_TURN_TYPE_SWIPING

}
Expand Up @@ -28,6 +28,15 @@ class SettingsActivity : AppCompatActivity() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.settings)

findPreference<ListPreference>("page_turn_type")?.apply {
setDefaultValue(Preferences.PAGE_TURN_TYPE_SWIPING)
summaryProvider = Preference.SummaryProvider { preference: ListPreference ->
val prefVal = preference.value ?: Preferences.PAGE_TURN_TYPE_SWIPING
val index = context.resources.getStringArray(R.array.page_turn_type_entry_values).indexOf(prefVal)
context.resources.getStringArray(R.array.page_turn_type_entries)[index]
}
}

findPreference<ListPreference>("select_wiki_site")?.apply {
lifecycleScope.launchWhenCreated {

Expand Down
@@ -0,0 +1,47 @@
package com.serwylo.babybook.bookviewer

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.serwylo.babybook.databinding.FragmentBookViewerPageBinding
import com.serwylo.babybook.db.entities.PageEditingData
import com.squareup.picasso.Picasso
import kotlinx.coroutines.launch

class BookPageFragment(
private val page: PageEditingData,
): Fragment() {

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val binding = FragmentBookViewerPageBinding.inflate(inflater, container, false)

binding.title.text = page.title()
binding.text.text = page.text()

if (page.image == null) {
binding.image.visibility = View.GONE
} else {
binding.image.visibility = View.VISIBLE
lifecycleScope.launch {
val image = page.image(requireContext())
if (image != null) {
Picasso.get()
.load(image)
.fit()
.centerCrop()
.into(binding.image)
}
}
}

return binding.root
}

}
@@ -1,38 +1,67 @@
package com.serwylo.babybook.bookviewer

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.serwylo.babybook.Preferences
import com.serwylo.babybook.R
import com.serwylo.babybook.attribution.AttributionActivity
import com.serwylo.babybook.book.BookConfig
import com.serwylo.babybook.book.Page
import com.serwylo.babybook.databinding.ActivityBookViewerBinding
import com.serwylo.babybook.db.AppDatabase
import com.serwylo.babybook.db.entities.PageEditingData
import com.serwylo.babybook.db.entities.imagePathToFile
import com.serwylo.babybook.db.repositories.BookRepository
import com.serwylo.babybook.pdf.generatePdf
import com.serwylo.babybook.utils.viewInWikipedia
import com.squareup.picasso.Picasso
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.*

class BookViewerActivity : AppCompatActivity() {

private lateinit var pageTurnType: String

private lateinit var viewModel: BookViewerViewModel
private lateinit var binding: ActivityBookViewerBinding

private val onPageChange = object: ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
binding.apply {
val count = (pager.adapter?.itemCount ?: 0)
nextOverlay.visibility = if (pageTurnType == Preferences.PAGE_TURN_TYPE_BUTTONS_OVERLAYED && position < count - 1) {
View.VISIBLE
} else {
View.GONE
}

previousOverlay.visibility = if (pageTurnType == Preferences.PAGE_TURN_TYPE_BUTTONS_OVERLAYED && position > 0) {
View.VISIBLE
} else {
View.GONE
}
}
}
}

override fun onResume() {
super.onResume()

pageTurnType = Preferences.pageTurnType(this)
}

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)
Expand Down Expand Up @@ -157,12 +186,15 @@ class BookViewerActivity : AppCompatActivity() {
Toast.makeText(this, "This book does not have any pages yet.", Toast.LENGTH_SHORT).show()
finish()
} else {
showPage(firstPage)
val pagerAdapter = ScreenSlidePagerAdapter(this)
binding.pager.adapter = pagerAdapter
binding.pager.offscreenPageLimit = 3
binding.pager.registerOnPageChangeCallback(onPageChange)
}
}

binding.previous.setOnClickListener { viewModel.turnToPreviousPage() }
binding.next.setOnClickListener { viewModel.turnToNextPage() }
binding.previousOverlay.setOnClickListener { viewModel.turnToPreviousPage() }
binding.nextOverlay.setOnClickListener { viewModel.turnToNextPage() }

viewModel.currentPageIndex.observe(this) { currentPage ->
// Be defensive here, because it is almost always guaranteed that we receive a
Expand All @@ -171,36 +203,11 @@ class BookViewerActivity : AppCompatActivity() {
// by the observer on viewModel.bookWithPages).
val pages = viewModel.pages.value
if (pages != null && pages.size > currentPage) {
showPage(pages[currentPage])
binding.pager.currentItem = currentPage
}
}
}

private fun showPage(page: PageEditingData) {

binding.previous.visibility = if (viewModel.hasPreviousPage()) View.VISIBLE else View.GONE
binding.next.visibility = if (viewModel.hasNextPage()) View.VISIBLE else View.GONE

if (page.image == null) {
binding.image.visibility = View.GONE
} else {
binding.image.visibility = View.VISIBLE
lifecycleScope.launch {
val image = page.image(this@BookViewerActivity)
if (image != null) {
Picasso.get()
.load(image)
.fit()
.centerCrop()
.into(binding.image)
}
}
}

binding.title.text = page.title()
binding.text.text = page.text()
}

companion object {

private const val TAG = "BookViewerActivity"
Expand All @@ -211,4 +218,10 @@ class BookViewerActivity : AppCompatActivity() {

}

private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
override fun getItemCount(): Int = viewModel.pages.value!!.size

override fun createFragment(position: Int): Fragment = BookPageFragment(viewModel.pages.value!![position])
}

}
Binary file added android/src/main/res/drawable/paper.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 9 additions & 42 deletions android/src/main/res/layout/activity_book_viewer.xml
Expand Up @@ -4,77 +4,44 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".bookviewer.BookViewerActivity">
tools:context=".bookviewer.BookViewerActivity"
android:background="@drawable/paper">

<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image"
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:src="@tools:sample/backgrounds/scenic" />

<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constrainedWidth="true"
tools:text="Hubble Space Telescope"
android:textAppearance="?attr/textAppearanceHeadline1"
android:textColor="@color/black"
android:textSize="42sp"
android:background="#88ffffff"
android:padding="12dp"
android:layout_margin="32dp" />

<androidx.appcompat.widget.AppCompatTextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="A bug is a thing which is nice to look at but we don't touch them."
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="@color/black"
android:background="#88ffffff"
android:padding="12dp"
android:layout_margin="16dp" />
/>

<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/previous"
android:id="@+id/previous_overlay"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintWidth_percent=".5"
app:layout_constraintHorizontal_bias="0"
android:alpha="0.2"
android:alpha="0.3"
android:background="@android:color/transparent"
android:src="@drawable/ic_previous"
android:scaleType="fitCenter"
android:adjustViewBounds="true"/>

<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/next"
android:id="@+id/next_overlay"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintWidth_percent=".5"
app:layout_constraintHorizontal_bias="1"
android:alpha="0.2"
android:alpha="0.3"
android:background="@android:color/transparent"
android:src="@drawable/ic_next"
android:scaleType="fitCenter"
Expand Down
2 changes: 2 additions & 0 deletions android/src/main/res/layout/activity_edit_book.xml
Expand Up @@ -3,13 +3,15 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:background="@drawable/paper"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:layout_constraintTop_toTopOf="parent">

<androidx.constraintlayout.widget.ConstraintLayout
Expand Down
2 changes: 2 additions & 0 deletions android/src/main/res/layout/activity_edit_book_page.xml
Expand Up @@ -5,12 +5,14 @@
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/paper"
tools:context=".editbookpage.EditBookPageActivity">

<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:layout_constraintTop_toTopOf="parent">

<androidx.constraintlayout.widget.ConstraintLayout
Expand Down

0 comments on commit 711c502

Please sign in to comment.