UI changes

This commit is contained in:
ztimms73
2021-06-20 19:30:29 +03:00
parent de3c4545e6
commit 49e08eaf2f
37 changed files with 154 additions and 1368 deletions

View File

@@ -11,13 +11,6 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<queries>
<intent>
<action android:name="android.speech.RecognitionService" />
</intent>
</queries>
<application
android:name="org.koitharu.kotatsu.KotatsuApp"

View File

@@ -57,7 +57,7 @@ abstract class BaseActivity<B : ViewBinding> : AppCompatActivity(), OnApplyWindo
this.binding = binding
super.setContentView(binding.root)
(binding.root.findViewById<View>(R.id.toolbar) as? Toolbar)?.let(this::setSupportActionBar)
val params = (binding.root.findViewById<View>(R.id.toolbar) as? Toolbar)?.layoutParams as? AppBarLayout.LayoutParams
val params = (binding.root.findViewById<View>(R.id.toolbar_card))?.layoutParams as? AppBarLayout.LayoutParams
ViewCompat.setOnApplyWindowInsetsListener(binding.root, this)
if (get<AppSettings>().isToolbarHideWhenScrolling) {
params?.scrollFlags = SCROLL_FLAG_SCROLL or SCROLL_FLAG_ENTER_ALWAYS

View File

@@ -1,231 +0,0 @@
/*https://github.com/lapism/search*/
package org.koitharu.kotatsu.base.ui.widgets.search
import android.animation.LayoutTransition
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.widgets.search.internal.SearchLayout
class MaterialSearchView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : SearchLayout(context, attrs, defStyleAttr, defStyleRes), CoordinatorLayout.AttachedBehavior {
// *********************************************************************************************
private var mBehavior: CoordinatorLayout.Behavior<*> = SearchBehavior<MaterialSearchView>()
private var mTransition: LayoutTransition? = null
private var mStrokeWidth: Int = 0
private var mRadius: Float = 0f
private var mElevation: Float = 0f
// *********************************************************************************************
init {
inflate(context, R.layout.layout_search_view, this)
init()
setTransition()
val a = context.obtainStyledAttributes(
attrs, R.styleable.MaterialSearchView, defStyleAttr, defStyleRes
)
if (a.hasValue(R.styleable.MaterialSearchView_search_navigationIconSupport)) {
navigationIconSupport = a.getInt(
R.styleable.MaterialSearchView_search_navigationIconSupport,
NavigationIconSupport.NONE
)
}
if (a.hasValue(R.styleable.MaterialSearchView_search_navigationIcon)) {
setNavigationIconImageDrawable(a.getDrawable(R.styleable.MaterialSearchView_search_navigationIcon))
}
if (a.hasValue(R.styleable.MaterialSearchView_search_clearIcon)) {
setClearIconImageDrawable(a.getDrawable(R.styleable.MaterialSearchView_search_clearIcon))
} else {
setClearIconImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.ic_clear
)
)
}
if (a.hasValue(R.styleable.MaterialSearchView_search_micIcon)) {
setMicIconImageDrawable(a.getDrawable(R.styleable.MaterialSearchView_search_micIcon))
} else {
setMicIconImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.ic_mic_none
)
)
}
if (a.hasValue(R.styleable.MaterialSearchView_search_menuIcon)) {
setMicIconImageDrawable(a.getDrawable(R.styleable.MaterialSearchView_search_menuIcon))
} else {
setMicIconImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.ic_more
)
)
}
if (a.hasValue(R.styleable.MaterialSearchView_search_dividerColor)) {
setDividerColor(a.getInt(R.styleable.MaterialSearchView_search_dividerColor, 0))
}
val defaultShadowColor = ContextCompat.getColor(context, R.color.shadow)
setShadowColor(
a.getInt(
R.styleable.MaterialSearchView_search_shadowColor,
defaultShadowColor
)
)
if (a.hasValue(R.styleable.MaterialSearchView_search_textHint)) {
setTextHint(a.getText(R.styleable.MaterialSearchView_search_textHint))
}
if (a.hasValue(R.styleable.MaterialSearchView_search_strokeColor)) {
setBackgroundStrokeColor(a.getInt(R.styleable.MaterialSearchView_search_strokeColor, 0))
}
if (a.hasValue(R.styleable.MaterialSearchView_search_strokeWidth)) {
setBackgroundStrokeWidth(a.getInt(R.styleable.MaterialSearchView_search_strokeWidth, 0))
}
val defaultTransitionDuration =
context.resources.getInteger(R.integer.search_animation_duration)
setTransitionDuration(
a.getInt(
R.styleable.MaterialSearchView_search_transitionDuration,
defaultTransitionDuration
).toLong()
)
val defaultRadius = context.resources.getDimensionPixelSize(R.dimen.search_radius)
setBackgroundRadius(
a.getInt(R.styleable.MaterialSearchView_search_radius, defaultRadius).toFloat()
)
val defaultElevation = context.resources.getDimensionPixelSize(R.dimen.search_elevation)
elevation =
a.getInt(R.styleable.MaterialSearchView_android_elevation, defaultElevation).toFloat()
val imeOptions = a.getInt(R.styleable.MaterialSearchView_android_imeOptions, -1)
if (imeOptions != -1) {
setTextImeOptions(imeOptions)
}
val inputType = a.getInt(R.styleable.MaterialSearchView_android_inputType, -1)
if (inputType != -1) {
setTextInputType(inputType)
}
a.recycle()
}
// *********************************************************************************************
override fun addFocus() {
mOnFocusChangeListener?.onFocusChange(true)
showKeyboard()
mStrokeWidth = getBackgroundStrokeWidth()
mRadius = getBackgroundRadius()
mElevation = elevation
setBackgroundStrokeWidth(context.resources.getDimensionPixelSize(R.dimen.search_stroke_width_focus))
setBackgroundRadius(resources.getDimensionPixelSize(R.dimen.search_radius_focus).toFloat())
elevation =
context.resources.getDimensionPixelSize(R.dimen.search_elevation_focus).toFloat()
val left = context.resources.getDimensionPixelSize(R.dimen.search_dp_16)
val params = mSearchEditText?.layoutParams as LinearLayout.LayoutParams
params.setMargins(left, 0, 0, 0)
mSearchEditText?.layoutParams = params
margins = Margins.FOCUS
setLayoutHeight(context.resources.getDimensionPixelSize(R.dimen.search_layout_height_focus))
mViewShadow?.visibility = View.VISIBLE
mViewDivider?.visibility = View.VISIBLE
mViewAnim?.visibility = View.VISIBLE
mRecyclerView?.visibility = View.VISIBLE
// layoutTransition = null
}
override fun removeFocus() {
// layoutTransition = mTransition
mOnFocusChangeListener?.onFocusChange(false)
hideKeyboard()
val params = mSearchEditText?.layoutParams as LinearLayout.LayoutParams
params.setMargins(0, 0, 0, 0)
mSearchEditText?.layoutParams = params
setBackgroundStrokeWidth(mStrokeWidth)
setBackgroundRadius(mRadius)
elevation = mElevation
setLayoutHeight(context.resources.getDimensionPixelSize(R.dimen.search_layout_height))
margins = Margins.NO_FOCUS
mViewShadow?.visibility = View.GONE
mRecyclerView?.visibility = View.GONE
mViewAnim?.visibility = View.GONE
mViewDivider?.visibility = View.GONE
}
override fun getBehavior(): CoordinatorLayout.Behavior<*> {
return mBehavior
}
fun setBehavior(behavior: CoordinatorLayout.Behavior<*>) {
mBehavior = behavior
}
fun setTransitionDuration(duration: Long) {
mTransition?.setDuration(duration)
layoutTransition = mTransition
}
private fun setTransition() {
mTransition = LayoutTransition()
mTransition?.enableTransitionType(LayoutTransition.CHANGING)
mTransition?.addTransitionListener(object : LayoutTransition.TransitionListener {
override fun startTransition(
transition: LayoutTransition?,
container: ViewGroup?,
view: View?,
transitionType: Int
) {
}
override fun endTransition(
transition: LayoutTransition?,
container: ViewGroup?,
view: View?,
transitionType: Int
) {
}
})
}
}

