Optimize layout for tablet

pull/1/head
Koitharu 6 years ago
parent 5f49030926
commit ad201d2bcd

@ -11,9 +11,11 @@ _Coming soon_
### Main Features ### Main Features
* Online manga catalogues * Online manga catalogues
* Search manga by name and genre
* Reading history * Reading history
* Favourites with custom categories * Favourites with custom categories
* Saving manga and reading it offline * Saving manga and reading it offline
* Tablet-optimized modern UI
* Reading third-party comics from CBZ * Reading third-party comics from CBZ
* Standard and Webtoon-optimized reader * Standard and Webtoon-optimized reader

@ -1,17 +1,27 @@
package org.koitharu.kotatsu.ui.common package org.koitharu.kotatsu.ui.common
import android.app.Dialog
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatDialog
import moxy.MvpBottomSheetDialogFragment import moxy.MvpBottomSheetDialogFragment
import org.koitharu.kotatsu.utils.UiUtils
abstract class BaseBottomSheet(@LayoutRes private val layoutResId: Int) : MvpBottomSheetDialogFragment() { abstract class BaseBottomSheet(@LayoutRes private val layoutResId: Int) :
MvpBottomSheetDialogFragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? = inflater.inflate(layoutResId, container, false) ): View? = inflater.inflate(layoutResId, container, false)
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return if (UiUtils.isTablet(requireContext())) {
AppCompatDialog(context, theme)
} else super.onCreateDialog(savedInstanceState)
}
} }

