Manual screen rotation in reader
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package org.koitharu.kotatsu.ui.reader
|
package org.koitharu.kotatsu.ui.reader
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
@@ -17,10 +18,13 @@ import androidx.core.view.isVisible
|
|||||||
import androidx.core.view.postDelayed
|
import androidx.core.view.postDelayed
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.fragment.app.commit
|
import androidx.fragment.app.commit
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.android.synthetic.main.activity_reader.*
|
import kotlinx.android.synthetic.main.activity_reader.*
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import moxy.MvpDelegate
|
import moxy.MvpDelegate
|
||||||
import moxy.ktx.moxyPresenter
|
import moxy.ktx.moxyPresenter
|
||||||
@@ -40,6 +44,7 @@ import org.koitharu.kotatsu.ui.reader.thumbnails.PagesThumbnailsSheet
|
|||||||
import org.koitharu.kotatsu.ui.reader.wetoon.WebtoonReaderFragment
|
import org.koitharu.kotatsu.ui.reader.wetoon.WebtoonReaderFragment
|
||||||
import org.koitharu.kotatsu.utils.GridTouchHelper
|
import org.koitharu.kotatsu.utils.GridTouchHelper
|
||||||
import org.koitharu.kotatsu.utils.MangaShortcut
|
import org.koitharu.kotatsu.utils.MangaShortcut
|
||||||
|
import org.koitharu.kotatsu.utils.ScreenOrientationHelper
|
||||||
import org.koitharu.kotatsu.utils.ShareHelper
|
import org.koitharu.kotatsu.utils.ShareHelper
|
||||||
import org.koitharu.kotatsu.utils.anim.Motion
|
import org.koitharu.kotatsu.utils.anim.Motion
|
||||||
import org.koitharu.kotatsu.utils.ext.*
|
import org.koitharu.kotatsu.utils.ext.*
|
||||||
@@ -56,6 +61,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
|||||||
private set
|
private set
|
||||||
|
|
||||||
private lateinit var touchHelper: GridTouchHelper
|
private lateinit var touchHelper: GridTouchHelper
|
||||||
|
private lateinit var orientationHelper: ScreenOrientationHelper
|
||||||
private var isTapSwitchEnabled = true
|
private var isTapSwitchEnabled = true
|
||||||
private var isVolumeKeysSwitchEnabled = false
|
private var isVolumeKeysSwitchEnabled = false
|
||||||
|
|
||||||
@@ -67,6 +73,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
|||||||
setContentView(R.layout.activity_reader)
|
setContentView(R.layout.activity_reader)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
touchHelper = GridTouchHelper(this, this)
|
touchHelper = GridTouchHelper(this, this)
|
||||||
|
orientationHelper = ScreenOrientationHelper(this)
|
||||||
toolbar_bottom.inflateMenu(R.menu.opt_reader_bottom)
|
toolbar_bottom.inflateMenu(R.menu.opt_reader_bottom)
|
||||||
toolbar_bottom.setOnMenuItemClickListener(::onOptionsItemSelected)
|
toolbar_bottom.setOnMenuItemClickListener(::onOptionsItemSelected)
|
||||||
|
|
||||||
@@ -89,6 +96,10 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
|||||||
|
|
||||||
settings.subscribe(this)
|
settings.subscribe(this)
|
||||||
loadSettings()
|
loadSettings()
|
||||||
|
orientationHelper.observeAutoOrientation()
|
||||||
|
.onEach {
|
||||||
|
toolbar_bottom.menu.findItem(R.id.action_screen_rotate).isVisible = !it
|
||||||
|
}.launchIn(lifecycleScope)
|
||||||
|
|
||||||
if (savedInstanceState?.containsKey(MvpDelegate.MOXY_DELEGATE_TAGS_KEY) != true) {
|
if (savedInstanceState?.containsKey(MvpDelegate.MOXY_DELEGATE_TAGS_KEY) != true) {
|
||||||
presenter.init(state.manga)
|
presenter.init(state.manga)
|
||||||
@@ -165,6 +176,10 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
|||||||
)
|
)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
R.id.action_screen_rotate -> {
|
||||||
|
orientationHelper.toggleOrientation()
|
||||||
|
true
|
||||||
|
}
|
||||||
R.id.action_pages_thumbs -> {
|
R.id.action_pages_thumbs -> {
|
||||||
if (reader?.hasItems == true) {
|
if (reader?.hasItems == true) {
|
||||||
val pages = reader?.getPages()
|
val pages = reader?.getPages()
|
||||||
@@ -325,14 +340,18 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
|||||||
presenter.setMode(state.manga, mode)
|
presenter.setMode(state.manga, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ShowToast")
|
||||||
override fun onPageSaved(uri: Uri?) {
|
override fun onPageSaved(uri: Uri?) {
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
Snackbar.make(container, R.string.page_saved, Snackbar.LENGTH_LONG)
|
Snackbar.make(container, R.string.page_saved, Snackbar.LENGTH_LONG)
|
||||||
|
.setAnchorView(appbar_bottom)
|
||||||
.setAction(R.string.share) {
|
.setAction(R.string.share) {
|
||||||
ShareHelper.shareImage(this, uri)
|
ShareHelper.shareImage(this, uri)
|
||||||
}.show()
|
}.show()
|
||||||
} else {
|
} else {
|
||||||
Snackbar.make(container, R.string.error_occurred, Snackbar.LENGTH_SHORT).show()
|
Snackbar.make(container, R.string.error_occurred, Snackbar.LENGTH_SHORT)
|
||||||
|
.setAnchorView(appbar_bottom)
|
||||||
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,8 +388,16 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onApplyWindowInsets(v: View, insets: WindowInsets): WindowInsets {
|
override fun onApplyWindowInsets(v: View, insets: WindowInsets): WindowInsets {
|
||||||
appbar_top.updatePadding(top = insets.systemWindowInsetTop)
|
appbar_top.updatePadding(
|
||||||
appbar_bottom.updatePadding(bottom = insets.systemWindowInsetBottom)
|
top = insets.systemWindowInsetTop,
|
||||||
|
right = insets.systemWindowInsetRight,
|
||||||
|
left = insets.systemWindowInsetLeft
|
||||||
|
)
|
||||||
|
appbar_bottom.updatePadding(
|
||||||
|
bottom = insets.systemWindowInsetBottom,
|
||||||
|
right = insets.systemWindowInsetRight,
|
||||||
|
left = insets.systemWindowInsetLeft
|
||||||
|
)
|
||||||
return insets.consumeSystemWindowInsets()
|
return insets.consumeSystemWindowInsets()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package org.koitharu.kotatsu.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.database.ContentObserver
|
||||||
|
import android.os.Handler
|
||||||
|
import android.provider.Settings
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.channels.sendBlocking
|
||||||
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.onStart
|
||||||
|
|
||||||
|
class ScreenOrientationHelper(private val activity: Activity) {
|
||||||
|
|
||||||
|
val isAutoRotationEnabled: Boolean
|
||||||
|
get() = Settings.System.getInt(
|
||||||
|
activity.contentResolver,
|
||||||
|
Settings.System.ACCELEROMETER_ROTATION,
|
||||||
|
0
|
||||||
|
) == 1
|
||||||
|
|
||||||
|
var isLandscape: Boolean
|
||||||
|
get() = activity.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
|
set(value) {
|
||||||
|
activity.requestedOrientation = if (value) {
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
||||||
|
} else {
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toggleOrientation() {
|
||||||
|
isLandscape = !isLandscape
|
||||||
|
}
|
||||||
|
|
||||||
|
fun observeAutoOrientation() = callbackFlow<Boolean> {
|
||||||
|
val observer = object : ContentObserver(Handler(activity.mainLooper)) {
|
||||||
|
override fun onChange(selfChange: Boolean) {
|
||||||
|
sendBlocking(isAutoRotationEnabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activity.contentResolver.registerContentObserver(
|
||||||
|
Settings.System.CONTENT_URI, true, observer
|
||||||
|
)
|
||||||
|
awaitClose {
|
||||||
|
activity.contentResolver.unregisterContentObserver(observer)
|
||||||
|
}
|
||||||
|
}.onStart {
|
||||||
|
emit(isAutoRotationEnabled)
|
||||||
|
}.distinctUntilChanged()
|
||||||
|
}
|
||||||
11
app/src/main/res/drawable/ic_screen_rotation.xml
Normal file
11
app/src/main/res/drawable/ic_screen_rotation.xml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?android:textColorPrimary"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M16.48,2.52c3.27,1.55 5.61,4.72 5.97,8.48h1.5C23.44,4.84 18.29,0 12,0l-0.66,0.03 3.81,3.81 1.33,-1.32zM10.23,1.75c-0.59,-0.59 -1.54,-0.59 -2.12,0L1.75,8.11c-0.59,0.59 -0.59,1.54 0,2.12l12.02,12.02c0.59,0.59 1.54,0.59 2.12,0l6.36,-6.36c0.59,-0.59 0.59,-1.54 0,-2.12L10.23,1.75zM14.83,21.19L2.81,9.17l6.36,-6.36 12.02,12.02 -6.36,6.36zM7.52,21.48C4.25,19.94 1.91,16.76 1.55,13L0.05,13C0.56,19.16 5.71,24 12,24l0.66,-0.03 -3.81,-3.81 -1.33,1.32z" />
|
||||||
|
</vector>
|
||||||
@@ -1,10 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu
|
<menu
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:ignore="AlwaysShowAction">
|
tools:ignore="AlwaysShowAction">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_screen_rotate"
|
||||||
|
android:icon="@drawable/ic_screen_rotation"
|
||||||
|
android:title="@string/rotate_screen"
|
||||||
|
android:visible="false"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_bookmark_add"
|
android:id="@+id/action_bookmark_add"
|
||||||
android:icon="@drawable/ic_bookmark_add"
|
android:icon="@drawable/ic_bookmark_add"
|
||||||
@@ -12,12 +19,6 @@
|
|||||||
android:visible="false"
|
android:visible="false"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always" />
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_save_page"
|
|
||||||
android:icon="@drawable/ic_page_image"
|
|
||||||
android:title="@string/save_page"
|
|
||||||
app:showAsAction="always" />
|
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_pages_thumbs"
|
android:id="@+id/action_pages_thumbs"
|
||||||
android:icon="@drawable/ic_grid"
|
android:icon="@drawable/ic_grid"
|
||||||
@@ -30,10 +31,14 @@
|
|||||||
android:title="@string/read_mode"
|
android:title="@string/read_mode"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_save_page"
|
||||||
|
android:title="@string/save_page"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_settings"
|
android:id="@+id/action_settings"
|
||||||
android:icon="@drawable/ic_tune"
|
|
||||||
android:title="@string/settings"
|
android:title="@string/settings"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<string name="_s_deleted_from_local_storage">\"%s\" удалено с устройства</string>
|
<string name="_s_deleted_from_local_storage">\"%s\" удалено с устройства</string>
|
||||||
<string name="wait_for_loading_finish">Дождитесь окончания загрузки</string>
|
<string name="wait_for_loading_finish">Дождитесь окончания загрузки</string>
|
||||||
<string name="save_page">Сохранить страницу</string>
|
<string name="save_page">Сохранить страницу</string>
|
||||||
<string name="page_saved">Страницы сохранена</string>
|
<string name="page_saved">Страница сохранена</string>
|
||||||
<string name="share_image">Поделиться изображением</string>
|
<string name="share_image">Поделиться изображением</string>
|
||||||
<string name="_import">Импорт</string>
|
<string name="_import">Импорт</string>
|
||||||
<string name="delete">Удалить</string>
|
<string name="delete">Удалить</string>
|
||||||
@@ -142,4 +142,5 @@
|
|||||||
<string name="waiting_for_network">Ожидание подключения…</string>
|
<string name="waiting_for_network">Ожидание подключения…</string>
|
||||||
<string name="clear_updates_feed">Очистить ленту обновлений</string>
|
<string name="clear_updates_feed">Очистить ленту обновлений</string>
|
||||||
<string name="updates_feed_cleared">Лента обновлений очищена</string>
|
<string name="updates_feed_cleared">Лента обновлений очищена</string>
|
||||||
|
<string name="rotate_screen">Повернуть экран</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -143,4 +143,5 @@
|
|||||||
<string name="waiting_for_network">Waiting for network…</string>
|
<string name="waiting_for_network">Waiting for network…</string>
|
||||||
<string name="clear_updates_feed">Clear updates feed</string>
|
<string name="clear_updates_feed">Clear updates feed</string>
|
||||||
<string name="updates_feed_cleared">Updates feed cleared</string>
|
<string name="updates_feed_cleared">Updates feed cleared</string>
|
||||||
|
<string name="rotate_screen">Rotate screen</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user