Enhance tablet ui

This commit is contained in:
Koitharu
2022-03-11 19:22:31 +02:00
parent 445ff89392
commit 0b07e83e3c
11 changed files with 267 additions and 63 deletions

View File

@@ -9,6 +9,8 @@ import androidx.appcompat.view.ActionMode
import androidx.core.graphics.Insets
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative
import androidx.fragment.app.FragmentContainerView
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.divider.MaterialDividerItemDecoration
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
@@ -24,6 +26,7 @@ import org.koitharu.kotatsu.details.ui.model.ChapterListItem
import org.koitharu.kotatsu.download.ui.service.DownloadService
import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.utils.ext.getEnd
class ChaptersFragment : BaseFragment<FragmentChaptersBinding>(),
OnListItemClickListener<ChapterListItem>,
@@ -200,11 +203,19 @@ class ChaptersFragment : BaseFragment<FragmentChaptersBinding>(),
}
override fun onWindowInsetsChanged(insets: Insets) {
binding.recyclerViewChapters.updatePadding(
left = insets.left,
right = insets.right,
bottom = insets.bottom + binding.spinnerBranches.height
)
val root = binding.root
if (root.parent is FragmentContainerView) {
binding.recyclerViewChapters.updatePaddingRelative(
end = insets.getEnd(root),
bottom = insets.bottom + binding.spinnerBranches.height,
)
} else {
binding.recyclerViewChapters.updatePadding(
left = insets.left,
right = insets.right,
bottom = insets.bottom + binding.spinnerBranches.height,
)
}
}
private fun onChaptersChanged(list: List<ChapterListItem>) {

View File

@@ -17,14 +17,12 @@ import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import kotlinx.coroutines.launch
import org.koin.android.ext.android.get
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.domain.MangaIntent
import org.koitharu.kotatsu.base.ui.BaseActivity
@@ -43,8 +41,7 @@ import org.koitharu.kotatsu.utils.ShareHelper
import org.koitharu.kotatsu.utils.ext.buildAlertDialog
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
class DetailsActivity : BaseActivity<ActivityDetailsBinding>(),
TabLayoutMediator.TabConfigurationStrategy {
class DetailsActivity : BaseActivity<ActivityDetailsBinding>(), TabLayoutMediator.TabConfigurationStrategy {
private val viewModel by viewModel<DetailsViewModel> {
parametersOf(MangaIntent(intent))
@@ -54,8 +51,11 @@ class DetailsActivity : BaseActivity<ActivityDetailsBinding>(),
super.onCreate(savedInstanceState)
setContentView(ActivityDetailsBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
binding.pager.adapter = MangaDetailsAdapter(this)
TabLayoutMediator(binding.tabs, binding.pager, this).attach()
val pager = binding.pager
if (pager != null) {
pager.adapter = MangaDetailsAdapter(this)
TabLayoutMediator(checkNotNull(binding.tabs), pager, this).attach()
}
viewModel.manga.observe(this, ::onMangaUpdated)
viewModel.newChaptersCount.observe(this, ::onNewChaptersChanged)
@@ -105,8 +105,9 @@ class DetailsActivity : BaseActivity<ActivityDetailsBinding>(),
topMargin = insets.top
}
}
if (binding.tabs.parent !is Toolbar) {
binding.tabs.updatePadding(
val tabs = binding.tabs
if (tabs != null && tabs.parent !is Toolbar) {
tabs.updatePadding(
left = insets.left,
right = insets.right
)
@@ -114,7 +115,7 @@ class DetailsActivity : BaseActivity<ActivityDetailsBinding>(),
}
private fun onNewChaptersChanged(newChapters: Int) {
val tab = binding.tabs.getTabAt(1) ?: return
val tab = binding.tabs?.getTabAt(1) ?: return
if (newChapters == 0) {
tab.removeBadge()
} else {
@@ -208,11 +209,7 @@ class DetailsActivity : BaseActivity<ActivityDetailsBinding>(),
viewModel.manga.value?.let {
lifecycleScope.launch {
if (!get<ShortcutsRepository>().requestPinShortcut(it)) {
Snackbar.make(
binding.pager,
R.string.operation_not_supported,
Snackbar.LENGTH_SHORT
).show()
binding.snackbar.show(getString(R.string.operation_not_supported))
}
}
}
@@ -231,19 +228,18 @@ class DetailsActivity : BaseActivity<ActivityDetailsBinding>(),
override fun onSupportActionModeStarted(mode: ActionMode) {
super.onSupportActionModeStarted(mode)
binding.pager.isUserInputEnabled = false
binding.pager?.isUserInputEnabled = false
}
override fun onSupportActionModeFinished(mode: ActionMode) {
super.onSupportActionModeFinished(mode)
binding.pager.isUserInputEnabled = true
binding.pager?.isUserInputEnabled = true
}
fun showChapterMissingDialog(chapterId: Long) {
val remoteManga = viewModel.getRemoteManga()
if (remoteManga == null) {
Snackbar.make(binding.pager, R.string.chapter_is_missing, Snackbar.LENGTH_LONG)
.show()
binding.snackbar.show(getString( R.string.chapter_is_missing))
return
}
buildAlertDialog(this) {
@@ -268,8 +264,6 @@ class DetailsActivity : BaseActivity<ActivityDetailsBinding>(),
companion object {
const val ACTION_MANGA_VIEW = "${BuildConfig.APPLICATION_ID}.action.VIEW_MANGA"
fun newIntent(context: Context, manga: Manga): Intent {
return Intent(context, DetailsActivity::class.java)
.putExtra(MangaIntent.KEY_MANGA, manga)

View File

@@ -13,6 +13,8 @@ import androidx.core.net.toUri
import androidx.core.text.parseAsHtml
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative
import androidx.fragment.app.FragmentContainerView
import coil.ImageLoader
import coil.request.ImageRequest
import coil.util.CoilUtils
@@ -232,11 +234,19 @@ class DetailsFragment : BaseFragment<FragmentDetailsBinding>(), View.OnClickList
}
override fun onWindowInsetsChanged(insets: Insets) {
binding.root.updatePadding(
left = insets.left,
right = insets.right,
bottom = insets.bottom
)
val root = binding.root
if (root.parent is FragmentContainerView) {
root.updatePaddingRelative(
start = insets.getStart(root),
bottom = insets.bottom,
)
} else {
root.updatePadding(
left = insets.left,
right = insets.right,
bottom = insets.bottom,
)
}
}
private fun bindTags(manga: Manga) {

View File

@@ -53,10 +53,7 @@ import org.koitharu.kotatsu.suggestions.ui.SuggestionsFragment
import org.koitharu.kotatsu.suggestions.ui.SuggestionsWorker
import org.koitharu.kotatsu.tracker.ui.FeedFragment
import org.koitharu.kotatsu.tracker.work.TrackWorker
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.hideKeyboard
import org.koitharu.kotatsu.utils.ext.measureHeight
import org.koitharu.kotatsu.utils.ext.resolveDp
import org.koitharu.kotatsu.utils.ext.*
private const val TAG_PRIMARY = "primary"
private const val TAG_SEARCH = "search"
@@ -69,7 +66,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
private val searchSuggestionViewModel by viewModel<SearchSuggestionViewModel>()
private lateinit var navHeaderBinding: NavigationHeaderBinding
private lateinit var drawerToggle: ActionBarDrawerToggle
private var drawerToggle: ActionBarDrawerToggle? = null
private var drawer: DrawerLayout? = null
override val appBar: AppBarLayout
get() = binding.appbar
@@ -78,24 +76,31 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
super.onCreate(savedInstanceState)
setContentView(ActivityMainBinding.inflate(layoutInflater))
navHeaderBinding = NavigationHeaderBinding.inflate(layoutInflater)
drawerToggle = ActionBarDrawerToggle(
this,
binding.drawer,
binding.toolbar,
R.string.open_menu,
R.string.close_menu
)
drawerToggle.setHomeAsUpIndicator(ContextCompat.getDrawable(this, R.drawable.ic_arrow_back))
drawerToggle.setToolbarNavigationClickListener {
binding.searchView.hideKeyboard()
onBackPressed()
drawer = binding.root as? DrawerLayout
drawerToggle = drawer?.let {
ActionBarDrawerToggle(
this,
it,
binding.toolbar,
R.string.open_menu,
R.string.close_menu
).apply {
setHomeAsUpIndicator(ContextCompat.getDrawable(this@MainActivity, R.drawable.ic_arrow_back))
setToolbarNavigationClickListener {
binding.searchView.hideKeyboard()
onBackPressed()
}
it.addDrawerListener(this)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
}
binding.drawer.addDrawerListener(drawerToggle)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
with(binding.searchView) {
onFocusChangeListener = this@MainActivity
searchSuggestionListener = this@MainActivity
if (drawer == null) {
drawableStart = ContextCompat.getDrawable(context, R.drawable.ic_search)
}
}
with(binding.navigationView) {
@@ -132,26 +137,27 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
drawerToggle.isDrawerIndicatorEnabled =
binding.drawer.getDrawerLockMode(GravityCompat.START) == DrawerLayout.LOCK_MODE_UNLOCKED
drawerToggle?.isDrawerIndicatorEnabled =
drawer?.getDrawerLockMode(GravityCompat.START) == DrawerLayout.LOCK_MODE_UNLOCKED
}
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
drawerToggle.syncState()
drawerToggle?.syncState()
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
drawerToggle.onConfigurationChanged(newConfig)
drawerToggle?.onConfigurationChanged(newConfig)
}
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentByTag(TAG_SEARCH)
binding.searchView.clearFocus()
when {
binding.drawer.isDrawerOpen(binding.navigationView) -> binding.drawer.closeDrawer(
binding.navigationView)
drawer?.isDrawerOpen(binding.navigationView) == true -> {
drawer?.closeDrawer(binding.navigationView)
}
fragment != null -> supportFragmentManager.commit {
remove(fragment)
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
@@ -162,7 +168,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return drawerToggle.onOptionsItemSelected(item) || when (item.itemId) {
return drawerToggle?.onOptionsItemSelected(item) == true || when (item.itemId) {
else -> super.onOptionsItemSelected(item)
}
}
@@ -208,7 +214,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
else -> return false
}
}
binding.drawer.closeDrawers()
drawer?.closeDrawers()
return true
}
@@ -221,8 +227,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
leftMargin = insets.left + topMargin
rightMargin = insets.right + topMargin
}
binding.container.updateLayoutParams<MarginLayoutParams> {
topMargin = -(binding.appbar.measureHeight())
if (drawer != null) {
binding.container.updateLayoutParams<MarginLayoutParams> {
topMargin = -(binding.appbar.measureHeight())
}
}
}
@@ -354,13 +362,13 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
}
private fun onSearchOpened() {
binding.drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
drawerToggle.isDrawerIndicatorEnabled = false
drawer?.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
drawerToggle?.isDrawerIndicatorEnabled = false
}
private fun onSearchClosed() {
binding.drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
drawerToggle.isDrawerIndicatorEnabled = true
drawer?.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
drawerToggle?.isDrawerIndicatorEnabled = true
}
private fun onFirstStart() {

View File

@@ -0,0 +1,20 @@
package org.koitharu.kotatsu.utils.ext
import android.view.View
import androidx.core.graphics.Insets
fun Insets.getStart(view: View): Int {
return if (view.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
right
} else {
left
}
}
fun Insets.getEnd(view: View): Int {
return if (view.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
left
} else {
right
}
}

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:keylines="@array/keylines_details"
tools:context=".details.ui.DetailsActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
app:liftOnScroll="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_scrollFlags="scroll|enterAlways" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/container_details"
android:name="org.koitharu.kotatsu.details.ui.DetailsFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
app:layout_keyline="0"
tools:layout="@layout/fragment_details" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/container_chapters"
android:name="org.koitharu.kotatsu.details.ui.ChaptersFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="end"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
app:layout_keyline="0"
tools:layout="@layout/fragment_chapters" />
<org.koitharu.kotatsu.base.ui.widgets.FadingSnackbar
android:id="@+id/snackbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:visibility="gone" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<com.google.android.material.navigation.NavigationView
android:id="@+id/navigationView"
android:layout_width="260dp"
android:layout_height="match_parent"
app:drawerLayoutCornerSize="0dp"
app:elevation="0dp"
android:fitsSystemWindows="false"
app:menu="@menu/nav_drawer" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:stateListAnimator="@null">
<FrameLayout
android:id="@+id/toolbar_card"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:background="@drawable/toolbar_background">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:focusable="true"
android:focusableInTouchMode="true"
app:contentInsetStartWithNavigation="0dp"
app:titleTextAppearance="@style/TextAppearance.Kotatsu.PersistentToolbarTitle"
app:titleTextColor="?android:colorControlNormal"
tools:title="@string/app_name">
<org.koitharu.kotatsu.search.ui.widget.SearchEditText
android:id="@+id/searchView"
style="@style/Widget.Kotatsu.SearchView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:drawablePadding="6dp"
android:gravity="center_vertical"
android:hint="@string/search_manga"
android:imeOptions="actionSearch"
android:importantForAutofill="no"
android:paddingBottom="1dp"
android:singleLine="true" />
</com.google.android.material.appbar.MaterialToolbar>
</FrameLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
tools:layout="@layout/fragment_list" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:contentDescription="@string/_continue"
android:src="@drawable/ic_read_fill"
android:visibility="gone"
app:backgroundTint="?attr/colorContainer"
app:fabSize="normal"
app:layout_anchor="@id/container"
app:layout_anchorGravity="bottom|end"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
app:layout_dodgeInsetEdges="bottom"
tools:visibility="visible" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View File

@@ -3,7 +3,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".main.ui.MainActivity">
@@ -16,6 +15,7 @@
android:id="@id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_list"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
<com.google.android.material.appbar.AppBarLayout

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="keylines_details">
<item>760</item>
</array>
</resources>

View File

@@ -21,4 +21,8 @@
<!--Text dimens-->
<!-- Keylines -->
<array name="keylines_details">
<item>600</item>
</array>
</resources>