@ -14,6 +14,7 @@ import org.koitharu.kotatsu.ui.common.BaseFragment
import org.koitharu.kotatsu.ui.main.list.favourites.categories.FavouriteCategoriesDialog import org.koitharu.kotatsu.ui.main.list.favourites.categories.FavouriteCategoriesDialog
import org.koitharu.kotatsu.ui.reader.ReaderActivity import org.koitharu.kotatsu.ui.reader.ReaderActivity
import org.koitharu.kotatsu.utils.ext.setChips import org.koitharu.kotatsu.utils.ext.setChips
import org.koitharu.kotatsu.utils.ext.textAndVisible
import kotlin.math.roundToInt import kotlin.math.roundToInt
class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetailsView { class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetailsView {
@ -31,7 +32,7 @@ class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetai
crossfade(true) crossfade(true)
} }
textView_title.text = manga.title textView_title.text = manga.title
textView_subtitle.text = manga.altTitle textView_subtitle.textAndVisible = manga.altTitle
textView_description.text = manga.description?.parseAsHtml()?.takeUnless(Spanned::isBlank) textView_description.text = manga.description?.parseAsHtml()?.takeUnless(Spanned::isBlank)
?: getString(R.string.no_description) ?: getString(R.string.no_description)
if (manga.rating == Manga.NO_RATING) { if (manga.rating == Manga.NO_RATING) {

@ -51,7 +51,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) drawer?.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
adapter = MangaListAdapter(this) adapter = MangaListAdapter(this)
initListMode(settings.listMode) initListMode(settings.listMode)
recyclerView.adapter = adapter recyclerView.adapter = adapter
@ -88,15 +88,15 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
true true
} }
R.id.action_filter -> { R.id.action_filter -> {
drawer.toggleDrawer(GravityCompat.END) drawer?.toggleDrawer(GravityCompat.END)
true true
} }
else -> super.onOptionsItemSelected(item) else -> super.onOptionsItemSelected(item)
} }
override fun onPrepareOptionsMenu(menu: Menu) { override fun onPrepareOptionsMenu(menu: Menu) {
menu.findItem(R.id.action_filter).isVisible = menu.findItem(R.id.action_filter).isVisible = drawer != null &&
drawer.getDrawerLockMode(GravityCompat.END) != DrawerLayout.LOCK_MODE_LOCKED_CLOSED drawer?.getDrawerLockMode(GravityCompat.END) != DrawerLayout.LOCK_MODE_LOCKED_CLOSED
super.onPrepareOptionsMenu(menu) super.onPrepareOptionsMenu(menu)
} }
@ -184,7 +184,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
currentFilter: MangaFilter? currentFilter: MangaFilter?
) { ) {
recyclerView_filter.adapter = FilterAdapter(sortOrders, tags, currentFilter, this) recyclerView_filter.adapter = FilterAdapter(sortOrders, tags, currentFilter, this)
drawer.setDrawerLockMode( drawer?.setDrawerLockMode(
if (sortOrders.isEmpty() && tags.isEmpty()) { if (sortOrders.isEmpty() && tags.isEmpty()) {
DrawerLayout.LOCK_MODE_LOCKED_CLOSED DrawerLayout.LOCK_MODE_LOCKED_CLOSED
} else { } else {
@ -196,7 +196,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
@CallSuper @CallSuper
override fun onFilterChanged(filter: MangaFilter) { override fun onFilterChanged(filter: MangaFilter) {
drawer.closeDrawers() drawer?.closeDrawers()
} }
protected open fun setUpEmptyListHolder() { protected open fun setUpEmptyListHolder() {
@ -210,6 +210,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
recyclerView.adapter = null recyclerView.adapter = null
recyclerView.layoutManager = null recyclerView.layoutManager = null
recyclerView.clearItemDecorations() recyclerView.clearItemDecorations()
recyclerView.removeOnLayoutChangeListener(UiUtils.SpanCountResolver)
adapter?.listMode = mode adapter?.listMode = mode
recyclerView.layoutManager = when (mode) { recyclerView.layoutManager = when (mode) {
ListMode.GRID -> GridLayoutManager(ctx, UiUtils.resolveGridSpanCount(ctx)) ListMode.GRID -> GridLayoutManager(ctx, UiUtils.resolveGridSpanCount(ctx))
@ -225,6 +226,9 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
) )
} }
) )
if(mode == ListMode.GRID) {
recyclerView.addOnLayoutChangeListener(UiUtils.SpanCountResolver)
}
adapter?.notifyDataSetChanged() adapter?.notifyDataSetChanged()
recyclerView.firstItem = position recyclerView.firstItem = position
} }

@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.View import android.view.View
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import kotlinx.android.synthetic.main.sheet_pages.* import kotlinx.android.synthetic.main.sheet_pages.*
@ -33,17 +32,22 @@ class PagesThumbnailsSheet : BaseBottomSheet(R.layout.sheet_pages),
dismissAllowingStateLoss() dismissAllowingStateLoss()
return return
} }
(recyclerView.layoutManager as? GridLayoutManager)?.spanCount = UiUtils.resolveGridSpanCount(view.context)
val title = arguments?.getString(ARG_TITLE) val title = arguments?.getString(ARG_TITLE)
toolbar.title = title toolbar.title = title
toolbar.setNavigationOnClickListener { dismiss() } toolbar.setNavigationOnClickListener { dismiss() }
toolbar.subtitle = resources.getQuantityString(R.plurals.pages, pages.size, pages.size) toolbar.subtitle = resources.getQuantityString(R.plurals.pages, pages.size, pages.size)
textView_title.text = title textView_title.text = title
if (dialog !is BottomSheetDialog) {
toolbar.isVisible = true
textView_title.isVisible = false
appbar.elevation = resources.getDimension(R.dimen.elevation_large)
}
recyclerView.addOnLayoutChangeListener(UiUtils.SpanCountResolver)
} }
override fun onCreateDialog(savedInstanceState: Bundle?) = override fun onCreateDialog(savedInstanceState: Bundle?) =
super.onCreateDialog(savedInstanceState).also { super.onCreateDialog(savedInstanceState).also {
val behavior = (it as BottomSheetDialog).behavior val behavior = (it as? BottomSheetDialog)?.behavior ?: return@also
behavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { behavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
private val elevation = resources.getDimension(R.dimen.elevation_large) private val elevation = resources.getDimension(R.dimen.elevation_large)
@ -52,15 +56,16 @@ class PagesThumbnailsSheet : BaseBottomSheet(R.layout.sheet_pages),
override fun onStateChanged(bottomSheet: View, newState: Int) { override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) { if (newState == BottomSheetBehavior.STATE_EXPANDED) {
toolbar.isVisible = true toolbar.isVisible = true
textView_title.isVisible = false
appbar.elevation = elevation appbar.elevation = elevation
} else { } else {
toolbar.isVisible = false toolbar.isVisible = false
textView_title.isVisible = true
appbar.elevation = 0f appbar.elevation = 0f
} }
} }
}) })
// behavior.peekHeight = BottomSheetBehavior.PEEK_HEIGHT_AUTO
// behavior.isFitToContents = false
} }
override fun onDestroyView() { override fun onDestroyView() {

@ -3,22 +3,62 @@ package org.koitharu.kotatsu.ui.settings
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.commit import androidx.fragment.app.commit
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import kotlinx.android.synthetic.main.activity_settings.*
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.ui.common.BaseActivity import org.koitharu.kotatsu.ui.common.BaseActivity
class SettingsActivity : BaseActivity() { class SettingsActivity : BaseActivity(),
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings) setContentView(R.layout.activity_settings)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
val isTablet = container_side != null
if (supportFragmentManager.findFragmentById(R.id.container) == null) { if (supportFragmentManager.findFragmentById(R.id.container) == null) {
supportFragmentManager.beginTransaction() supportFragmentManager.commit {
.replace(R.id.container, SettingsHeadersFragment()) if (isTablet) {
.commit() replace(R.id.container_side, SettingsHeadersFragment())
replace(R.id.container, AppearanceSettingsFragment())
} else {
replace(R.id.container, SettingsHeadersFragment())
}
}
}
}
override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference): Boolean {
val fm = supportFragmentManager
if (container_side != null && caller is SettingsHeadersFragment) {
fm.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
}
val fragment = fm.fragmentFactory.instantiate(classLoader, pref.fragment)
fragment.arguments = pref.extras
fragment.setTargetFragment(caller, 0)
fm.commit {
replace(R.id.container, fragment)
if (container_side == null || caller !is SettingsHeadersFragment) {
addToBackStack(null)
}
}
return true
}
override fun onTitleChanged(title: CharSequence?, color: Int) {
if (container_side == null) {
super.onTitleChanged(title, color)
} else {
if (supportFragmentManager.backStackEntryCount == 0) {
supportActionBar?.subtitle = null
} else {
supportActionBar?.subtitle = title
}
} }
} }