View File

@@ -1,62 +0,0 @@
/*https://github.com/lapism/search*/
package org.koitharu.kotatsu.base.ui.widgets.search
import android.animation.ObjectAnimator
import android.content.Context
import android.util.Property
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.appcompat.graphics.drawable.DrawerArrowDrawable
import androidx.core.content.ContextCompat
class SearchArrowDrawable constructor(context: Context) : DrawerArrowDrawable(context) {
var position: Float
get() = progress
set(position) {
progress = position
}
init {
color = ContextCompat.getColor(context, android.R.color.white)
}
fun animate(state: Float, duration: Long) {
val anim: ObjectAnimator = if (state == ARROW) {
ObjectAnimator.ofFloat(
this,
PROGRESS,
MENU,
state
)
} else {
ObjectAnimator.ofFloat(
this,
PROGRESS,
ARROW,
state
)
}
anim.interpolator = AccelerateDecelerateInterpolator()
anim.duration = duration
anim.start()
}
companion object {
const val MENU = 0.0f
const val ARROW = 1.0f
private val PROGRESS =
object : Property<SearchArrowDrawable, Float>(Float::class.java, "progress") {
override fun set(obj: SearchArrowDrawable, value: Float?) {
obj.progress = value!!
}
override fun get(obj: SearchArrowDrawable): Float {
return obj.progress
}
}
}
}

View File

@@ -1,54 +0,0 @@
/*https://github.com/lapism/search*/
package org.koitharu.kotatsu.base.ui.widgets.search
import android.view.View
import android.widget.LinearLayout
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.ViewCompat
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.bottomnavigation.BottomNavigationView
import org.koitharu.kotatsu.base.ui.widgets.search.internal.SearchLayout
class SearchBehavior<S : SearchLayout> : CoordinatorLayout.Behavior<S>() {
override fun layoutDependsOn(
parent: CoordinatorLayout,
child: S,
dependency: View
): Boolean {
return if (dependency is AppBarLayout) {
true
} else
if (dependency is LinearLayout || dependency is BottomNavigationView) {
dependency.z = child.z + 1
true
} else {
super.layoutDependsOn(parent, child, dependency)
}
}
override fun onDependentViewChanged(
parent: CoordinatorLayout,
child: S,
dependency: View
): Boolean {
if (dependency is AppBarLayout) {
child.translationY = dependency.getY()
return true
}
return super.onDependentViewChanged(parent, child, dependency)
}
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: S,
directTargetChild: View,
target: View,
axes: Int,
type: Int
): Boolean {
return axes == ViewCompat.SCROLL_AXIS_VERTICAL
}
}

View File

@@ -1,40 +0,0 @@
/*https://github.com/lapism/search*/
package org.koitharu.kotatsu.base.ui.widgets.search.internal
import android.content.Context
import android.util.AttributeSet
import android.view.KeyEvent
import androidx.annotation.AttrRes
import androidx.appcompat.widget.AppCompatEditText
class SearchEditText : AppCompatEditText {
var clearFocusOnBackPressed: Boolean = false
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, @AttrRes defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
override fun onKeyPreIme(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP && clearFocusOnBackPressed) {
if (hasFocus()) {
clearFocus()
return true
}
}
return super.onKeyPreIme(keyCode, event)
}
override fun clearFocus() {
super.clearFocus()
text?.clear()
}
}

View File

