更新界面
This commit is contained in:
26 files changed
+185
-532
No files matched your search
@@ -19,7 +19,7 @@ import io.legato.kazusa.R
|
|||||||
import splitties.views.onLongClick
|
import splitties.views.onLongClick
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
open class Preference(context: Context, attrs: AttributeSet) :
|
open class Preference(context: Context, attrs: AttributeSet?) :
|
||||||
androidx.preference.Preference(context, attrs) {
|
androidx.preference.Preference(context, attrs) {
|
||||||
|
|
||||||
private var onLongClick: ((preference: Preference) -> Boolean)? = null
|
private var onLongClick: ((preference: Preference) -> Boolean)? = null
|
||||||
@@ -68,7 +68,7 @@ open class Preference(context: Context, attrs: AttributeSet) :
|
|||||||
if (iconView is ImageView) {
|
if (iconView is ImageView) {
|
||||||
iconView.isVisible = icon != null
|
iconView.isVisible = icon != null
|
||||||
iconView.setImageDrawable(icon)
|
iconView.setImageDrawable(icon)
|
||||||
//iconView.setColorFilter(context.accentColor)
|
// iconView.setColorFilter(context.primaryColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (weightLayoutRes != null && weightLayoutRes != 0 && viewId != null && viewId != 0) {
|
if (weightLayoutRes != null && weightLayoutRes != 0 && viewId != null && viewId != 0) {
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import androidx.core.view.isVisible
|
|||||||
import androidx.preference.PreferenceCategory
|
import androidx.preference.PreferenceCategory
|
||||||
import androidx.preference.PreferenceViewHolder
|
import androidx.preference.PreferenceViewHolder
|
||||||
import io.legato.kazusa.R
|
import io.legato.kazusa.R
|
||||||
|
import io.legato.kazusa.lib.theme.primaryColor
|
||||||
|
import io.legato.kazusa.utils.themeColor
|
||||||
|
|
||||||
//import io.legado.app.lib.theme.accentColor
|
//import io.legado.app.lib.theme.accentColor
|
||||||
//import io.legado.app.lib.theme.backgroundColor
|
//import io.legado.app.lib.theme.backgroundColor
|
||||||
|
|
||||||
@@ -25,7 +28,7 @@ class PreferenceCategory(context: Context, attrs: AttributeSet) :
|
|||||||
if (view is TextView) { // && !view.isInEditMode
|
if (view is TextView) { // && !view.isInEditMode
|
||||||
view.text = title
|
view.text = title
|
||||||
if (view.isInEditMode) return
|
if (view.isInEditMode) return
|
||||||
//view.setTextColor(context.accentColor)
|
// view.setTextColor(context.primaryColor)
|
||||||
view.isVisible = !title.isNullOrEmpty()
|
view.isVisible = !title.isNullOrEmpty()
|
||||||
|
|
||||||
// val da = holder.findViewById(R.id.preference_divider_above)
|
// val da = holder.findViewById(R.id.preference_divider_above)
|
||||||
|
|||||||
@@ -31,11 +31,6 @@ class AppLogDialog : BaseDialogFragment(R.layout.dialog_recycler_view),
|
|||||||
LogAdapter(requireContext())
|
LogAdapter(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
setLayout(0.9f, ViewGroup.LayoutParams.WRAP_CONTENT)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
binding.run {
|
binding.run {
|
||||||
//toolBar.setBackgroundColor(primaryColor)
|
//toolBar.setBackgroundColor(primaryColor)
|
||||||
@@ -46,13 +41,21 @@ class AppLogDialog : BaseDialogFragment(R.layout.dialog_recycler_view),
|
|||||||
recyclerView.adapter = adapter
|
recyclerView.adapter = adapter
|
||||||
}
|
}
|
||||||
adapter.setItems(AppLog.logs)
|
adapter.setItems(AppLog.logs)
|
||||||
|
updateEmptyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateEmptyView() {
|
||||||
|
binding.emptyView.visibility =
|
||||||
|
if (adapter.itemCount == 0) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||||
when (item?.itemId) {
|
when (item?.itemId) {
|
||||||
R.id.menu_clear -> {
|
R.id.menu_clear -> {
|
||||||
AppLog.clear()
|
AppLog.clear()
|
||||||
adapter.clearItems()
|
adapter.clearItems()
|
||||||
|
updateEmptyView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ class ImportBookSourceDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_r
|
|||||||
}
|
}
|
||||||
viewModel.errorLiveData.observe(this) {
|
viewModel.errorLiveData.observe(this) {
|
||||||
binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
text = it
|
setMessage(it)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,8 +104,8 @@ class ImportBookSourceDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_r
|
|||||||
adapter.setItems(viewModel.allSources)
|
adapter.setItems(viewModel.allSources)
|
||||||
upSelectText()
|
upSelectText()
|
||||||
} else {
|
} else {
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
setText(R.string.wrong_format)
|
setMessage(R.string.wrong_format)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,20 +80,20 @@ class ImportDictRuleDialog() : BaseDialogFragment(R.layout.dialog_recycler_view)
|
|||||||
upSelectText()
|
upSelectText()
|
||||||
}
|
}
|
||||||
viewModel.errorLiveData.observe(this) {
|
viewModel.errorLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
text = it
|
setMessage(it)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
viewModel.successLiveData.observe(this) {
|
viewModel.successLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
adapter.setItems(viewModel.allSources)
|
adapter.setItems(viewModel.allSources)
|
||||||
upSelectText()
|
upSelectText()
|
||||||
} else {
|
} else {
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
setText(R.string.wrong_format)
|
setMessage(R.string.wrong_format)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import io.legato.kazusa.databinding.ItemSourceImportBinding
|
|||||||
import io.legato.kazusa.ui.widget.dialog.CodeDialog
|
import io.legato.kazusa.ui.widget.dialog.CodeDialog
|
||||||
import io.legato.kazusa.ui.widget.dialog.WaitDialog
|
import io.legato.kazusa.ui.widget.dialog.WaitDialog
|
||||||
import io.legato.kazusa.utils.GSON
|
import io.legato.kazusa.utils.GSON
|
||||||
|
import io.legato.kazusa.utils.gone
|
||||||
import io.legato.kazusa.utils.setLayout
|
import io.legato.kazusa.utils.setLayout
|
||||||
import io.legato.kazusa.utils.showDialogFragment
|
import io.legato.kazusa.utils.showDialogFragment
|
||||||
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
||||||
@@ -83,20 +84,20 @@ class ImportHttpTtsDialog() : BaseDialogFragment(R.layout.dialog_recycler_view),
|
|||||||
upSelectText()
|
upSelectText()
|
||||||
}
|
}
|
||||||
viewModel.errorLiveData.observe(this) {
|
viewModel.errorLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
text = it
|
setMessage(it)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
viewModel.successLiveData.observe(this) {
|
viewModel.successLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
adapter.setItems(viewModel.allSources)
|
adapter.setItems(viewModel.allSources)
|
||||||
upSelectText()
|
upSelectText()
|
||||||
} else {
|
} else {
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
setText(R.string.wrong_format)
|
setMessage(R.string.wrong_format)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,20 +88,20 @@ class ImportReplaceRuleDialog() : BaseDialogFragment(R.layout.dialog_recycler_vi
|
|||||||
upSelectText()
|
upSelectText()
|
||||||
}
|
}
|
||||||
viewModel.errorLiveData.observe(this) {
|
viewModel.errorLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
text = it
|
setMessage(it)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
viewModel.successLiveData.observe(this) {
|
viewModel.successLiveData.observe(this) {
|
||||||
// binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
adapter.setItems(viewModel.allRules)
|
adapter.setItems(viewModel.allRules)
|
||||||
upSelectText()
|
upSelectText()
|
||||||
} else {
|
} else {
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
setText(R.string.wrong_format)
|
setMessage(R.string.wrong_format)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,20 +92,20 @@ class ImportRssSourceDialog() : BaseDialogFragment(R.layout.dialog_recycler_view
|
|||||||
upSelectText()
|
upSelectText()
|
||||||
}
|
}
|
||||||
viewModel.errorLiveData.observe(this) {
|
viewModel.errorLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
text = it
|
setMessage(it)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
viewModel.successLiveData.observe(this) {
|
viewModel.successLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
adapter.setItems(viewModel.allSources)
|
adapter.setItems(viewModel.allSources)
|
||||||
upSelectText()
|
upSelectText()
|
||||||
} else {
|
} else {
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
setText(R.string.wrong_format)
|
setMessage(R.string.wrong_format)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import io.legato.kazusa.help.config.ThemeConfig
|
|||||||
import io.legato.kazusa.ui.widget.dialog.CodeDialog
|
import io.legato.kazusa.ui.widget.dialog.CodeDialog
|
||||||
import io.legato.kazusa.ui.widget.dialog.WaitDialog
|
import io.legato.kazusa.ui.widget.dialog.WaitDialog
|
||||||
import io.legato.kazusa.utils.GSON
|
import io.legato.kazusa.utils.GSON
|
||||||
|
import io.legato.kazusa.utils.gone
|
||||||
import io.legato.kazusa.utils.setLayout
|
import io.legato.kazusa.utils.setLayout
|
||||||
import io.legato.kazusa.utils.showDialogFragment
|
import io.legato.kazusa.utils.showDialogFragment
|
||||||
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
||||||
@@ -82,20 +83,20 @@ class ImportThemeDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_recycl
|
|||||||
upSelectText()
|
upSelectText()
|
||||||
}
|
}
|
||||||
viewModel.errorLiveData.observe(this) {
|
viewModel.errorLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
text = it
|
setMessage(it)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
viewModel.successLiveData.observe(this) {
|
viewModel.successLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
adapter.setItems(viewModel.allSources)
|
adapter.setItems(viewModel.allSources)
|
||||||
upSelectText()
|
upSelectText()
|
||||||
} else {
|
} else {
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
setText(R.string.wrong_format)
|
setMessage(R.string.wrong_format)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import io.legato.kazusa.databinding.ItemSourceImportBinding
|
|||||||
import io.legato.kazusa.ui.widget.dialog.CodeDialog
|
import io.legato.kazusa.ui.widget.dialog.CodeDialog
|
||||||
import io.legato.kazusa.ui.widget.dialog.WaitDialog
|
import io.legato.kazusa.ui.widget.dialog.WaitDialog
|
||||||
import io.legato.kazusa.utils.GSON
|
import io.legato.kazusa.utils.GSON
|
||||||
|
import io.legato.kazusa.utils.gone
|
||||||
import io.legato.kazusa.utils.setLayout
|
import io.legato.kazusa.utils.setLayout
|
||||||
import io.legato.kazusa.utils.showDialogFragment
|
import io.legato.kazusa.utils.showDialogFragment
|
||||||
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
||||||
@@ -82,20 +83,20 @@ class ImportTxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_recycler_vie
|
|||||||
upSelectText()
|
upSelectText()
|
||||||
}
|
}
|
||||||
viewModel.errorLiveData.observe(this) {
|
viewModel.errorLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
text = it
|
setMessage(it)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
viewModel.successLiveData.observe(this) {
|
viewModel.successLiveData.observe(this) {
|
||||||
//binding.rotateLoading.gone()
|
binding.rotateLoading.gone()
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
adapter.setItems(viewModel.allSources)
|
adapter.setItems(viewModel.allSources)
|
||||||
upSelectText()
|
upSelectText()
|
||||||
} else {
|
} else {
|
||||||
binding.tvMsg.apply {
|
binding.emptyView.apply {
|
||||||
setText(R.string.wrong_format)
|
setMessage(R.string.wrong_format)
|
||||||
visible()
|
visible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ class ExploreFragment() : VMBaseFragment<ExploreViewModel>(R.layout.fragment_exp
|
|||||||
).catch {
|
).catch {
|
||||||
AppLog.put("发现界面更新数据出错", it)
|
AppLog.put("发现界面更新数据出错", it)
|
||||||
}.conflate().flowOn(IO).collect {
|
}.conflate().flowOn(IO).collect {
|
||||||
binding.tvEmptyMsg.isGone = it.isNotEmpty() || searchView.text.isNotEmpty() == true
|
binding.emptyView.isGone = it.isNotEmpty() || searchView.text.isNotEmpty() == true
|
||||||
adapter.setItems(it, diffItemCallBack)
|
adapter.setItems(it, diffItemCallBack)
|
||||||
delay(500)
|
delay(500)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package io.legato.kazusa.ui.widget
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import io.legato.kazusa.R
|
||||||
|
import io.legato.kazusa.utils.dpToPx
|
||||||
|
import androidx.core.content.withStyledAttributes
|
||||||
|
|
||||||
|
class EmptyMessageView @JvmOverloads constructor(
|
||||||
|
context: Context, attrs: AttributeSet? = null
|
||||||
|
) : LinearLayout(context, attrs) {
|
||||||
|
|
||||||
|
private val faceTextView: TextView
|
||||||
|
private val messageTextView: TextView
|
||||||
|
|
||||||
|
private val faces = listOf(
|
||||||
|
"(๑`^´๑)", "(´・ᴗ・`)", "(•̀ᴗ•́)و", "(ᵔᴥᵔ)", "(¬‿¬)", "(ಥ﹏ಥ)", "(。•́︿•̀。)"
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
orientation = VERTICAL
|
||||||
|
gravity = Gravity.CENTER
|
||||||
|
layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
|
||||||
|
setPadding(16.dpToPx(), 16.dpToPx(), 16.dpToPx(), 16.dpToPx())
|
||||||
|
|
||||||
|
post {
|
||||||
|
val faceWidth = faceTextView.width
|
||||||
|
if (faceWidth > 0) {
|
||||||
|
messageTextView.maxWidth = (faceWidth * 2f).toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
faceTextView = TextView(context).apply {
|
||||||
|
layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
|
||||||
|
gravity = Gravity.CENTER
|
||||||
|
textSize = 32f
|
||||||
|
text = faces.random()
|
||||||
|
}
|
||||||
|
|
||||||
|
messageTextView = TextView(context).apply {
|
||||||
|
layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).apply {
|
||||||
|
topMargin = 8.dpToPx()
|
||||||
|
}
|
||||||
|
gravity = Gravity.CENTER
|
||||||
|
text = R.string.empty.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
addView(faceTextView)
|
||||||
|
addView(messageTextView)
|
||||||
|
|
||||||
|
attrs?.let {
|
||||||
|
context.withStyledAttributes(it, R.styleable.EmptyMessageView) {
|
||||||
|
val msg = getString(R.styleable.EmptyMessageView_messageText)
|
||||||
|
messageTextView.text = msg ?: ""
|
||||||
|
faceTextView.text = faces.random()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 设置文字消息 */
|
||||||
|
fun setMessage(@StringRes resId: Int) {
|
||||||
|
messageTextView.setText(resId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setMessage(msg: String) {
|
||||||
|
messageTextView.text = msg
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 可选:手动刷新随机颜文字 */
|
||||||
|
fun refreshFace() {
|
||||||
|
faceTextView.text = faces.random()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
package io.legato.kazusa.ui.widget.checkbox
|
|
||||||
|
|
||||||
import android.animation.ValueAnimator
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.*
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.View
|
|
||||||
import android.view.animation.LinearInterpolator
|
|
||||||
import android.widget.Checkable
|
|
||||||
import androidx.core.view.postDelayed
|
|
||||||
import io.legato.kazusa.R
|
|
||||||
import io.legato.kazusa.lib.theme.ThemeStore
|
|
||||||
import io.legato.kazusa.utils.dpToPx
|
|
||||||
import io.legato.kazusa.utils.getCompatColor
|
|
||||||
import kotlin.math.min
|
|
||||||
import kotlin.math.pow
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
import kotlin.math.sqrt
|
|
||||||
|
|
||||||
class SmoothCheckBox @JvmOverloads constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null
|
|
||||||
) : View(context, attrs), Checkable {
|
|
||||||
private var mPaint: Paint
|
|
||||||
private var mTickPaint: Paint
|
|
||||||
private var mFloorPaint: Paint
|
|
||||||
private var mTickPoints: Array<Point>
|
|
||||||
private var mCenterPoint: Point
|
|
||||||
private var mTickPath: Path
|
|
||||||
private var mLeftLineDistance = 0f
|
|
||||||
private var mRightLineDistance = 0f
|
|
||||||
private var mDrewDistance = 0f
|
|
||||||
private var mScaleVal = 1.0f
|
|
||||||
private var mFloorScale = 1.0f
|
|
||||||
private var mWidth = 0
|
|
||||||
private var mAnimDuration = 0
|
|
||||||
private var mStrokeWidth = 0
|
|
||||||
private var mCheckedColor = 0
|
|
||||||
private var mUnCheckedColor = 0
|
|
||||||
private var mFloorColor = 0
|
|
||||||
private var mFloorUnCheckedColor = 0
|
|
||||||
private var mChecked = false
|
|
||||||
private var mTickDrawing = false
|
|
||||||
var onCheckedChangeListener: ((checkBox: SmoothCheckBox, isChecked: Boolean) -> Unit)? = null
|
|
||||||
|
|
||||||
init {
|
|
||||||
val ta = context.obtainStyledAttributes(attrs, R.styleable.SmoothCheckBox)
|
|
||||||
var tickColor = ThemeStore.accentColor(context)
|
|
||||||
//mCheckedColor = context.getCompatColor(R.color.background_menu)
|
|
||||||
//mUnCheckedColor = context.getCompatColor(R.color.background_menu)
|
|
||||||
mFloorColor = context.getCompatColor(R.color.transparent30)
|
|
||||||
tickColor = ta.getColor(R.styleable.SmoothCheckBox_color_tick, tickColor)
|
|
||||||
mAnimDuration = ta.getInt(R.styleable.SmoothCheckBox_duration, DEF_ANIM_DURATION)
|
|
||||||
mFloorColor = ta.getColor(R.styleable.SmoothCheckBox_color_unchecked_stroke, mFloorColor)
|
|
||||||
mCheckedColor = ta.getColor(R.styleable.SmoothCheckBox_color_checked, mCheckedColor)
|
|
||||||
mUnCheckedColor = ta.getColor(R.styleable.SmoothCheckBox_color_unchecked, mUnCheckedColor)
|
|
||||||
mStrokeWidth = ta.getDimensionPixelSize(R.styleable.SmoothCheckBox_stroke_width, 0)
|
|
||||||
ta.recycle()
|
|
||||||
mFloorUnCheckedColor = mFloorColor
|
|
||||||
mTickPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
||||||
mTickPaint.style = Paint.Style.STROKE
|
|
||||||
mTickPaint.strokeCap = Paint.Cap.ROUND
|
|
||||||
mTickPaint.color = tickColor
|
|
||||||
mFloorPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
||||||
mFloorPaint.style = Paint.Style.FILL
|
|
||||||
mFloorPaint.color = mFloorColor
|
|
||||||
mPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
||||||
mPaint.style = Paint.Style.FILL
|
|
||||||
mPaint.color = mCheckedColor
|
|
||||||
mTickPath = Path()
|
|
||||||
mCenterPoint = Point()
|
|
||||||
mTickPoints = arrayOf(Point(), Point(), Point())
|
|
||||||
setOnClickListener {
|
|
||||||
toggle()
|
|
||||||
mTickDrawing = false
|
|
||||||
mDrewDistance = 0f
|
|
||||||
if (isChecked) {
|
|
||||||
startCheckedAnimation()
|
|
||||||
} else {
|
|
||||||
startUnCheckedAnimation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isChecked(): Boolean {
|
|
||||||
return mChecked
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setChecked(checked: Boolean) {
|
|
||||||
mChecked = checked
|
|
||||||
reset()
|
|
||||||
invalidate()
|
|
||||||
onCheckedChangeListener?.invoke(this@SmoothCheckBox, mChecked)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toggle() {
|
|
||||||
this.isChecked = !isChecked
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* checked with animation
|
|
||||||
*
|
|
||||||
* @param checked checked
|
|
||||||
* @param animate change with animation
|
|
||||||
*/
|
|
||||||
fun setChecked(checked: Boolean, animate: Boolean) {
|
|
||||||
if (animate) {
|
|
||||||
mTickDrawing = false
|
|
||||||
mChecked = checked
|
|
||||||
mDrewDistance = 0f
|
|
||||||
if (checked) {
|
|
||||||
startCheckedAnimation()
|
|
||||||
} else {
|
|
||||||
startUnCheckedAnimation()
|
|
||||||
}
|
|
||||||
onCheckedChangeListener?.invoke(this@SmoothCheckBox, mChecked)
|
|
||||||
} else {
|
|
||||||
this.isChecked = checked
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun reset() {
|
|
||||||
mTickDrawing = true
|
|
||||||
mFloorScale = 1.0f
|
|
||||||
mScaleVal = if (isChecked) 0f else 1.0f
|
|
||||||
mFloorColor = if (isChecked) mCheckedColor else mFloorUnCheckedColor
|
|
||||||
mDrewDistance = if (isChecked) mLeftLineDistance + mRightLineDistance else 0f
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun measureSize(measureSpec: Int): Int {
|
|
||||||
val defSize: Int = DEF_DRAW_SIZE.dpToPx()
|
|
||||||
val specSize = MeasureSpec.getSize(measureSpec)
|
|
||||||
val specMode = MeasureSpec.getMode(measureSpec)
|
|
||||||
var result = 0
|
|
||||||
when (specMode) {
|
|
||||||
MeasureSpec.UNSPECIFIED, MeasureSpec.AT_MOST -> result = min(defSize, specSize)
|
|
||||||
MeasureSpec.EXACTLY -> result = specSize
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
|
||||||
setMeasuredDimension(measureSize(widthMeasureSpec), measureSize(heightMeasureSpec))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLayout(
|
|
||||||
changed: Boolean,
|
|
||||||
left: Int,
|
|
||||||
top: Int,
|
|
||||||
right: Int,
|
|
||||||
bottom: Int
|
|
||||||
) {
|
|
||||||
mWidth = measuredWidth
|
|
||||||
mStrokeWidth = if (mStrokeWidth == 0) measuredWidth / 10 else mStrokeWidth
|
|
||||||
mStrokeWidth =
|
|
||||||
if (mStrokeWidth > measuredWidth / 5) measuredWidth / 5 else mStrokeWidth
|
|
||||||
mStrokeWidth = if (mStrokeWidth < 3) 3 else mStrokeWidth
|
|
||||||
mCenterPoint.x = mWidth / 2
|
|
||||||
mCenterPoint.y = measuredHeight / 2
|
|
||||||
mTickPoints[0].x = (measuredWidth.toFloat() / 30 * 7).roundToInt()
|
|
||||||
mTickPoints[0].y = (measuredHeight.toFloat() / 30 * 14).roundToInt()
|
|
||||||
mTickPoints[1].x = (measuredWidth.toFloat() / 30 * 13).roundToInt()
|
|
||||||
mTickPoints[1].y = (measuredHeight.toFloat() / 30 * 20).roundToInt()
|
|
||||||
mTickPoints[2].x = (measuredWidth.toFloat() / 30 * 22).roundToInt()
|
|
||||||
mTickPoints[2].y = (measuredHeight.toFloat() / 30 * 10).roundToInt()
|
|
||||||
mLeftLineDistance = sqrt(
|
|
||||||
(mTickPoints[1].x - mTickPoints[0].x.toDouble()).pow(2.0) +
|
|
||||||
(mTickPoints[1].y - mTickPoints[0].y.toDouble()).pow(2.0)
|
|
||||||
).toFloat()
|
|
||||||
mRightLineDistance = sqrt(
|
|
||||||
(mTickPoints[2].x - mTickPoints[1].x.toDouble()).pow(2.0) +
|
|
||||||
(mTickPoints[2].y - mTickPoints[1].y.toDouble()).pow(2.0)
|
|
||||||
).toFloat()
|
|
||||||
mTickPaint.strokeWidth = mStrokeWidth.toFloat()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
|
||||||
drawBorder(canvas)
|
|
||||||
drawCenter(canvas)
|
|
||||||
drawTick(canvas)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawCenter(canvas: Canvas) {
|
|
||||||
mPaint.color = mUnCheckedColor
|
|
||||||
val radius = (mCenterPoint.x - mStrokeWidth) * mScaleVal
|
|
||||||
canvas.drawCircle(mCenterPoint.x.toFloat(), mCenterPoint.y.toFloat(), radius, mPaint)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawBorder(canvas: Canvas) {
|
|
||||||
mFloorPaint.color = mFloorColor
|
|
||||||
val radius = mCenterPoint.x
|
|
||||||
canvas.drawCircle(
|
|
||||||
mCenterPoint.x.toFloat(),
|
|
||||||
mCenterPoint.y.toFloat(),
|
|
||||||
radius * mFloorScale,
|
|
||||||
mFloorPaint
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawTick(canvas: Canvas) {
|
|
||||||
if (mTickDrawing && isChecked) {
|
|
||||||
drawTickPath(canvas)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawTickPath(canvas: Canvas) {
|
|
||||||
mTickPath.reset()
|
|
||||||
// draw left of the tick
|
|
||||||
if (mDrewDistance < mLeftLineDistance) {
|
|
||||||
val step: Float = if (mWidth / 20.0f < 3) 3f else mWidth / 20.0f
|
|
||||||
mDrewDistance += step
|
|
||||||
val stopX =
|
|
||||||
mTickPoints[0].x + (mTickPoints[1].x - mTickPoints[0].x) * mDrewDistance / mLeftLineDistance
|
|
||||||
val stopY =
|
|
||||||
mTickPoints[0].y + (mTickPoints[1].y - mTickPoints[0].y) * mDrewDistance / mLeftLineDistance
|
|
||||||
mTickPath.moveTo(mTickPoints[0].x.toFloat(), mTickPoints[0].y.toFloat())
|
|
||||||
mTickPath.lineTo(stopX, stopY)
|
|
||||||
canvas.drawPath(mTickPath, mTickPaint)
|
|
||||||
if (mDrewDistance > mLeftLineDistance) {
|
|
||||||
mDrewDistance = mLeftLineDistance
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mTickPath.moveTo(mTickPoints[0].x.toFloat(), mTickPoints[0].y.toFloat())
|
|
||||||
mTickPath.lineTo(mTickPoints[1].x.toFloat(), mTickPoints[1].y.toFloat())
|
|
||||||
canvas.drawPath(mTickPath, mTickPaint)
|
|
||||||
// draw right of the tick
|
|
||||||
if (mDrewDistance < mLeftLineDistance + mRightLineDistance) {
|
|
||||||
val stopX =
|
|
||||||
mTickPoints[1].x + (mTickPoints[2].x - mTickPoints[1].x) * (mDrewDistance - mLeftLineDistance) / mRightLineDistance
|
|
||||||
val stopY =
|
|
||||||
mTickPoints[1].y - (mTickPoints[1].y - mTickPoints[2].y) * (mDrewDistance - mLeftLineDistance) / mRightLineDistance
|
|
||||||
mTickPath.reset()
|
|
||||||
mTickPath.moveTo(mTickPoints[1].x.toFloat(), mTickPoints[1].y.toFloat())
|
|
||||||
mTickPath.lineTo(stopX, stopY)
|
|
||||||
canvas.drawPath(mTickPath, mTickPaint)
|
|
||||||
val step: Float = if (mWidth / 20f < 3) 3f else mWidth / 20f
|
|
||||||
mDrewDistance += step
|
|
||||||
} else {
|
|
||||||
mTickPath.reset()
|
|
||||||
mTickPath.moveTo(mTickPoints[1].x.toFloat(), mTickPoints[1].y.toFloat())
|
|
||||||
mTickPath.lineTo(mTickPoints[2].x.toFloat(), mTickPoints[2].y.toFloat())
|
|
||||||
canvas.drawPath(mTickPath, mTickPaint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// invalidate
|
|
||||||
if (mDrewDistance < mLeftLineDistance + mRightLineDistance) {
|
|
||||||
postDelayed(10) { this.postInvalidate() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startCheckedAnimation() {
|
|
||||||
val animator = ValueAnimator.ofFloat(1.0f, 0f)
|
|
||||||
animator.duration = mAnimDuration / 3 * 2.toLong()
|
|
||||||
animator.interpolator = LinearInterpolator()
|
|
||||||
animator.addUpdateListener { animation: ValueAnimator ->
|
|
||||||
mScaleVal = animation.animatedValue as Float
|
|
||||||
mFloorColor = getGradientColor(
|
|
||||||
mUnCheckedColor,
|
|
||||||
mCheckedColor,
|
|
||||||
1 - mScaleVal
|
|
||||||
)
|
|
||||||
postInvalidate()
|
|
||||||
}
|
|
||||||
animator.start()
|
|
||||||
val floorAnimator = ValueAnimator.ofFloat(1.0f, 0.8f, 1.0f)
|
|
||||||
floorAnimator.duration = mAnimDuration.toLong()
|
|
||||||
floorAnimator.interpolator = LinearInterpolator()
|
|
||||||
floorAnimator.addUpdateListener { animation: ValueAnimator ->
|
|
||||||
mFloorScale = animation.animatedValue as Float
|
|
||||||
postInvalidate()
|
|
||||||
}
|
|
||||||
floorAnimator.start()
|
|
||||||
drawTickDelayed()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startUnCheckedAnimation() {
|
|
||||||
val animator = ValueAnimator.ofFloat(0f, 1.0f)
|
|
||||||
animator.duration = mAnimDuration.toLong()
|
|
||||||
animator.interpolator = LinearInterpolator()
|
|
||||||
animator.addUpdateListener { animation: ValueAnimator ->
|
|
||||||
mScaleVal = animation.animatedValue as Float
|
|
||||||
mFloorColor = getGradientColor(
|
|
||||||
mCheckedColor,
|
|
||||||
mFloorUnCheckedColor,
|
|
||||||
mScaleVal
|
|
||||||
)
|
|
||||||
postInvalidate()
|
|
||||||
}
|
|
||||||
animator.start()
|
|
||||||
val floorAnimator = ValueAnimator.ofFloat(1.0f, 0.8f, 1.0f)
|
|
||||||
floorAnimator.duration = mAnimDuration.toLong()
|
|
||||||
floorAnimator.interpolator = LinearInterpolator()
|
|
||||||
floorAnimator.addUpdateListener { animation: ValueAnimator ->
|
|
||||||
mFloorScale = animation.animatedValue as Float
|
|
||||||
postInvalidate()
|
|
||||||
}
|
|
||||||
floorAnimator.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawTickDelayed() {
|
|
||||||
postDelayed(mAnimDuration.toLong()) {
|
|
||||||
mTickDrawing = true
|
|
||||||
postInvalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val DEF_DRAW_SIZE = 25
|
|
||||||
private const val DEF_ANIM_DURATION = 300
|
|
||||||
private fun getGradientColor(startColor: Int, endColor: Int, percent: Float): Int {
|
|
||||||
val startA = Color.alpha(startColor)
|
|
||||||
val startR = Color.red(startColor)
|
|
||||||
val startG = Color.green(startColor)
|
|
||||||
val startB = Color.blue(startColor)
|
|
||||||
val endA = Color.alpha(endColor)
|
|
||||||
val endR = Color.red(endColor)
|
|
||||||
val endG = Color.green(endColor)
|
|
||||||
val endB = Color.blue(endColor)
|
|
||||||
val currentA = (startA * (1 - percent) + endA * percent).toInt()
|
|
||||||
val currentR = (startR * (1 - percent) + endR * percent).toInt()
|
|
||||||
val currentG = (startG * (1 - percent) + endG * percent).toInt()
|
|
||||||
val currentB = (startB * (1 - percent) + endB * percent).toInt()
|
|
||||||
return Color.argb(currentA, currentR, currentG, currentB)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@ import io.legato.kazusa.lib.theme.ThemeStore
|
|||||||
class PrimaryTextView(context: Context, attrs: AttributeSet) :
|
class PrimaryTextView(context: Context, attrs: AttributeSet) :
|
||||||
AppCompatTextView(context, attrs) {
|
AppCompatTextView(context, attrs) {
|
||||||
|
|
||||||
init {
|
// init {
|
||||||
setTextColor(ThemeStore.textColorPrimary(context))
|
// setTextColor(ThemeStore.textColorPrimary(context))
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
package io.legato.kazusa.ui.widget.text
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
|
||||||
import io.legato.kazusa.R
|
|
||||||
import io.legato.kazusa.lib.theme.*
|
|
||||||
import io.legato.kazusa.utils.dpToPx
|
|
||||||
import io.legato.kazusa.utils.getCompatColor
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
open class StrokeTextView(context: Context, attrs: AttributeSet?) :
|
|
||||||
AppCompatTextView(context, attrs) {
|
|
||||||
|
|
||||||
private var radius = 1.dpToPx()
|
|
||||||
private val isBottomBackground: Boolean
|
|
||||||
|
|
||||||
init {
|
|
||||||
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.StrokeTextView)
|
|
||||||
radius = typedArray.getDimensionPixelOffset(R.styleable.StrokeTextView_radius, radius)
|
|
||||||
isBottomBackground =
|
|
||||||
typedArray.getBoolean(R.styleable.StrokeTextView_isBottomBackground, false)
|
|
||||||
typedArray.recycle()
|
|
||||||
upBackground()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setRadius(radius: Int) {
|
|
||||||
this.radius = radius.dpToPx()
|
|
||||||
upBackground()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun upBackground() {
|
|
||||||
when {
|
|
||||||
isInEditMode -> {
|
|
||||||
background = Selector.shapeBuild()
|
|
||||||
.setCornerRadius(radius)
|
|
||||||
.setStrokeWidth(1.dpToPx())
|
|
||||||
.setDisabledStrokeColor(context.getCompatColor(R.color.md_grey_500))
|
|
||||||
.setDefaultStrokeColor(context.getCompatColor(R.color.secondaryText))
|
|
||||||
//.setSelectedStrokeColor(context.getCompatColor(R.color.accent))
|
|
||||||
.setPressedBgColor(context.getCompatColor(R.color.transparent30))
|
|
||||||
.create()
|
|
||||||
setTextColor(
|
|
||||||
Selector.colorBuild()
|
|
||||||
.setDefaultColor(context.getCompatColor(R.color.secondaryText))
|
|
||||||
//.setSelectedColor(context.getCompatColor(R.color.accent))
|
|
||||||
.setDisabledColor(context.getCompatColor(R.color.md_grey_500))
|
|
||||||
.create()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
isBottomBackground -> {
|
|
||||||
//val isLight = ColorUtils.isColorLight(context.bottomBackground)
|
|
||||||
background = Selector.shapeBuild()
|
|
||||||
.setCornerRadius(radius)
|
|
||||||
.setStrokeWidth(1.dpToPx())
|
|
||||||
.setDisabledStrokeColor(context.getCompatColor(R.color.md_grey_500))
|
|
||||||
// .setDefaultStrokeColor(context.getPrimaryTextColor(isLight))
|
|
||||||
// .setSelectedStrokeColor(context.accentColor)
|
|
||||||
.setPressedBgColor(context.getCompatColor(R.color.transparent30))
|
|
||||||
.create()
|
|
||||||
setTextColor(
|
|
||||||
Selector.colorBuild()
|
|
||||||
// .setDefaultColor(context.getPrimaryTextColor(isLight))
|
|
||||||
// .setSelectedColor(context.accentColor)
|
|
||||||
.setDisabledColor(context.getCompatColor(R.color.md_grey_500))
|
|
||||||
.create()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
background = Selector.shapeBuild()
|
|
||||||
.setCornerRadius(radius)
|
|
||||||
.setStrokeWidth(1.dpToPx())
|
|
||||||
.setDisabledStrokeColor(context.getCompatColor(R.color.md_grey_500))
|
|
||||||
.setDefaultStrokeColor(ThemeStore.textColorSecondary(context))
|
|
||||||
.setSelectedStrokeColor(ThemeStore.accentColor(context))
|
|
||||||
.setPressedBgColor(context.getCompatColor(R.color.transparent30))
|
|
||||||
.create()
|
|
||||||
setTextColor(
|
|
||||||
Selector.colorBuild()
|
|
||||||
.setDefaultColor(ThemeStore.textColorSecondary(context))
|
|
||||||
.setSelectedColor(ThemeStore.accentColor(context))
|
|
||||||
.setDisabledColor(context.getCompatColor(R.color.md_grey_500))
|
|
||||||
.create()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -49,6 +49,7 @@
|
|||||||
android:id="@+id/refresh_progress_bar"
|
android:id="@+id/refresh_progress_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
android:indeterminate="true"
|
android:indeterminate="true"
|
||||||
app:layout_constraintTop_toBottomOf="@id/lay_top" />
|
app:layout_constraintTop_toBottomOf="@id/lay_top" />
|
||||||
|
|
||||||
|
|||||||
@@ -79,29 +79,13 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<io.legato.kazusa.ui.widget.EmptyMessageView
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/tv_empty_msg"
|
android:id="@+id/tv_empty_msg"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="16dp"
|
android:visibility="invisible"
|
||||||
android:gravity="center"
|
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:orientation="vertical"
|
app:messageText="还没有源!"/>
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="(๑`^´๑)"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:text="还没有源!" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recycler_view"
|
android:id="@+id/recycler_view"
|
||||||
|
|||||||
@@ -28,16 +28,17 @@
|
|||||||
android:id="@+id/rotate_loading"
|
android:id="@+id/rotate_loading"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
android:layout_margin="32dp"
|
android:layout_margin="32dp"
|
||||||
android:layout_gravity="center"/>
|
android:layout_gravity="center"/>
|
||||||
|
|
||||||
<TextView
|
<io.legato.kazusa.ui.widget.EmptyMessageView
|
||||||
android:id="@+id/tv_msg"
|
android:id="@+id/emptyView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="16dp"
|
android:visibility="invisible"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:visibility="gone" />
|
app:messageText="@string/empty"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<io.legato.kazusa.ui.widget.checkbox.SmoothCheckBox
|
<com.google.android.material.checkbox.MaterialCheckBox
|
||||||
android:id="@+id/cb_all_export"
|
android:id="@+id/cb_all_export"
|
||||||
android:layout_width="20dp"
|
android:layout_width="20dp"
|
||||||
android:layout_height="20dp"
|
android:layout_height="20dp"
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<io.legato.kazusa.ui.widget.checkbox.SmoothCheckBox
|
<com.google.android.material.checkbox.MaterialCheckBox
|
||||||
android:id="@+id/cb_select_export"
|
android:id="@+id/cb_select_export"
|
||||||
android:layout_width="20dp"
|
android:layout_width="20dp"
|
||||||
android:layout_height="20dp"
|
android:layout_height="20dp"
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout 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"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:id="@+id/refresh_layout"
|
android:id="@+id/refresh_layout"
|
||||||
@@ -17,27 +18,13 @@
|
|||||||
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<io.legato.kazusa.ui.widget.EmptyMessageView
|
||||||
android:id="@+id/tv_empty_msg"
|
android:id="@+id/emptyView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:visibility="gone"
|
android:visibility="visible"
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_margin="16dp"
|
app:messageText="@string/bookshelf_empty"/>
|
||||||
android:gravity="center">
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="(๑`^´๑)"
|
|
||||||
android:textSize="32sp" />
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:text="@string/bookshelf_empty" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
@@ -55,29 +55,16 @@
|
|||||||
tools:listitem="@layout/item_find_book"
|
tools:listitem="@layout/item_find_book"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
||||||
|
|
||||||
<LinearLayout
|
<io.legato.kazusa.ui.widget.EmptyMessageView
|
||||||
android:id="@+id/tv_empty_msg"
|
android:id="@+id/emptyView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_anchor="@id/app_bar"
|
app:layout_anchor="@id/rv_find"
|
||||||
app:layout_anchorGravity="center"
|
app:layout_anchorGravity="center"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_margin="16dp"
|
android:gravity="center"
|
||||||
android:gravity="center">
|
app:messageText="@string/explore_empty"/>
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="(っ˘ω˘ς )"
|
|
||||||
android:textSize="32sp" />
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/explore_empty" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
@@ -131,4 +131,9 @@
|
|||||||
<item>关闭</item>
|
<item>关闭</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="customMode">
|
||||||
|
<item>全局</item>
|
||||||
|
<item>仅强调色</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -613,7 +613,7 @@
|
|||||||
<string name="dur_pos">当前位置:</string>
|
<string name="dur_pos">当前位置:</string>
|
||||||
<string name="precision_search">精准搜索</string>
|
<string name="precision_search">精准搜索</string>
|
||||||
<string name="service_starting">正在启动服务</string>
|
<string name="service_starting">正在启动服务</string>
|
||||||
<string name="empty">空</string>
|
<string name="empty">内容为空</string>
|
||||||
<string name="file_chooser">文件选择</string>
|
<string name="file_chooser">文件选择</string>
|
||||||
<string name="folder_chooser">文件夹选择</string>
|
<string name="folder_chooser">文件夹选择</string>
|
||||||
<string name="bottom_line">我是有底线的</string>
|
<string name="bottom_line">我是有底线的</string>
|
||||||
@@ -786,7 +786,7 @@
|
|||||||
<string name="import_str">导入</string>
|
<string name="import_str">导入</string>
|
||||||
<string name="export_str">导出</string>
|
<string name="export_str">导出</string>
|
||||||
<string name="save_theme_config">保存主题配置</string>
|
<string name="save_theme_config">保存主题配置</string>
|
||||||
<string name="save_day_theme_summary">保存白天主题配置以供调用和分享</string>
|
<string name="save_day_theme_summary">保存主题配置以供调用和分享</string>
|
||||||
<string name="save_night_theme_summary">保存夜间主题配置以供调用和分享</string>
|
<string name="save_night_theme_summary">保存夜间主题配置以供调用和分享</string>
|
||||||
<string name="theme_list">主题列表</string>
|
<string name="theme_list">主题列表</string>
|
||||||
<string name="theme_list_summary">使用、保存、导入或分享主题</string>
|
<string name="theme_list_summary">使用、保存、导入或分享主题</string>
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
<item>9</item>
|
<item>9</item>
|
||||||
<item>10</item>
|
<item>10</item>
|
||||||
<item>11</item>
|
<item>11</item>
|
||||||
|
<item>12</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="screen_direction_value">
|
<string-array name="screen_direction_value">
|
||||||
@@ -75,4 +76,9 @@
|
|||||||
<item>off</item>
|
<item>off</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="customMode_value">
|
||||||
|
<item>global</item>
|
||||||
|
<item>accent</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -66,6 +66,7 @@
|
|||||||
<item>千禧年</item>
|
<item>千禧年</item>
|
||||||
<item>隐海修会</item>
|
<item>隐海修会</item>
|
||||||
<item>乐队</item>
|
<item>乐队</item>
|
||||||
|
<item>自定义</item>
|
||||||
<item>透明</item>
|
<item>透明</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
@@ -163,6 +164,11 @@
|
|||||||
<item>Off</item>
|
<item>Off</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="customMode">
|
||||||
|
<item>Global</item>
|
||||||
|
<item>Accent</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="rule_type">
|
<string-array name="rule_type">
|
||||||
<item>BookSource</item>
|
<item>BookSource</item>
|
||||||
<item>RssSource</item>
|
<item>RssSource</item>
|
||||||
|
|||||||
@@ -254,4 +254,8 @@
|
|||||||
<attr name="tipText" format="string" />
|
<attr name="tipText" format="string" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="EmptyMessageView">
|
||||||
|
<attr name="messageText" format="string" />
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
Reference in new issue
Block a user