@@ -11,13 +11,6 @@
|
|||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<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
|
<application
|
||||||
android:name="org.koitharu.kotatsu.KotatsuApp"
|
android:name="org.koitharu.kotatsu.KotatsuApp"
|
||||||
|
|||||||
@@ -57,12 +57,15 @@ abstract class BaseActivity<B : ViewBinding> : AppCompatActivity(), OnApplyWindo
|
|||||||
this.binding = binding
|
this.binding = binding
|
||||||
super.setContentView(binding.root)
|
super.setContentView(binding.root)
|
||||||
(binding.root.findViewById<View>(R.id.toolbar) as? Toolbar)?.let(this::setSupportActionBar)
|
(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 toolbarParams = (binding.root.findViewById<View>(R.id.toolbar) as? Toolbar)?.layoutParams as? AppBarLayout.LayoutParams
|
||||||
|
val persistentToolbarParams = (binding.root.findViewById<View>(R.id.toolbar_card))?.layoutParams as? AppBarLayout.LayoutParams
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root, this)
|
ViewCompat.setOnApplyWindowInsetsListener(binding.root, this)
|
||||||
if (get<AppSettings>().isToolbarHideWhenScrolling) {
|
if (get<AppSettings>().isToolbarHideWhenScrolling) {
|
||||||
params?.scrollFlags = SCROLL_FLAG_SCROLL or SCROLL_FLAG_ENTER_ALWAYS
|
toolbarParams?.scrollFlags = SCROLL_FLAG_SCROLL or SCROLL_FLAG_ENTER_ALWAYS
|
||||||
|
persistentToolbarParams?.scrollFlags = SCROLL_FLAG_SCROLL or SCROLL_FLAG_ENTER_ALWAYS
|
||||||
} else {
|
} else {
|
||||||
params?.scrollFlags = SCROLL_FLAG_NO_SCROLL
|
toolbarParams?.scrollFlags = SCROLL_FLAG_NO_SCROLL
|
||||||
|
persistentToolbarParams?.scrollFlags = SCROLL_FLAG_NO_SCROLL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -28,6 +28,8 @@ class FavouritesListViewModel(
|
|||||||
when {
|
when {
|
||||||
list.isEmpty() -> listOf(
|
list.isEmpty() -> listOf(
|
||||||
EmptyState(
|
EmptyState(
|
||||||
|
R.drawable.ic_heart_outline,
|
||||||
|
R.string.text_empty_holder_primary,
|
||||||
if (categoryId == 0L) {
|
if (categoryId == 0L) {
|
||||||
R.string.you_have_not_favourites_yet
|
R.string.you_have_not_favourites_yet
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class HistoryListViewModel(
|
|||||||
createListModeFlow()
|
createListModeFlow()
|
||||||
) { list, grouped, mode ->
|
) { list, grouped, mode ->
|
||||||
when {
|
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)
|
else -> mapList(list, grouped, mode)
|
||||||
}
|
}
|
||||||
}.onFirst {
|
}.onFirst {
|
||||||
|
|||||||
@@ -1,14 +1,23 @@
|
|||||||
package org.koitharu.kotatsu.list.ui.adapter
|
package org.koitharu.kotatsu.list.ui.adapter
|
||||||
|
|
||||||
import android.widget.TextView
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate
|
import org.koitharu.kotatsu.databinding.ItemEmptyStateBinding
|
||||||
import org.koitharu.kotatsu.R
|
|
||||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
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 {
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
package org.koitharu.kotatsu.list.ui.model
|
package org.koitharu.kotatsu.list.ui.model
|
||||||
|
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
|
||||||
data class EmptyState(
|
data class EmptyState(
|
||||||
@StringRes val text: Int
|
@DrawableRes val icon: Int,
|
||||||
|
@StringRes val textPrimary: Int,
|
||||||
|
@StringRes val textSecondary: Int
|
||||||
) : ListModel
|
) : ListModel
|
||||||
@@ -45,7 +45,7 @@ class LocalListViewModel(
|
|||||||
when {
|
when {
|
||||||
error != null -> listOf(error.toErrorState(canRetry = true))
|
error != null -> listOf(error.toErrorState(canRetry = true))
|
||||||
list == null -> listOf(LoadingState)
|
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)
|
else -> list.toUi(mode)
|
||||||
}
|
}
|
||||||
}.asLiveDataDistinct(
|
}.asLiveDataDistinct(
|
||||||
|
|||||||
@@ -44,13 +44,12 @@ import org.koitharu.kotatsu.settings.SettingsActivity
|
|||||||
import org.koitharu.kotatsu.settings.onboard.OnboardDialogFragment
|
import org.koitharu.kotatsu.settings.onboard.OnboardDialogFragment
|
||||||
import org.koitharu.kotatsu.tracker.ui.FeedFragment
|
import org.koitharu.kotatsu.tracker.ui.FeedFragment
|
||||||
import org.koitharu.kotatsu.tracker.work.TrackWorker
|
import org.koitharu.kotatsu.tracker.work.TrackWorker
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
import org.koitharu.kotatsu.utils.ext.*
|
||||||
import org.koitharu.kotatsu.utils.ext.navigationItemBackground
|
|
||||||
import org.koitharu.kotatsu.utils.ext.resolveDp
|
|
||||||
|
|
||||||
class MainActivity : BaseActivity<ActivityMainBinding>(),
|
class MainActivity : BaseActivity<ActivityMainBinding>(),
|
||||||
NavigationView.OnNavigationItemSelectedListener,
|
NavigationView.OnNavigationItemSelectedListener,
|
||||||
View.OnClickListener, SearchSuggestionListener, MenuItem.OnActionExpandListener {
|
View.OnClickListener, View.OnFocusChangeListener, SearchSuggestionListener,
|
||||||
|
MenuItem.OnActionExpandListener {
|
||||||
|
|
||||||
private val viewModel by viewModel<MainViewModel>(mode = LazyThreadSafetyMode.NONE)
|
private val viewModel by viewModel<MainViewModel>(mode = LazyThreadSafetyMode.NONE)
|
||||||
private val searchSuggestionViewModel by viewModel<SearchSuggestionViewModel>(
|
private val searchSuggestionViewModel by viewModel<SearchSuggestionViewModel>(
|
||||||
@@ -66,15 +65,20 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
|
|||||||
setContentView(ActivityMainBinding.inflate(layoutInflater))
|
setContentView(ActivityMainBinding.inflate(layoutInflater))
|
||||||
navHeaderBinding = NavigationHeaderBinding.inflate(layoutInflater)
|
navHeaderBinding = NavigationHeaderBinding.inflate(layoutInflater)
|
||||||
drawerToggle = ActionBarDrawerToggle(
|
drawerToggle = ActionBarDrawerToggle(
|
||||||
this,
|
this,
|
||||||
binding.drawer,
|
binding.drawer,
|
||||||
binding.toolbar,
|
binding.toolbar,
|
||||||
R.string.open_menu,
|
R.string.open_menu,
|
||||||
R.string.close_menu
|
R.string.close_menu
|
||||||
)
|
)
|
||||||
binding.drawer.addDrawerListener(drawerToggle)
|
binding.drawer.addDrawerListener(drawerToggle)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
|
binding.searchView.apply {
|
||||||
|
setOnQueryTextFocusChangeListener(this@MainActivity)
|
||||||
|
searchUi = SearchUI.from(this, this@MainActivity)
|
||||||
|
}
|
||||||
|
|
||||||
binding.navigationView.apply {
|
binding.navigationView.apply {
|
||||||
val menuView = findViewById<RecyclerView>(com.google.android.material.R.id.design_navigation_view)
|
val menuView = findViewById<RecyclerView>(com.google.android.material.R.id.design_navigation_view)
|
||||||
navHeaderBinding.root.setOnApplyWindowInsetsListener { v, insets ->
|
navHeaderBinding.root.setOnApplyWindowInsetsListener { v, insets ->
|
||||||
@@ -121,23 +125,19 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
if (binding.drawer.isDrawerOpen(binding.navigationView)) {
|
val fragment = supportFragmentManager.findFragmentByTag(TAG_SEARCH)
|
||||||
binding.drawer.closeDrawer(binding.navigationView)
|
binding.searchView.setQuery(resources.getString(R.string._empty), false)
|
||||||
} else {
|
when {
|
||||||
super.onBackPressed()
|
binding.drawer.isDrawerOpen(binding.navigationView) -> binding.drawer.closeDrawer(
|
||||||
|
binding.navigationView)
|
||||||
|
fragment != null -> supportFragmentManager.commit {
|
||||||
|
remove(fragment)
|
||||||
|
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
|
||||||
|
}
|
||||||
|
else -> super.onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
||||||
menuInflater.inflate(R.menu.opt_main, menu)
|
|
||||||
searchUi = menu.findItem(R.id.action_search)?.let { menuItem ->
|
|
||||||
onMenuItemActionCollapse(menuItem)
|
|
||||||
menuItem.setOnActionExpandListener(this)
|
|
||||||
SearchUI.from(menuItem, this)
|
|
||||||
}
|
|
||||||
return super.onCreateOptionsMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
return drawerToggle.onOptionsItemSelected(item) || when (item.itemId) {
|
return drawerToggle.onOptionsItemSelected(item) || when (item.itemId) {
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
@@ -186,11 +186,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onWindowInsetsChanged(insets: Insets) {
|
override fun onWindowInsetsChanged(insets: Insets) {
|
||||||
binding.toolbar.updatePadding(
|
binding.toolbarCard.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
top = insets.top,
|
topMargin = insets.top + 16
|
||||||
left = insets.left,
|
leftMargin = insets.left + 32
|
||||||
right = insets.right
|
rightMargin = insets.right + 32
|
||||||
)
|
}
|
||||||
binding.fab.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
binding.fab.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
bottomMargin = insets.bottom + topMargin
|
bottomMargin = insets.bottom + topMargin
|
||||||
leftMargin = insets.left + topMargin
|
leftMargin = insets.left + topMargin
|
||||||
@@ -198,6 +198,18 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onFocusChange(v: View?, hasFocus: Boolean) {
|
||||||
|
val fragment = supportFragmentManager.findFragmentByTag(TAG_SEARCH)
|
||||||
|
if (v?.id == R.id.searchView && hasFocus) {
|
||||||
|
if (fragment == null) {
|
||||||
|
supportFragmentManager.commit {
|
||||||
|
add(R.id.container, SearchSuggestionFragment.newInstance(), TAG_SEARCH)
|
||||||
|
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onMangaClick(manga: Manga) {
|
override fun onMangaClick(manga: Manga) {
|
||||||
startActivity(DetailsActivity.newIntent(this, manga))
|
startActivity(DetailsActivity.newIntent(this, manga))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class RemoteListViewModel(
|
|||||||
when {
|
when {
|
||||||
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
|
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
|
||||||
list == null -> listOf(LoadingState)
|
list == null -> listOf(LoadingState)
|
||||||
list.isEmpty() -> listOf(EmptyState(R.string.nothing_found))
|
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_book_cross, R.string.nothing_found, R.string._empty))
|
||||||
else -> {
|
else -> {
|
||||||
val result = ArrayList<ListModel>(list.size + 1)
|
val result = ArrayList<ListModel>(list.size + 1)
|
||||||
list.toUi(result, mode)
|
list.toUi(result, mode)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class SearchViewModel(
|
|||||||
when {
|
when {
|
||||||
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
|
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
|
||||||
list == null -> listOf(LoadingState)
|
list == null -> listOf(LoadingState)
|
||||||
list.isEmpty() -> listOf(EmptyState(R.string.nothing_found))
|
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_book_search, R.string.nothing_found, R.string.text_search_holder_secondary))
|
||||||
else -> {
|
else -> {
|
||||||
val result = ArrayList<ListModel>(list.size + 1)
|
val result = ArrayList<ListModel>(list.size + 1)
|
||||||
list.toUi(result, mode)
|
list.toUi(result, mode)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class GlobalSearchViewModel(
|
|||||||
when {
|
when {
|
||||||
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
|
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
|
||||||
list == null -> listOf(LoadingState)
|
list == null -> listOf(LoadingState)
|
||||||
list.isEmpty() -> listOf(EmptyState(R.string.nothing_found))
|
list.isEmpty() -> listOf(EmptyState(R.drawable.ic_book_search, R.string.nothing_found, R.string.text_search_holder_secondary))
|
||||||
else -> {
|
else -> {
|
||||||
val result = ArrayList<ListModel>(list.size + 1)
|
val result = ArrayList<ListModel>(list.size + 1)
|
||||||
list.toUi(result, mode)
|
list.toUi(result, mode)
|
||||||
|
|||||||
@@ -42,10 +42,8 @@ class SearchUI(
|
|||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun from(
|
fun from(
|
||||||
menuItem: MenuItem,
|
searchView: SearchView,
|
||||||
listener: SearchSuggestionListener,
|
listener: SearchSuggestionListener,
|
||||||
): SearchUI? = (menuItem.actionView as? SearchView)?.let {
|
): SearchUI = SearchUI(searchView, listener)
|
||||||
SearchUI(it, listener)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@ class FeedViewModel(
|
|||||||
hasNextPage
|
hasNextPage
|
||||||
) { list, isHasNextPage ->
|
) { list, isHasNextPage ->
|
||||||
when {
|
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
|
isHasNextPage -> list + LoadingFooter
|
||||||
else -> list
|
else -> list
|
||||||
}
|
}
|
||||||
|
|||||||
5
app/src/main/res/color/navigation_item_color_tint.xml
Normal file
5
app/src/main/res/color/navigation_item_color_tint.xml
Normal 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>
|
||||||
10
app/src/main/res/drawable/ic_book_cross.xml
Normal file
10
app/src/main/res/drawable/ic_book_cross.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M13.09 20C13.21 20.72 13.46 21.39 13.81 22H6C4.89 22 4 21.11 4 20V4C4 2.9 4.89 2 6 2H18C19.11 2 20 2.9 20 4V13.09C19.67 13.04 19.34 13 19 13C18.66 13 18.33 13.04 18 13.09V4H13V12L10.5 9.75L8 12V4H6V20H13.09M22.54 16.88L21.12 15.47L19 17.59L16.88 15.47L15.47 16.88L17.59 19L15.47 21.12L16.88 22.54L19 20.41L21.12 22.54L22.54 21.12L20.41 19L22.54 16.88Z"/>
|
||||||
|
</vector>
|
||||||
10
app/src/main/res/drawable/ic_book_search.xml
Normal file
10
app/src/main/res/drawable/ic_book_search.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M15.5,12C18,12 20,14 20,16.5C20,17.38 19.75,18.21 19.31,18.9L22.39,22L21,23.39L17.88,20.32C17.19,20.75 16.37,21 15.5,21C13,21 11,19 11,16.5C11,14 13,12 15.5,12M15.5,14A2.5,2.5 0 0,0 13,16.5A2.5,2.5 0 0,0 15.5,19A2.5,2.5 0 0,0 18,16.5A2.5,2.5 0 0,0 15.5,14M13,4V12L10.5,9.75L8,12V4H6V20H10C10.54,20.81 11.23,21.5 12.03,22H6A2,2 0 0,1 4,20V4A2,2 0 0,1 6,2H18A2,2 0 0,1 20,4V11.81C19.42,11.26 18.75,10.81 18,10.5V4H13Z"/>
|
||||||
|
</vector>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
style="@style/Widget.Kotatsu.AppBar"
|
style="@style/Widget.Kotatsu.AppBar"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:elevation="0dp"
|
android:elevation="4dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
style="@style/Widget.Kotatsu.AppBar"
|
style="@style/Widget.Kotatsu.AppBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:elevation="0dp">
|
android:elevation="4dp">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
|
|||||||
@@ -19,12 +19,41 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:elevation="0dp">
|
app:elevation="0dp">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:id="@id/toolbar"
|
android:id="@+id/toolbar_card"
|
||||||
style="@style/Widget.Kotatsu.Toolbar"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
app:layout_scrollFlags="scroll|enterAlways" />
|
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"
|
||||||
|
android:focusableInTouchMode="true"
|
||||||
|
android:focusable="true"
|
||||||
|
tools:title="@string/app_name">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.SearchView
|
||||||
|
android:id="@+id/searchView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:iconifiedByDefault="false"
|
||||||
|
app:queryHint="@string/search_manga"
|
||||||
|
android:paddingStart="-12dp"/>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
@@ -58,6 +87,9 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="start"
|
android:layout_gravity="start"
|
||||||
app:insetForeground="@android:color/transparent"
|
app:insetForeground="@android:color/transparent"
|
||||||
|
app:itemHorizontalPadding="16dp"
|
||||||
|
app:itemIconPadding="24dp"
|
||||||
|
app:itemIconTint="@color/navigation_item_color_tint"
|
||||||
app:menu="@menu/nav_drawer" />
|
app:menu="@menu/nav_drawer" />
|
||||||
|
|
||||||
</androidx.drawerlayout.widget.DrawerLayout>
|
</androidx.drawerlayout.widget.DrawerLayout>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
style="@style/Widget.Kotatsu.AppBar"
|
style="@style/Widget.Kotatsu.AppBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:elevation="0dp">
|
android:elevation="4dp">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@id/toolbar"
|
android:id="@id/toolbar"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
style="@style/Widget.Kotatsu.AppBar"
|
style="@style/Widget.Kotatsu.AppBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:elevation="0dp">
|
android:elevation="4dp">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@id/toolbar"
|
android:id="@id/toolbar"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
style="@style/Widget.Kotatsu.AppBar"
|
style="@style/Widget.Kotatsu.AppBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:elevation="0dp">
|
android:elevation="4dp">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@id/toolbar"
|
android:id="@id/toolbar"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
style="@style/Widget.Kotatsu.AppBar"
|
style="@style/Widget.Kotatsu.AppBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:elevation="0dp">
|
android:elevation="4dp">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@id/toolbar"
|
android:id="@id/toolbar"
|
||||||
|
|||||||
@@ -1,11 +1,37 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<TextView
|
<LinearLayout
|
||||||
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"
|
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"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:padding="20dp"
|
android:orientation="vertical"
|
||||||
android:textAppearance="?android:textAppearanceMedium"
|
android:padding="16dp">
|
||||||
android:textColor="?android:textColorSecondary"
|
|
||||||
tools:text="@tools:sample/lorem[3]" />
|
<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>
|
||||||
@@ -6,19 +6,22 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="16dp">
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:id="@+id/card_cover"
|
android:id="@+id/card_cover"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
app:cardCornerRadius="4dp"
|
app:cardCornerRadius="4dp"
|
||||||
app:cardElevation="4dp"
|
app:cardElevation="4dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintDimensionRatio="h,1:1"
|
app:layout_constraintDimensionRatio="h,1:1"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.0">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageView_cover"
|
android:id="@+id/imageView_cover"
|
||||||
|
|||||||
@@ -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>
|
|
||||||
@@ -8,13 +8,28 @@
|
|||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ImageView
|
<LinearLayout
|
||||||
android:layout_width="@dimen/nav_header_logo_size"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="@dimen/nav_header_logo_size"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/nav_item_horizontal_padding"
|
android:gravity="center"
|
||||||
android:layout_marginTop="@dimen/margin_normal"
|
android:orientation="horizontal">
|
||||||
android:layout_marginBottom="@dimen/margin_normal"
|
|
||||||
app:srcCompat="@drawable/ic_totoro" />
|
<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
|
<View
|
||||||
android:id="@+id/divider"
|
android:id="@+id/divider"
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_search"
|
|
||||||
android:icon="@drawable/ic_search"
|
|
||||||
android:orderInCategory="0"
|
|
||||||
android:title="@string/search"
|
|
||||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
|
||||||
app:showAsAction="always|collapseActionView" />
|
|
||||||
|
|
||||||
</menu>
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<color name="color_primary">#1976D2</color>
|
<color name="color_primary">#4098EF</color>
|
||||||
<color name="color_primary_variant">#1565C0</color>
|
<color name="color_primary_variant">#2C7CD6</color>
|
||||||
<color name="color_on_secondary">@android:color/black</color>
|
<color name="color_on_secondary">@android:color/black</color>
|
||||||
|
|
||||||
<color name="color_control_light">#2EFFFFFF</color> <!-- 18% white -->
|
<color name="color_control_light">#2EFFFFFF</color> <!-- 18% white -->
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<string name="history_is_empty">История пуста</string>
|
<string name="history_is_empty">История пуста</string>
|
||||||
<string name="read">Читать</string>
|
<string name="read">Читать</string>
|
||||||
<string name="add_bookmark">Добавить закладку</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_to_favourites">В избранное</string>
|
||||||
<string name="add_new_category">Создать категорию</string>
|
<string name="add_new_category">Создать категорию</string>
|
||||||
<string name="add">Добавить</string>
|
<string name="add">Добавить</string>
|
||||||
@@ -116,9 +116,13 @@
|
|||||||
<string name="rename">Переименовать</string>
|
<string name="rename">Переименовать</string>
|
||||||
<string name="category_delete_confirm">Вы уверены, что хотите удалить категорию \"%s\"? \nВся манга из данной категории будет утеряна.</string>
|
<string name="category_delete_confirm">Вы уверены, что хотите удалить категорию \"%s\"? \nВся манга из данной категории будет утеряна.</string>
|
||||||
<string name="remove_category">Удалить категорию</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_categories_holder">Категории помогают упорядочивать избранную мангу. Нажмите «+», чтобы создать категорию</string>
|
||||||
<string name="text_history_holder">Здесь будет оборажаться манга, которую Вы читаете. Вы можете найти, что почитать, в боковом меню</string>
|
<string name="text_history_holder_primary">Здесь будет отображаться манга, которую Вы читаете</string>
|
||||||
<string name="text_local_holder">У Вас пока нет сохранённой манги. Вы можете сохранить мангу из онлайн каталога или импортировать из файла</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="manga_shelf">Полка с мангой</string>
|
||||||
<string name="recent_manga">Недавняя манга</string>
|
<string name="recent_manga">Недавняя манга</string>
|
||||||
<string name="pages_animation">Анимация листания</string>
|
<string name="pages_animation">Анимация листания</string>
|
||||||
|
|||||||
@@ -13,29 +13,4 @@
|
|||||||
<attr name="android:orientation" />
|
<attr name="android:orientation" />
|
||||||
</declare-styleable>
|
</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>
|
</resources>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<string name="app_name" translatable="false">Kotatsu</string>
|
<string name="app_name" translatable="false">Kotatsu</string>
|
||||||
|
<string name="_empty" translatable="false"/>
|
||||||
<string name="close_menu">Close menu</string>
|
<string name="close_menu">Close menu</string>
|
||||||
<string name="open_menu">Open menu</string>
|
<string name="open_menu">Open menu</string>
|
||||||
<string name="local_storage">Local storage</string>
|
<string name="local_storage">Local storage</string>
|
||||||
@@ -117,9 +118,13 @@
|
|||||||
<string name="rename">Rename</string>
|
<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="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="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_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_search_holder_secondary">Try to reformulate the query.</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_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="manga_shelf">Manga shelf</string>
|
||||||
<string name="recent_manga">Recent manga</string>
|
<string name="recent_manga">Recent manga</string>
|
||||||
<string name="pages_animation">Pages animation</string>
|
<string name="pages_animation">Pages animation</string>
|
||||||
|
|||||||
@@ -29,6 +29,12 @@
|
|||||||
<item name="itemHorizontalPadding">@dimen/nav_item_horizontal_padding</item>
|
<item name="itemHorizontalPadding">@dimen/nav_item_horizontal_padding</item>
|
||||||
</style>
|
</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">
|
<style name="Widget.Kotatsu.Chip" parent="Widget.MaterialComponents.Chip.Action">
|
||||||
<item name="chipStrokeWidth">1dp</item>
|
<item name="chipStrokeWidth">1dp</item>
|
||||||
<item name="chipStrokeColor">?attr/colorAccent</item>
|
<item name="chipStrokeColor">?attr/colorAccent</item>
|
||||||
@@ -63,6 +69,10 @@
|
|||||||
<item name="android:textSize">20sp</item>
|
<item name="android:textSize">20sp</item>
|
||||||
</style>
|
</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">
|
<style name="TextAppearance.Kotatsu.Tab" parent="@style/TextAppearance.Design.Tab">
|
||||||
<item name="textAllCaps">false</item>
|
<item name="textAllCaps">false</item>
|
||||||
<item name="android:textAllCaps">false</item>
|
<item name="android:textAllCaps">false</item>
|
||||||
|
|||||||
@@ -14,9 +14,7 @@
|
|||||||
<!-- Window decor -->
|
<!-- Window decor -->
|
||||||
<item name="android:windowLightStatusBar" tools:targetApi="m">@bool/use_light_status</item>
|
<item name="android:windowLightStatusBar" tools:targetApi="m">@bool/use_light_status</item>
|
||||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||||
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">
|
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">@bool/use_light_navigation</item>
|
||||||
@bool/use_light_navigation
|
|
||||||
</item>
|
|
||||||
<item name="android:navigationBarColor">@color/nav_bar_scrim</item>
|
<item name="android:navigationBarColor">@color/nav_bar_scrim</item>
|
||||||
<item name="popupTheme">@style/ThemeOverlay.Kotatsu</item>
|
<item name="popupTheme">@style/ThemeOverlay.Kotatsu</item>
|
||||||
|
|
||||||
@@ -24,6 +22,7 @@
|
|||||||
<item name="toolbarStyle">@style/Widget.Kotatsu.Toolbar</item>
|
<item name="toolbarStyle">@style/Widget.Kotatsu.Toolbar</item>
|
||||||
<item name="tabStyle">@style/Widget.Kotatsu.Tabs</item>
|
<item name="tabStyle">@style/Widget.Kotatsu.Tabs</item>
|
||||||
<item name="navigationViewStyle">@style/Widget.Kotatsu.NavigationView</item>
|
<item name="navigationViewStyle">@style/Widget.Kotatsu.NavigationView</item>
|
||||||
|
<item name="searchViewStyle">@style/Widget.Kotatsu.SearchView</item>
|
||||||
|
|
||||||
<!-- Text appearances -->
|
<!-- Text appearances -->
|
||||||
<item name="textAppearanceBody2">@style/TextAppearance.Kotatsu.Body2</item>
|
<item name="textAppearanceBody2">@style/TextAppearance.Kotatsu.Body2</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user