@@ -1,725 +0,0 @@
/*https://github.com/lapism/search*/
package org.koitharu.kotatsu.base.ui.widgets.search.internal
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.ColorFilter
import android.graphics.PorterDuff
import android.graphics.Rect
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.os.Parcelable
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import android.widget.ImageButton
import android.widget.LinearLayout
import androidx.annotation.*
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.card.MaterialCardView
import org.koitharu.kotatsu.R
abstract class SearchLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes), View.OnClickListener {
// *********************************************************************************************
// Better way than enum class :-)
@IntDef(
NavigationIconSupport.NONE,
NavigationIconSupport.MENU,
NavigationIconSupport.ARROW,
NavigationIconSupport.SEARCH
)
@Retention(AnnotationRetention.SOURCE)
annotation class NavigationIconSupport {
companion object {
const val NONE = 0
const val MENU = 1
const val ARROW = 2
const val SEARCH = 3
}
}
@IntDef(
Margins.NO_FOCUS,
Margins.FOCUS
)
@Retention(AnnotationRetention.SOURCE)
internal annotation class Margins {
companion object {
const val NO_FOCUS = 4
const val FOCUS = 5
}
}
// *********************************************************************************************
private var mImageViewMic: ImageButton? = null
private var mImageViewMenu: ImageButton? = null
protected var mRecyclerView: RecyclerView? = null
private var mMaterialCardView: MaterialCardView? = null
var mSearchEditText: SearchEditText? = null
protected var mViewShadow: View? = null
protected var mViewDivider: View? = null
protected var mViewAnim: View? = null
protected var mOnFocusChangeListener: OnFocusChangeListener? = null
private var mLinearLayout: LinearLayout? = null
private var mImageViewNavigation: ImageButton? = null
private var mImageViewClear: ImageButton? = null
private var mOnQueryTextListener: OnQueryTextListener? = null
private var mOnNavigationClickListener: OnNavigationClickListener? = null
private var mOnMicClickListener: OnMicClickListener? = null
private var mOnMenuClickListener: OnMenuClickListener? = null
private var mOnClearClickListener: OnClearClickListener? = null
// *********************************************************************************************
@NavigationIconSupport
@get:NavigationIconSupport
var navigationIconSupport: Int = 0
set(@NavigationIconSupport navigationIconSupport) {
field = navigationIconSupport
when (navigationIconSupport) {
NavigationIconSupport.NONE
-> {
setNavigationIconImageDrawable(null)
}
NavigationIconSupport.MENU -> {
setNavigationIconImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.ic_menu
)
)
}
NavigationIconSupport.ARROW -> {
setNavigationIconImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.ic_arrow_back
)
)
}
NavigationIconSupport.SEARCH -> {
setNavigationIconImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.ic_search
)
)
}
}
}
@Margins
@get:Margins
protected var margins: Int = 0
set(@Margins margins) {
field = margins
val left: Int
val top: Int
val right: Int
val bottom: Int
val params = mMaterialCardView?.layoutParams as LayoutParams?
when (margins) {
Margins.NO_FOCUS -> {
left =
context.resources.getDimensionPixelSize(R.dimen.search_margins_left_right)
top =
context.resources.getDimensionPixelSize(R.dimen.search_margins_top_bottom)
right =
context.resources.getDimensionPixelSize(R.dimen.search_margins_left_right)
bottom =
context.resources.getDimensionPixelSize(R.dimen.search_margins_top_bottom)
params?.width = ViewGroup.LayoutParams.MATCH_PARENT
params?.height = ViewGroup.LayoutParams.WRAP_CONTENT
params?.setMargins(left, top, right, bottom)
mMaterialCardView?.layoutParams = params
}
Margins.FOCUS -> {
left =
context.resources.getDimensionPixelSize(R.dimen.search_margins_focus)
top =
context.resources.getDimensionPixelSize(R.dimen.search_margins_focus)
right =
context.resources.getDimensionPixelSize(R.dimen.search_margins_focus)
bottom =
context.resources.getDimensionPixelSize(R.dimen.search_margins_focus)
params?.width = ViewGroup.LayoutParams.MATCH_PARENT
params?.height = ViewGroup.LayoutParams.MATCH_PARENT
params?.setMargins(left, top, right, bottom)
mMaterialCardView?.layoutParams = params
}
}
}
// *********************************************************************************************
protected abstract fun addFocus()
protected abstract fun removeFocus()
// *********************************************************************************************
protected fun init() {
mLinearLayout = findViewById(R.id.search_linear_layout)
mImageViewNavigation = findViewById(R.id.search_image_view_navigation)
mImageViewNavigation?.setOnClickListener(this)
mImageViewMic = findViewById(R.id.search_image_view_mic)
mImageViewMic?.setOnClickListener(this)
mImageViewMenu = findViewById(R.id.search_image_view_menu)
mImageViewMenu?.setOnClickListener(this)
mImageViewClear = findViewById(R.id.search_image_view_clear)
mImageViewClear?.visibility = View.GONE
mImageViewClear?.setOnClickListener(this)
mSearchEditText = findViewById(R.id.search_search_edit_text)
mSearchEditText?.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
this@SearchLayout.onTextChanged(s)
}
override fun afterTextChanged(s: Editable?) {
}
})
mSearchEditText?.setOnEditorActionListener { _, _, _ ->
onSubmitQuery()
return@setOnEditorActionListener true // true
}
mSearchEditText?.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
addFocus()
} else {
removeFocus()
}
}
mRecyclerView = findViewById(R.id.search_recycler_view)
mRecyclerView?.visibility = View.GONE
mRecyclerView?.layoutManager = LinearLayoutManager(context)
mRecyclerView?.isNestedScrollingEnabled = false
mRecyclerView?.itemAnimator = DefaultItemAnimator()
mRecyclerView?.overScrollMode = View.OVER_SCROLL_NEVER
mRecyclerView?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
hideKeyboard()
}
}
})
mViewShadow = findViewById(R.id.search_view_shadow)
mViewShadow?.visibility = View.GONE
mViewDivider = findViewById(R.id.search_view_divider)
mViewDivider?.visibility = View.GONE
mViewAnim = findViewById(R.id.search_view_anim)
mViewAnim?.visibility = View.GONE
mMaterialCardView = findViewById(R.id.search_material_card_view)
margins = Margins.NO_FOCUS
isClickable = true
isFocusable = true
isFocusableInTouchMode = true
}
// *********************************************************************************************
fun setNavigationIconVisibility(visibility: Int) {
mImageViewNavigation?.visibility = visibility
}
fun setNavigationIconImageResource(@DrawableRes resId: Int) {
mImageViewNavigation?.setImageResource(resId)
}
fun setNavigationIconImageDrawable(@Nullable drawable: Drawable?) {
mImageViewNavigation?.setImageDrawable(drawable)
}
fun setNavigationIconColorFilter(color: Int) {
mImageViewNavigation?.setColorFilter(color)
}
fun setNavigationIconColorFilter(color: Int, mode: PorterDuff.Mode) {
mImageViewNavigation?.setColorFilter(color, mode)
}
fun setNavigationIconColorFilter(cf: ColorFilter?) {
mImageViewNavigation?.colorFilter = cf
}
fun clearNavigationIconColorFilter() {
mImageViewNavigation?.clearColorFilter()
}
fun setNavigationIconContentDescription(contentDescription: CharSequence) {
mImageViewNavigation?.contentDescription = contentDescription
}
// *********************************************************************************************
fun setMicIconImageResource(@DrawableRes resId: Int) {
mImageViewMic?.setImageResource(resId)
}
fun setMicIconImageDrawable(@Nullable drawable: Drawable?) {
mImageViewMic?.setImageDrawable(drawable)
}
fun setMicIconColorFilter(color: Int) {
mImageViewMic?.setColorFilter(color)
}
fun setMicIconColorFilter(color: Int, mode: PorterDuff.Mode) {
mImageViewMic?.setColorFilter(color, mode)
}
fun setMicIconColorFilter(cf: ColorFilter?) {
mImageViewMic?.colorFilter = cf
}
fun clearMicIconColorFilter() {
mImageViewMic?.clearColorFilter()
}
fun setMicIconContentDescription(contentDescription: CharSequence) {
mImageViewMic?.contentDescription = contentDescription
}
// *********************************************************************************************
fun setMenuIconImageResource(@DrawableRes resId: Int) {
mImageViewMenu?.setImageResource(resId)
}
fun setMenuIconImageDrawable(@Nullable drawable: Drawable?) {
mImageViewMenu?.setImageDrawable(drawable)
}
fun setMenuIconColorFilter(color: Int) {
mImageViewMenu?.setColorFilter(color)
}
fun setMenuIconColorFilter(color: Int, mode: PorterDuff.Mode) {
mImageViewMenu?.setColorFilter(color, mode)
}
fun setMenuIconColorFilter(cf: ColorFilter?) {
mImageViewMenu?.colorFilter = cf
}
fun clearMenuIconColorFilter() {
mImageViewMenu?.clearColorFilter()
}
fun setMenuIconContentDescription(contentDescription: CharSequence) {
mImageViewMenu?.contentDescription = contentDescription
}
// *********************************************************************************************
fun setClearIconImageResource(@DrawableRes resId: Int) {
mImageViewClear?.setImageResource(resId)
}
fun setClearIconImageDrawable(@Nullable drawable: Drawable?) {
mImageViewClear?.setImageDrawable(drawable)
}
fun setClearIconColorFilter(color: Int) {
mImageViewClear?.setColorFilter(color)
}
fun setClearIconColorFilter(color: Int, mode: PorterDuff.Mode) {
mImageViewClear?.setColorFilter(color, mode)
}
fun setClearIconColorFilter(cf: ColorFilter?) {
mImageViewClear?.colorFilter = cf
}
fun clearClearIconColorFilter() {
mImageViewClear?.clearColorFilter()
}
fun setClearIconContentDescription(contentDescription: CharSequence) {
mImageViewClear?.contentDescription = contentDescription
}
// *********************************************************************************************
fun setAdapterLayoutManager(@Nullable layout: RecyclerView.LayoutManager?) {
mRecyclerView?.layoutManager = layout
}
// only when height == match_parent
fun setAdapterHasFixedSize(hasFixedSize: Boolean) {
mRecyclerView?.setHasFixedSize(hasFixedSize)
}
fun addAdapterItemDecoration(@NonNull decor: RecyclerView.ItemDecoration) {
mRecyclerView?.addItemDecoration(decor)
}
fun removeAdapterItemDecoration(@NonNull decor: RecyclerView.ItemDecoration) {
mRecyclerView?.removeItemDecoration(decor)
}
fun setAdapter(@Nullable adapter: RecyclerView.Adapter<*>?) {
mRecyclerView?.adapter = adapter
}
@Nullable
fun getAdapter(): RecyclerView.Adapter<*>? {
return mRecyclerView?.adapter
}
// *********************************************************************************************
/**
* Typeface.NORMAL
* Typeface.BOLD
* Typeface.ITALIC
* Typeface.BOLD_ITALIC
*
* Typeface.DEFAULT
* Typeface.DEFAULT_BOLD
* Typeface.SANS_SERIF
* Typeface.SERIF
* Typeface.MONOSPACE
*
* Typeface.create(Typeface.NORMAL, Typeface.DEFAULT)
*/
fun setTextTypeface(@Nullable tf: Typeface?) {
mSearchEditText?.typeface = tf
}
fun getTextTypeface(): Typeface? {
return mSearchEditText?.typeface
}
fun setTextInputType(type: Int) {
mSearchEditText?.inputType = type
}
fun getTextInputType(): Int? {
return mSearchEditText?.inputType
}
fun setTextImeOptions(imeOptions: Int) {
mSearchEditText?.imeOptions = imeOptions
}
fun getTextImeOptions(): Int? {
return mSearchEditText?.imeOptions
}
fun setTextQuery(query: CharSequence?, submit: Boolean) {
mSearchEditText?.setText(query)
if (query != null) {
mSearchEditText?.setSelection(mSearchEditText?.length()!!)
}
if (submit && !TextUtils.isEmpty(query)) {
onSubmitQuery()
}
}
@Nullable
fun getTextQuery(): CharSequence? {
return mSearchEditText?.text
}
fun setTextHint(hint: CharSequence?) {
mSearchEditText?.hint = hint
}
fun getTextHint(): CharSequence? {
return mSearchEditText?.hint
}
fun setTextColor(@ColorInt color: Int) {
mSearchEditText?.setTextColor(color)
}
fun setTextSize(size: Float) {
mSearchEditText?.textSize = size
}
fun setTextGravity(gravity: Int) {
mSearchEditText?.gravity = gravity
}
fun setTextHint(@StringRes resid: Int) {
mSearchEditText?.setHint(resid)
}
fun setTextHintColor(@ColorInt color: Int) {
mSearchEditText?.setHintTextColor(color)
}
fun setClearFocusOnBackPressed(clearFocusOnBackPressed: Boolean) {
mSearchEditText?.clearFocusOnBackPressed = clearFocusOnBackPressed
}
// *********************************************************************************************
override fun setBackgroundColor(@ColorInt color: Int) {
mMaterialCardView?.setCardBackgroundColor(color)
}
fun setBackgroundColor(@Nullable color: ColorStateList?) {
mMaterialCardView?.setCardBackgroundColor(color)
}
override fun setElevation(elevation: Float) {
mMaterialCardView?.cardElevation = elevation
mMaterialCardView?.maxCardElevation = elevation
}
override fun getElevation(): Float {
return mMaterialCardView?.elevation!!
}
fun setBackgroundRadius(radius: Float) {
mMaterialCardView?.radius = radius
}
fun getBackgroundRadius(): Float {
return mMaterialCardView?.radius!!
}
fun setBackgroundRippleColor(@ColorRes rippleColorResourceId: Int) {
mMaterialCardView?.setRippleColorResource(rippleColorResourceId)
}
fun setBackgroundRippleColorResource(@Nullable rippleColor: ColorStateList?) {
mMaterialCardView?.rippleColor = rippleColor
}
fun setBackgroundStrokeColor(@ColorInt strokeColor: Int) {
mMaterialCardView?.strokeColor = strokeColor
}
fun setBackgroundStrokeColor(strokeColor: ColorStateList) {
mMaterialCardView?.setStrokeColor(strokeColor)
}
fun setBackgroundStrokeWidth(@Dimension strokeWidth: Int) {
mMaterialCardView?.strokeWidth = strokeWidth
}
@Dimension
fun getBackgroundStrokeWidth(): Int {
return mMaterialCardView?.strokeWidth!!
}
// *********************************************************************************************
fun setDividerColor(@ColorInt color: Int) {
mViewDivider?.setBackgroundColor(color)
}
fun setShadowColor(@ColorInt color: Int) {
mViewShadow?.setBackgroundColor(color)
}
// *********************************************************************************************
fun setOnFocusChangeListener(listener: OnFocusChangeListener) {
mOnFocusChangeListener = listener
}
fun setOnQueryTextListener(listener: OnQueryTextListener) {
mOnQueryTextListener = listener
}
fun setOnNavigationClickListener(listener: OnNavigationClickListener) {
mOnNavigationClickListener = listener
}
fun setOnMicClickListener(listener: OnMicClickListener) {
mOnMicClickListener = listener
}
fun setOnMenuClickListener(listener: OnMenuClickListener) {
mOnMenuClickListener = listener
}
fun setOnClearClickListener(listener: OnClearClickListener) {
mOnClearClickListener = listener
}
// *********************************************************************************************
fun showKeyboard() {
if (!isInEditMode) {
val inputMethodManager =
context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(
mSearchEditText,
InputMethodManager.RESULT_UNCHANGED_SHOWN
)
}
}
fun hideKeyboard() {
if (!isInEditMode) {
val inputMethodManager =
context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(
windowToken,
InputMethodManager.RESULT_UNCHANGED_SHOWN
)
}
}
// *********************************************************************************************
protected fun setLayoutHeight(height: Int) {
val params = mLinearLayout?.layoutParams
params?.height = height
params?.width = ViewGroup.LayoutParams.MATCH_PARENT
mLinearLayout?.layoutParams = params
}
// *********************************************************************************************
private fun onTextChanged(newText: CharSequence) {
if (!TextUtils.isEmpty(newText)) {
mImageViewMic?.visibility = View.GONE
mImageViewClear?.visibility = View.VISIBLE
} else {
mImageViewClear?.visibility = View.GONE
if (mSearchEditText?.hasFocus()!!) {
mImageViewMic?.visibility = View.VISIBLE
} else {
mImageViewMic?.visibility = View.GONE
}
}
if (mOnQueryTextListener != null) {
mOnQueryTextListener?.onQueryTextChange(newText)
}
}
private fun onSubmitQuery() {
val query = mSearchEditText?.text
if (query != null && TextUtils.getTrimmedLength(query) > 0) {
if (mOnQueryTextListener == null || !mOnQueryTextListener!!.onQueryTextSubmit(query.toString())) {
mSearchEditText?.text = query
}
}
}
// *********************************************************************************************
override fun onSaveInstanceState(): Parcelable? {
val superState = super.onSaveInstanceState()
val ss = SearchViewSavedState(superState!!)
if (mSearchEditText?.text!!.isNotEmpty()) {
ss.query = mSearchEditText?.text
}
ss.hasFocus = mSearchEditText?.hasFocus()!!
return ss
}
override fun onRestoreInstanceState(state: Parcelable?) {
if (state !is SearchViewSavedState) {
super.onRestoreInstanceState(state)
return
}
super.onRestoreInstanceState(state.superState)
if (state.hasFocus) {
mSearchEditText?.requestFocus()
}
if (state.query != null) {
setTextQuery(state.query, false)
}
requestLayout()
}
override fun requestFocus(direction: Int, previouslyFocusedRect: Rect?): Boolean {
return if (!isFocusable) {
false
} else {
mSearchEditText?.requestFocus(direction, previouslyFocusedRect)!!
}
}
override fun clearFocus() {
super.clearFocus()
mSearchEditText?.clearFocus()
}
override fun onClick(view: View?) {
if (view === mImageViewNavigation) {
if (mOnNavigationClickListener != null) {
mOnNavigationClickListener?.onNavigationClick(mSearchEditText?.hasFocus()!!)
}
} else if (view === mImageViewMic) {
if (mOnMicClickListener != null) {
mOnMicClickListener?.onMicClick()
}
} else if (view === mImageViewMenu) {
if (mOnMenuClickListener != null) {
mOnMenuClickListener?.onMenuClick()
}
} else if (view === mImageViewClear) {
if (mSearchEditText?.text!!.isNotEmpty()) {
mSearchEditText?.text!!.clear()
}
if (mOnClearClickListener != null) {
mOnClearClickListener?.onClearClick()
}
}
}
// *********************************************************************************************
interface OnFocusChangeListener {
fun onFocusChange(hasFocus: Boolean)
}
interface OnQueryTextListener {
fun onQueryTextChange(newText: CharSequence): Boolean
fun onQueryTextSubmit(query: CharSequence): Boolean
}
interface OnNavigationClickListener {
fun onNavigationClick(hasFocus: Boolean)
}
interface OnMicClickListener {
fun onMicClick()
}
interface OnMenuClickListener {
fun onMenuClick()
}
interface OnClearClickListener {
fun onClearClick()
}
}