@ -9,4 +9,5 @@ class SettingsHeadersFragment : BasePreferenceFragment(R.string.settings) {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.pref_headers) addPreferencesFromResource(R.xml.pref_headers)
} }
} }

@ -2,8 +2,12 @@ package org.koitharu.kotatsu.utils
import android.content.Context import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.view.View
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import kotlin.math.abs
import kotlin.math.roundToInt import kotlin.math.roundToInt
object UiUtils { object UiUtils {
@ -19,10 +23,31 @@ object UiUtils {
} }
@JvmStatic @JvmStatic
fun resolveGridSpanCount(context: Context): Int { fun resolveGridSpanCount(context: Context, width: Int = 0): Int {
val cellWidth = context.resources.getDimensionPixelSize(R.dimen.preferred_grid_width) val cellWidth = context.resources.getDimensionPixelSize(R.dimen.preferred_grid_width)
val screenWidth = context.resources.displayMetrics.widthPixels.toDouble() val screenWidth = (if (width <= 0) {
context.resources.displayMetrics.widthPixels
} else width).toDouble()
val estimatedCount = (screenWidth / cellWidth).roundToInt() val estimatedCount = (screenWidth / cellWidth).roundToInt()
return estimatedCount.coerceAtLeast(2) return estimatedCount.coerceAtLeast(2)
} }
@JvmStatic
fun isTablet(context: Context) = context.resources.getBoolean(R.bool.is_tablet)
object SpanCountResolver : View.OnLayoutChangeListener {
override fun onLayoutChange(
v: View?, left: Int, top: Int, right: Int, bottom: Int,
oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int
) {
val rv = v as? RecyclerView ?: return
val width = abs(right - left)
if (width == 0) {
return
}
(rv.layoutManager as? GridLayoutManager)?.spanCount =
resolveGridSpanCount(rv.context, width)
}
}
} }

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorButtonNormal"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:background="?colorPrimary"
android:theme="@style/AppToolbarTheme">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppPopupTheme" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/container_side"
android:layout_width="340dp"
android:layout_height="match_parent"
android:layout_below="@id/appbar"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true" />
<com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/appbar"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_margin="16dp"
android:layout_toEndOf="@id/container_side"
app:cardBackgroundColor="?android:windowBackground">
<androidx.fragment.app.FragmentContainerView
android:id="@id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.google.android.material.card.MaterialCardView>
</RelativeLayout>

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
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="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageView_cover"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintDimensionRatio="13:18"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.3" />
<TextView
android:id="@+id/textView_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:maxLines="3"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textColor="?android:textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/imageView_cover"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/lorem[20]" />
<TextView
android:id="@+id/textView_subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:maxLines="2"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="?android:textColorSecondary"
app:layout_constraintEnd_toEndOf="@id/textView_title"
app:layout_constraintStart_toStartOf="@id/textView_title"
app:layout_constraintTop_toBottomOf="@id/textView_title"
tools:text="@tools:sample/lorem[20]" />
<RatingBar
android:id="@+id/ratingBar"
style="@style/Widget.AppCompat.RatingBar.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:isIndicator="true"
android:max="100"
app:layout_constraintStart_toStartOf="@id/textView_title"
app:layout_constraintTop_toBottomOf="@id/textView_subtitle"
tools:progress="70" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_read"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:enabled="false"
android:text="@string/read"
app:icon="@drawable/ic_read"
app:iconPadding="12dp"
app:layout_constraintEnd_toEndOf="@id/textView_title"
app:layout_constraintTop_toBottomOf="@id/ratingBar" />
<ImageView
android:id="@+id/imageView_favourite"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="4dp"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/add_to_favourites"
android:scaleType="center"
android:src="@drawable/ic_tag_heart_outline"
app:layout_constraintBottom_toBottomOf="@id/button_read"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toStartOf="@id/button_read"
app:layout_constraintTop_toTopOf="@id/button_read"
app:tint="?colorAccent" />
<View
android:id="@+id/divider_top"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:background="?android:listDivider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/imageView_cover"
app:layout_constraintTop_toBottomOf="@id/button_read" />
<com.google.android.material.chip.ChipGroup
android:id="@+id/chips_tags"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:padding="6dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/imageView_cover"
app:layout_constraintTop_toBottomOf="@id/divider_top" />
<TextView
android:id="@+id/textView_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:justificationMode="inter_word"
android:lineSpacingMultiplier="1.2"
android:padding="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/imageView_cover"
app:layout_constraintTop_toBottomOf="@id/chips_tags"
tools:text="@tools:sample/lorem/random" />
<ProgressBar
android:id="@+id/progressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/divider_top"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/imageView_cover"
app:layout_constraintTop_toBottomOf="@id/divider_top"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