View File

@@ -1,21 +0,0 @@
/*https://github.com/lapism/search*/
package org.koitharu.kotatsu.base.ui.widgets.search.internal
import android.os.Parcel
import android.os.Parcelable
import android.text.TextUtils
import android.view.View
internal class SearchViewSavedState(superState: Parcelable) : View.BaseSavedState(superState) {
var query: CharSequence? = null
var hasFocus: Boolean = false
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
TextUtils.writeToParcel(query, out, flags)
out.writeInt(if (hasFocus) 1 else 0)
}
}

View File

@@ -1,37 +0,0 @@
package org.koitharu.kotatsu.base.ui.widgets.search.util
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.speech.RecognizerIntent
object SearchUtils {
const val SPEECH_REQUEST_CODE = 300
@JvmStatic
fun setVoiceSearch(activity: Activity, text: String) {
val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
)
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, text)
intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1)
activity.startActivityForResult(
intent,
SPEECH_REQUEST_CODE
)
}
@JvmStatic
fun isVoiceSearchAvailable(context: Context): Boolean {
val pm = context.packageManager
val activities =
pm.queryIntentActivities(Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0)
return activities.size != 0
}
}

View File

@@ -28,6 +28,8 @@ class FavouritesListViewModel(
when {
list.isEmpty() -> listOf(
EmptyState(
R.drawable.ic_heart_outline,
R.string.text_empty_holder_primary,
if (categoryId == 0L) {
R.string.you_have_not_favourites_yet
} else {

View File

@@ -44,7 +44,7 @@ class HistoryListViewModel(
createListModeFlow()
) { list, grouped, mode ->
when {
list.isEmpty() -> listOf(EmptyState(R.string.text_history_holder))
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_history, R.string.text_history_holder_primary, R.string.text_history_holder_secondary))
else -> mapList(list, grouped, mode)
}
}.onFirst {

View File

@@ -1,14 +1,23 @@
package org.koitharu.kotatsu.list.ui.adapter
import android.widget.TextView
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate
import org.koitharu.kotatsu.R
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.databinding.ItemEmptyStateBinding
import org.koitharu.kotatsu.list.ui.model.EmptyState
import org.koitharu.kotatsu.list.ui.model.ListModel
fun emptyStateListAD() = adapterDelegate<EmptyState, ListModel>(R.layout.item_empty_state) {
fun emptyStateListAD() = adapterDelegateViewBinding<EmptyState, ListModel, ItemEmptyStateBinding>(
{ inflater, parent -> ItemEmptyStateBinding.inflate(inflater, parent, false) }
) {
bind {
(itemView as TextView).setText(item.text)
with(binding.icon) {
setImageResource(item.icon)
}
with(binding.textPrimary) {
setText(item.textPrimary)
}
with(binding.textSecondary) {
setText(item.textSecondary)
}
}
}

View File

@@ -1,7 +1,10 @@
package org.koitharu.kotatsu.list.ui.model
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
data class EmptyState(
@StringRes val text: Int
@DrawableRes val icon: Int,
@StringRes val textPrimary: Int,
@StringRes val textSecondary: Int
) : ListModel

View File

@@ -45,7 +45,7 @@ class LocalListViewModel(
when {
error != null -> listOf(error.toErrorState(canRetry = true))
list == null -> listOf(LoadingState)
list.isEmpty() -> listOf(EmptyState(R.string.text_local_holder))
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_storage, R.string.text_local_holder_primary, R.string.text_local_holder_secondary))
else -> list.toUi(mode)
}
}.asLiveDataDistinct(

View File

@@ -186,11 +186,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
}
override fun onWindowInsetsChanged(insets: Insets) {
binding.toolbar.updatePadding(
top = insets.top,
left = insets.left,
right = insets.right
)
binding.toolbarCard.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top + 16
leftMargin = insets.left + 32
rightMargin = insets.right + 32
}
binding.fab.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = insets.bottom + topMargin
leftMargin = insets.left + topMargin

View File

@@ -37,7 +37,7 @@ class RemoteListViewModel(
when {
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
list == null -> listOf(LoadingState)
list.isEmpty() -> listOf(EmptyState(R.string.nothing_found))
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_search, R.string.nothing_found, R.string._empty))
else -> {
val result = ArrayList<ListModel>(list.size + 1)
list.toUi(result, mode)

View File

@@ -34,7 +34,7 @@ class SearchViewModel(
when {
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
list == null -> listOf(LoadingState)
list.isEmpty() -> listOf(EmptyState(R.string.nothing_found))
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_search, R.string.nothing_found, R.string.text_search_holder_secondary))
else -> {
val result = ArrayList<ListModel>(list.size + 1)
list.toUi(result, mode)

View File

@@ -35,7 +35,7 @@ class GlobalSearchViewModel(
when {
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
list == null -> listOf(LoadingState)
list.isEmpty() -> listOf(EmptyState(R.string.nothing_found))
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_search, R.string.nothing_found, R.string.text_search_holder_secondary))
else -> {
val result = ArrayList<ListModel>(list.size + 1)
list.toUi(result, mode)

View File

@@ -39,7 +39,7 @@ class FeedViewModel(
hasNextPage
) { list, isHasNextPage ->
when {
list.isEmpty() -> listOf(EmptyState(R.string.text_feed_holder))
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_feed, R.string.text_empty_holder_primary, R.string.text_feed_holder))
isHasNextPage -> list + LoadingFooter
else -> list
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorSecondary" android:state_checked="true" />
<item android:color="?attr/colorControlNormal" />
</selector>

View File

@@ -11,7 +11,7 @@
style="@style/Widget.Kotatsu.AppBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:elevation="0dp"
android:elevation="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

View File

@@ -11,7 +11,7 @@
style="@style/Widget.Kotatsu.AppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
android:elevation="4dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"

View File

@@ -19,12 +19,29 @@
android:layout_height="wrap_content"
app:elevation="0dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
style="@style/Widget.Kotatsu.Toolbar"
<com.google.android.material.card.MaterialCardView
android:id="@+id/toolbar_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways" />
android:layout_height="50dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
style="@style/Widget.Kotatsu.Toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentInsetStartWithNavigation="0dp"
app:layout_scrollFlags="scroll|enterAlways"
app:titleTextAppearance="@style/TextAppearance.Kotatsu.PersistentToolbarTitle"
app:titleTextColor="?android:colorControlNormal"
tools:title="@string/app_name" />
</com.google.android.material.card.MaterialCardView>
</com.google.android.material.appbar.AppBarLayout>
@@ -58,6 +75,9 @@
android:layout_height="match_parent"
android:layout_gravity="start"
app:insetForeground="@android:color/transparent"
app:itemHorizontalPadding="16dp"
app:itemIconPadding="24dp"
app:itemIconTint="@color/navigation_item_color_tint"
app:menu="@menu/nav_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>

View File

@@ -10,7 +10,7 @@
style="@style/Widget.Kotatsu.AppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
android:elevation="4dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"

View File

@@ -10,7 +10,7 @@
style="@style/Widget.Kotatsu.AppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
android:elevation="4dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"

View File

@@ -11,7 +11,7 @@
style="@style/Widget.Kotatsu.AppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
android:elevation="4dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"

View File

@@ -10,7 +10,7 @@
style="@style/Widget.Kotatsu.AppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
android:elevation="4dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"

View File

@@ -1,11 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:padding="20dp"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorSecondary"
tools:text="@tools:sample/lorem[3]" />
android:orientation="vertical"
android:padding="16dp">
<ImageView
android:id="@+id/icon"
android:layout_width="98dp"
android:layout_height="98dp"
android:layout_marginBottom="16dp"
tools:src="@drawable/ic_alert_outline" />
<TextView
android:id="@+id/textPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="4dp"
android:textAppearance="?android:textAppearanceLarge"
tools:text="@tools:sample/lorem[3]" />
<TextView
android:id="@+id/textSecondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="4dp"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorSecondary"
tools:text="@tools:sample/lorem[3]" />
</LinearLayout>

View File

@@ -6,19 +6,22 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_cover"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="4dp"
app:cardElevation="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
<ImageView
android:id="@+id/imageView_cover"

View File

@@ -1,113 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true">
<View
android:id="@+id/search_view_shadow"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/search_material_card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/search_view_anim"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/search_linear_layout"
android:layout_width="match_parent"
android:layout_height="@dimen/search_layout_height"
android:layoutDirection="locale"
android:orientation="horizontal">
<ImageButton
android:id="@+id/search_image_view_navigation"
android:layout_width="@dimen/search_icon_56"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@null"
android:scaleType="centerInside" />
<org.koitharu.kotatsu.base.ui.widgets.search.internal.SearchEditText
android:id="@+id/search_search_edit_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|start"
android:layout_weight="1"
android:background="@null"
android:ellipsize="end"
android:gravity="start|center_vertical"
android:imeOptions="actionSearch|flagNoExtractUi"
android:inputType="text|textNoSuggestions"
android:layoutDirection="locale"
android:maxLines="1"
android:privateImeOptions="nm"
android:singleLine="true"
android:textAlignment="viewStart"
android:textColor="?android:attr/textColorPrimary"
android:textColorHint="?android:attr/textColorSecondary"
android:textDirection="locale"
android:textSize="@dimen/search_sp_16"
android:windowSoftInputMode="stateAlwaysHidden|adjustPan|adjustNothing" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="match_parent">
<ImageButton
android:id="@+id/search_image_view_mic"
android:layout_width="@dimen/search_icon_48"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@null"
android:scaleType="centerInside" />
<ImageButton
android:id="@+id/search_image_view_clear"
android:layout_width="@dimen/search_icon_48"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@null"
android:scaleType="centerInside" />
<ImageButton
android:id="@+id/search_image_view_menu"
android:layout_width="@dimen/search_icon_48"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@null"
android:scaleType="centerInside" />
</FrameLayout>
</LinearLayout>
<View
android:id="@+id/search_view_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/search_divider"
android:background="?android:attr/listDivider" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/search_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</merge>

View File

@@ -8,13 +8,28 @@
android:fitsSystemWindows="true"
android:orientation="vertical">
<ImageView
android:layout_width="@dimen/nav_header_logo_size"
android:layout_height="@dimen/nav_header_logo_size"
android:layout_marginStart="@dimen/nav_item_horizontal_padding"
android:layout_marginTop="@dimen/margin_normal"
android:layout_marginBottom="@dimen/margin_normal"
app:srcCompat="@drawable/ic_totoro" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:layout_width="@dimen/nav_header_logo_size"
android:layout_height="@dimen/nav_header_logo_size"
android:layout_marginStart="@dimen/margin_normal"
android:layout_marginTop="24dp"
android:layout_marginBottom="24dp"
app:srcCompat="@drawable/ic_totoro" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/nav_item_horizontal_padding"
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.AppCompat.Title" />
</LinearLayout>
<View
android:id="@+id/divider"

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="color_primary">#1976D2</color>
<color name="color_primary_variant">#1565C0</color>
<color name="color_primary">#4098EF</color>
<color name="color_primary_variant">#2C7CD6</color>
<color name="color_on_secondary">@android:color/black</color>
<color name="color_control_light">#2EFFFFFF</color> <!-- 18% white -->

View File

@@ -23,7 +23,7 @@
<string name="history_is_empty">История пуста</string>
<string name="read">Читать</string>
<string name="add_bookmark">Добавить закладку</string>
<string name="you_have_not_favourites_yet">Добавьте интересующую Вас мангу в избренное, чтобы не потерять её</string>
<string name="you_have_not_favourites_yet">Добавьте интересующую Вас мангу в избранное, чтобы не потерять её</string>
<string name="add_to_favourites">В избранное</string>
<string name="add_new_category">Создать категорию</string>
<string name="add">Добавить</string>
@@ -116,9 +116,13 @@
<string name="rename">Переименовать</string>
<string name="category_delete_confirm">Вы уверены, что хотите удалить категорию \"%s\"? \nВся манга из данной категории будет утеряна.</string>
<string name="remove_category">Удалить категорию</string>
<string name="text_empty_holder_primary">Как-то здесь пусто…</string>
<string name="text_search_holder_secondary">Попробуйте переформулировать запрос.</string>
<string name="text_categories_holder">Категории помогают упорядочивать избранную мангу. Нажмите «+», чтобы создать категорию</string>
<string name="text_history_holder">Здесь будет оборажаться манга, которую Вы читаете. Вы можете найти, что почитать, в боковом меню</string>
<string name="text_local_holder">У Вас пока нет сохранённой манги. Вы можете сохранить мангу из онлайн каталога или импортировать из файла</string>
<string name="text_history_holder_primary">Здесь будет отображаться манга, которую Вы читаете</string>
<string name="text_history_holder_secondary">Вы можете найти, что почитать, в боковом меню.</string>
<string name="text_local_holder_primary">У Вас пока нет сохранённой манги</string>
<string name="text_local_holder_secondary">Вы можете сохранить мангу из онлайн каталога или импортировать из файла.</string>
<string name="manga_shelf">Полка с мангой</string>
<string name="recent_manga">Недавняя манга</string>
<string name="pages_animation">Анимация листания</string>

View File

@@ -13,29 +13,4 @@
<attr name="android:orientation" />
</declare-styleable>
<!--SearchView attrs-->
<declare-styleable name="MaterialSearchView">
<attr name="search_navigationIconSupport" format="enum">
<enum name="none" value="0" />
<enum name="menu" value="1" />
<enum name="arrow" value="2" />
<enum name="search" value="3" />
</attr>
<attr name="search_navigationIcon" format="reference" />
<attr name="search_clearIcon" format="reference" />
<attr name="search_micIcon" format="reference" />
<attr name="search_menuIcon" format="reference" />
<attr name="search_textHint" format="string" />
<attr name="search_strokeColor" format="reference" />
<attr name="search_strokeWidth" format="reference" />
<attr name="search_dividerColor" format="reference" />
<attr name="search_shadowColor" format="reference" />
<attr name="search_transitionDuration" format="integer" />
<attr name="search_radius" format="integer" />
<attr name="android:elevation" />
<attr name="android:imeOptions" />
<attr name="android:inputType" />
</declare-styleable>
</resources>

View File

@@ -1,5 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name" translatable="false">Kotatsu</string>
<string name="_empty" translatable="false"/>
<string name="close_menu">Close menu</string>
<string name="open_menu">Open menu</string>
<string name="local_storage">Local storage</string>
@@ -117,9 +118,13 @@
<string name="rename">Rename</string>
<string name="category_delete_confirm">Do you really want to remove category \"%s\" from your favourites? \nAll containing manga will be lost.</string>
<string name="remove_category">Remove category</string>
<string name="text_empty_holder_primary">It\'s kind of empty here…</string>
<string name="text_categories_holder">You can use categories to organize your favourite manga. Press «+» to create a category</string>
<string name="text_history_holder">Manga you are reading will be displayed here. You can find what to read in side menu</string>
<string name="text_local_holder">You have not any saved manga yet. You can save it from online sources or import from file</string>
<string name="text_search_holder_secondary">Try to reformulate the query.</string>
<string name="text_history_holder_primary">Manga you are reading will be displayed here</string>
<string name="text_history_holder_secondary">You can find what to read in side menu.</string>
<string name="text_local_holder_primary">You have not any saved manga yet</string>
<string name="text_local_holder_secondary">You can save it from online sources or import from file.</string>
<string name="manga_shelf">Manga shelf</string>
<string name="recent_manga">Recent manga</string>
<string name="pages_animation">Pages animation</string>

View File

@@ -29,6 +29,12 @@
<item name="itemHorizontalPadding">@dimen/nav_item_horizontal_padding</item>
</style>
<style name="Widget.Kotatsu.SearchView" parent="@style/Widget.AppCompat.SearchView">
<item name="iconifiedByDefault">false</item>
<item name="searchIcon">@null</item>
<item name="queryBackground">@null</item>
</style>
<style name="Widget.Kotatsu.Chip" parent="Widget.MaterialComponents.Chip.Action">
<item name="chipStrokeWidth">1dp</item>
<item name="chipStrokeColor">?attr/colorAccent</item>
@@ -63,6 +69,10 @@
<item name="android:textSize">20sp</item>
</style>
<style name="TextAppearance.Kotatsu.PersistentToolbarTitle" parent="@style/TextAppearance.AppCompat">
<item name="android:textSize">16sp</item>
</style>
<style name="TextAppearance.Kotatsu.Tab" parent="@style/TextAppearance.Design.Tab">
<item name="textAllCaps">false</item>
<item name="android:textAllCaps">false</item>

View File

@@ -14,9 +14,7 @@
<!-- Window decor -->
<item name="android:windowLightStatusBar" tools:targetApi="m">@bool/use_light_status</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">
@bool/use_light_navigation
</item>
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">@bool/use_light_navigation</item>
<item name="android:navigationBarColor">@color/nav_bar_scrim</item>
<item name="popupTheme">@style/ThemeOverlay.Kotatsu</item>
@@ -24,6 +22,7 @@
<item name="toolbarStyle">@style/Widget.Kotatsu.Toolbar</item>
<item name="tabStyle">@style/Widget.Kotatsu.Tabs</item>
<item name="navigationViewStyle">@style/Widget.Kotatsu.NavigationView</item>
<item name="searchViewStyle">@style/Widget.Kotatsu.SearchView</item>
<!-- Text appearances -->
<item name="textAppearanceBody2">@style/TextAppearance.Kotatsu.Body2</item>