@ -0,0 +1,79 @@
<?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:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="end">
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_manga_list" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<LinearLayout
android:id="@+id/layout_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/textView_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:textColor="?android:textColorSecondary"
android:textAppearance="?android:textAppearanceMedium"
tools:text="@tools:sample/lorem[3]" />
</LinearLayout>
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminate="true" />
</FrameLayout>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="?dividerVertical" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView_filter"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:background="?android:windowBackground"
android:orientation="vertical"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_category_checkable" />
</LinearLayout>

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
xmlns:tools="http://schemas.android.com/tools">
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
android:id="@+id/ssiv" android:id="@+id/ssiv"
@ -17,31 +17,33 @@
android:layout_gravity="center" /> android:layout_gravity="center" />
<LinearLayout <LinearLayout
android:id="@+id/layout_error"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:orientation="vertical"
android:layout_marginStart="60dp" android:layout_marginStart="60dp"
android:layout_marginEnd="60dp" android:layout_marginEnd="60dp"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:id="@+id/layout_error" > android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<TextView <TextView
android:drawableTop="@drawable/ic_error_large"
android:id="@+id/textView_error" android:id="@+id/textView_error"
android:layout_width="wrap_content" android:layout_width="wrap_content"
tools:text="@tools:sample/lorem[6]" android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_error_large"
android:drawablePadding="12dp" android:drawablePadding="12dp"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:layout_height="wrap_content" /> android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="@tools:sample/lorem[6]" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/button_retry" android:id="@+id/button_retry"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:text="@string/try_again" /> android:text="@string/try_again" />
</LinearLayout> </LinearLayout>

@ -1,26 +1,28 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:background="?attr/scrimBackground" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:background="?attr/scrimBackground">
<org.koitharu.kotatsu.ui.common.widgets.CoverImageView <org.koitharu.kotatsu.ui.common.widgets.CoverImageView
android:id="@+id/imageView_thumb" android:id="@+id/imageView_thumb"
android:scaleType="centerCrop"
tools:src="@drawable/ic_placeholder"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
android:scaleType="centerCrop"
tools:src="@drawable/ic_placeholder" />
<TextView <TextView
android:id="@+id/textView_number"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:text="2"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:padding="12dp"
android:gravity="end|bottom"
android:background="?android:selectableItemBackground" android:background="?android:selectableItemBackground"
android:id="@+id/textView_number" /> android:ellipsize="none"
android:gravity="end|bottom"
android:padding="12dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
tools:text="2" />
</FrameLayout> </FrameLayout>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="is_tablet">true</bool>
</resources>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="is_tablet">false</bool>
</resources>

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen <PreferenceScreen
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">
<PreferenceScreen <PreferenceScreen
android:fragment="org.koitharu.kotatsu.ui.settings.AppearanceSettingsFragment" android:fragment="org.koitharu.kotatsu.ui.settings.AppearanceSettingsFragment"

Loading…
Cancel
Save