From 58e0f51c3e6a8fdaee4b99a525725ee477804f41 Mon Sep 17 00:00:00 2001 From: HapeLee <1321903405@qq.com> Date: Mon, 22 Sep 2025 01:14:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/legato/kazusa/lib/prefs/Preference.kt | 4 +- .../kazusa/lib/prefs/PreferenceCategory.kt | 5 +- .../io/legato/kazusa/ui/about/AppLogDialog.kt | 13 +- .../ui/association/ImportBookSourceDialog.kt | 8 +- .../ui/association/ImportDictRuleDialog.kt | 12 +- .../ui/association/ImportHttpTtsDialog.kt | 13 +- .../ui/association/ImportReplaceRuleDialog.kt | 12 +- .../ui/association/ImportRssSourceDialog.kt | 12 +- .../ui/association/ImportThemeDialog.kt | 13 +- .../ui/association/ImportTxtTocRuleDialog.kt | 13 +- .../kazusa/ui/main/explore/ExploreFragment.kt | 2 +- .../kazusa/ui/widget/EmptyMessageView.kt | 78 +++++ .../ui/widget/checkbox/SmoothCheckBox.kt | 327 ------------------ .../kazusa/ui/widget/text/PrimaryTextView.kt | 6 +- .../kazusa/ui/widget/text/StrokeTextView.kt | 88 ----- .../main/res/layout/activity_import_book.xml | 1 + .../res/layout/dialog_book_change_source.xml | 22 +- .../main/res/layout/dialog_recycler_view.xml | 11 +- .../layout/dialog_select_section_export.xml | 4 +- app/src/main/res/layout/fragment_books.xml | 25 +- app/src/main/res/layout/fragment_explore.xml | 23 +- app/src/main/res/values-zh/arrays.xml | 5 + app/src/main/res/values-zh/strings.xml | 4 +- app/src/main/res/values/array_values.xml | 6 + app/src/main/res/values/arrays.xml | 6 + app/src/main/res/values/attrs.xml | 4 + 26 files changed, 185 insertions(+), 532 deletions(-) create mode 100644 app/src/main/java/io/legato/kazusa/ui/widget/EmptyMessageView.kt delete mode 100644 app/src/main/java/io/legato/kazusa/ui/widget/checkbox/SmoothCheckBox.kt delete mode 100644 app/src/main/java/io/legato/kazusa/ui/widget/text/StrokeTextView.kt diff --git a/app/src/main/java/io/legato/kazusa/lib/prefs/Preference.kt b/app/src/main/java/io/legato/kazusa/lib/prefs/Preference.kt index 622f88b34..69b37eb8f 100644 --- a/app/src/main/java/io/legato/kazusa/lib/prefs/Preference.kt +++ b/app/src/main/java/io/legato/kazusa/lib/prefs/Preference.kt @@ -19,7 +19,7 @@ import io.legato.kazusa.R import splitties.views.onLongClick import kotlin.math.roundToInt -open class Preference(context: Context, attrs: AttributeSet) : +open class Preference(context: Context, attrs: AttributeSet?) : androidx.preference.Preference(context, attrs) { private var onLongClick: ((preference: Preference) -> Boolean)? = null @@ -68,7 +68,7 @@ open class Preference(context: Context, attrs: AttributeSet) : if (iconView is ImageView) { iconView.isVisible = icon != null iconView.setImageDrawable(icon) - //iconView.setColorFilter(context.accentColor) + // iconView.setColorFilter(context.primaryColor) } if (weightLayoutRes != null && weightLayoutRes != 0 && viewId != null && viewId != 0) { diff --git a/app/src/main/java/io/legato/kazusa/lib/prefs/PreferenceCategory.kt b/app/src/main/java/io/legato/kazusa/lib/prefs/PreferenceCategory.kt index f65010e67..bba223395 100644 --- a/app/src/main/java/io/legato/kazusa/lib/prefs/PreferenceCategory.kt +++ b/app/src/main/java/io/legato/kazusa/lib/prefs/PreferenceCategory.kt @@ -7,6 +7,9 @@ import androidx.core.view.isVisible import androidx.preference.PreferenceCategory import androidx.preference.PreferenceViewHolder 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.backgroundColor @@ -25,7 +28,7 @@ class PreferenceCategory(context: Context, attrs: AttributeSet) : if (view is TextView) { // && !view.isInEditMode view.text = title if (view.isInEditMode) return - //view.setTextColor(context.accentColor) + // view.setTextColor(context.primaryColor) view.isVisible = !title.isNullOrEmpty() // val da = holder.findViewById(R.id.preference_divider_above) diff --git a/app/src/main/java/io/legato/kazusa/ui/about/AppLogDialog.kt b/app/src/main/java/io/legato/kazusa/ui/about/AppLogDialog.kt index 102b0fafb..859166756 100644 --- a/app/src/main/java/io/legato/kazusa/ui/about/AppLogDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/about/AppLogDialog.kt @@ -31,11 +31,6 @@ class AppLogDialog : BaseDialogFragment(R.layout.dialog_recycler_view), LogAdapter(requireContext()) } - override fun onStart() { - super.onStart() - setLayout(0.9f, ViewGroup.LayoutParams.WRAP_CONTENT) - } - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { binding.run { //toolBar.setBackgroundColor(primaryColor) @@ -46,13 +41,21 @@ class AppLogDialog : BaseDialogFragment(R.layout.dialog_recycler_view), recyclerView.adapter = adapter } 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 { when (item?.itemId) { R.id.menu_clear -> { AppLog.clear() adapter.clearItems() + updateEmptyView() } } return true diff --git a/app/src/main/java/io/legato/kazusa/ui/association/ImportBookSourceDialog.kt b/app/src/main/java/io/legato/kazusa/ui/association/ImportBookSourceDialog.kt index edc372c10..fd7777529 100644 --- a/app/src/main/java/io/legato/kazusa/ui/association/ImportBookSourceDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/association/ImportBookSourceDialog.kt @@ -93,8 +93,8 @@ class ImportBookSourceDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_r } viewModel.errorLiveData.observe(this) { binding.rotateLoading.gone() - binding.tvMsg.apply { - text = it + binding.emptyView.apply { + setMessage(it) visible() } } @@ -104,8 +104,8 @@ class ImportBookSourceDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_r adapter.setItems(viewModel.allSources) upSelectText() } else { - binding.tvMsg.apply { - setText(R.string.wrong_format) + binding.emptyView.apply { + setMessage(R.string.wrong_format) visible() } } diff --git a/app/src/main/java/io/legato/kazusa/ui/association/ImportDictRuleDialog.kt b/app/src/main/java/io/legato/kazusa/ui/association/ImportDictRuleDialog.kt index 2ee2b57e3..e5cb0ae97 100644 --- a/app/src/main/java/io/legato/kazusa/ui/association/ImportDictRuleDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/association/ImportDictRuleDialog.kt @@ -80,20 +80,20 @@ class ImportDictRuleDialog() : BaseDialogFragment(R.layout.dialog_recycler_view) upSelectText() } viewModel.errorLiveData.observe(this) { - //binding.rotateLoading.gone() - binding.tvMsg.apply { - text = it + binding.rotateLoading.gone() + binding.emptyView.apply { + setMessage(it) visible() } } viewModel.successLiveData.observe(this) { - //binding.rotateLoading.gone() + binding.rotateLoading.gone() if (it > 0) { adapter.setItems(viewModel.allSources) upSelectText() } else { - binding.tvMsg.apply { - setText(R.string.wrong_format) + binding.emptyView.apply { + setMessage(R.string.wrong_format) visible() } } diff --git a/app/src/main/java/io/legato/kazusa/ui/association/ImportHttpTtsDialog.kt b/app/src/main/java/io/legato/kazusa/ui/association/ImportHttpTtsDialog.kt index 26864cc60..60f41eaa9 100644 --- a/app/src/main/java/io/legato/kazusa/ui/association/ImportHttpTtsDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/association/ImportHttpTtsDialog.kt @@ -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.WaitDialog import io.legato.kazusa.utils.GSON +import io.legato.kazusa.utils.gone import io.legato.kazusa.utils.setLayout import io.legato.kazusa.utils.showDialogFragment import io.legato.kazusa.utils.viewbindingdelegate.viewBinding @@ -83,20 +84,20 @@ class ImportHttpTtsDialog() : BaseDialogFragment(R.layout.dialog_recycler_view), upSelectText() } viewModel.errorLiveData.observe(this) { - //binding.rotateLoading.gone() - binding.tvMsg.apply { - text = it + binding.rotateLoading.gone() + binding.emptyView.apply { + setMessage(it) visible() } } viewModel.successLiveData.observe(this) { - //binding.rotateLoading.gone() + binding.rotateLoading.gone() if (it > 0) { adapter.setItems(viewModel.allSources) upSelectText() } else { - binding.tvMsg.apply { - setText(R.string.wrong_format) + binding.emptyView.apply { + setMessage(R.string.wrong_format) visible() } } diff --git a/app/src/main/java/io/legato/kazusa/ui/association/ImportReplaceRuleDialog.kt b/app/src/main/java/io/legato/kazusa/ui/association/ImportReplaceRuleDialog.kt index 017ec95f7..61cc4c7b1 100644 --- a/app/src/main/java/io/legato/kazusa/ui/association/ImportReplaceRuleDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/association/ImportReplaceRuleDialog.kt @@ -88,20 +88,20 @@ class ImportReplaceRuleDialog() : BaseDialogFragment(R.layout.dialog_recycler_vi upSelectText() } viewModel.errorLiveData.observe(this) { - //binding.rotateLoading.gone() - binding.tvMsg.apply { - text = it + binding.rotateLoading.gone() + binding.emptyView.apply { + setMessage(it) visible() } } viewModel.successLiveData.observe(this) { - // binding.rotateLoading.gone() + binding.rotateLoading.gone() if (it > 0) { adapter.setItems(viewModel.allRules) upSelectText() } else { - binding.tvMsg.apply { - setText(R.string.wrong_format) + binding.emptyView.apply { + setMessage(R.string.wrong_format) visible() } } diff --git a/app/src/main/java/io/legato/kazusa/ui/association/ImportRssSourceDialog.kt b/app/src/main/java/io/legato/kazusa/ui/association/ImportRssSourceDialog.kt index 6da6a6768..bbbed284c 100644 --- a/app/src/main/java/io/legato/kazusa/ui/association/ImportRssSourceDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/association/ImportRssSourceDialog.kt @@ -92,20 +92,20 @@ class ImportRssSourceDialog() : BaseDialogFragment(R.layout.dialog_recycler_view upSelectText() } viewModel.errorLiveData.observe(this) { - //binding.rotateLoading.gone() - binding.tvMsg.apply { - text = it + binding.rotateLoading.gone() + binding.emptyView.apply { + setMessage(it) visible() } } viewModel.successLiveData.observe(this) { - //binding.rotateLoading.gone() + binding.rotateLoading.gone() if (it > 0) { adapter.setItems(viewModel.allSources) upSelectText() } else { - binding.tvMsg.apply { - setText(R.string.wrong_format) + binding.emptyView.apply { + setMessage(R.string.wrong_format) visible() } } diff --git a/app/src/main/java/io/legato/kazusa/ui/association/ImportThemeDialog.kt b/app/src/main/java/io/legato/kazusa/ui/association/ImportThemeDialog.kt index d61cbce6d..623120294 100644 --- a/app/src/main/java/io/legato/kazusa/ui/association/ImportThemeDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/association/ImportThemeDialog.kt @@ -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.WaitDialog import io.legato.kazusa.utils.GSON +import io.legato.kazusa.utils.gone import io.legato.kazusa.utils.setLayout import io.legato.kazusa.utils.showDialogFragment import io.legato.kazusa.utils.viewbindingdelegate.viewBinding @@ -82,20 +83,20 @@ class ImportThemeDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_recycl upSelectText() } viewModel.errorLiveData.observe(this) { - //binding.rotateLoading.gone() - binding.tvMsg.apply { - text = it + binding.rotateLoading.gone() + binding.emptyView.apply { + setMessage(it) visible() } } viewModel.successLiveData.observe(this) { - //binding.rotateLoading.gone() + binding.rotateLoading.gone() if (it > 0) { adapter.setItems(viewModel.allSources) upSelectText() } else { - binding.tvMsg.apply { - setText(R.string.wrong_format) + binding.emptyView.apply { + setMessage(R.string.wrong_format) visible() } } diff --git a/app/src/main/java/io/legato/kazusa/ui/association/ImportTxtTocRuleDialog.kt b/app/src/main/java/io/legato/kazusa/ui/association/ImportTxtTocRuleDialog.kt index c3d723a25..664c9d9f7 100644 --- a/app/src/main/java/io/legato/kazusa/ui/association/ImportTxtTocRuleDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/association/ImportTxtTocRuleDialog.kt @@ -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.WaitDialog import io.legato.kazusa.utils.GSON +import io.legato.kazusa.utils.gone import io.legato.kazusa.utils.setLayout import io.legato.kazusa.utils.showDialogFragment import io.legato.kazusa.utils.viewbindingdelegate.viewBinding @@ -82,20 +83,20 @@ class ImportTxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_recycler_vie upSelectText() } viewModel.errorLiveData.observe(this) { - //binding.rotateLoading.gone() - binding.tvMsg.apply { - text = it + binding.rotateLoading.gone() + binding.emptyView.apply { + setMessage(it) visible() } } viewModel.successLiveData.observe(this) { - //binding.rotateLoading.gone() + binding.rotateLoading.gone() if (it > 0) { adapter.setItems(viewModel.allSources) upSelectText() } else { - binding.tvMsg.apply { - setText(R.string.wrong_format) + binding.emptyView.apply { + setMessage(R.string.wrong_format) visible() } } diff --git a/app/src/main/java/io/legato/kazusa/ui/main/explore/ExploreFragment.kt b/app/src/main/java/io/legato/kazusa/ui/main/explore/ExploreFragment.kt index e3e9ffdf2..864d4cccd 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/explore/ExploreFragment.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/explore/ExploreFragment.kt @@ -179,7 +179,7 @@ class ExploreFragment() : VMBaseFragment(R.layout.fragment_exp ).catch { AppLog.put("发现界面更新数据出错", it) }.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) delay(500) } diff --git a/app/src/main/java/io/legato/kazusa/ui/widget/EmptyMessageView.kt b/app/src/main/java/io/legato/kazusa/ui/widget/EmptyMessageView.kt new file mode 100644 index 000000000..06f76460c --- /dev/null +++ b/app/src/main/java/io/legato/kazusa/ui/widget/EmptyMessageView.kt @@ -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() + } +} diff --git a/app/src/main/java/io/legato/kazusa/ui/widget/checkbox/SmoothCheckBox.kt b/app/src/main/java/io/legato/kazusa/ui/widget/checkbox/SmoothCheckBox.kt deleted file mode 100644 index 6b4fe3bf9..000000000 --- a/app/src/main/java/io/legato/kazusa/ui/widget/checkbox/SmoothCheckBox.kt +++ /dev/null @@ -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 - 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) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/io/legato/kazusa/ui/widget/text/PrimaryTextView.kt b/app/src/main/java/io/legato/kazusa/ui/widget/text/PrimaryTextView.kt index fd96104d5..c04c92575 100644 --- a/app/src/main/java/io/legato/kazusa/ui/widget/text/PrimaryTextView.kt +++ b/app/src/main/java/io/legato/kazusa/ui/widget/text/PrimaryTextView.kt @@ -12,7 +12,7 @@ import io.legato.kazusa.lib.theme.ThemeStore class PrimaryTextView(context: Context, attrs: AttributeSet) : AppCompatTextView(context, attrs) { - init { - setTextColor(ThemeStore.textColorPrimary(context)) - } +// init { +// setTextColor(ThemeStore.textColorPrimary(context)) +// } } diff --git a/app/src/main/java/io/legato/kazusa/ui/widget/text/StrokeTextView.kt b/app/src/main/java/io/legato/kazusa/ui/widget/text/StrokeTextView.kt deleted file mode 100644 index 537d057c2..000000000 --- a/app/src/main/java/io/legato/kazusa/ui/widget/text/StrokeTextView.kt +++ /dev/null @@ -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() - ) - } - } - } -} diff --git a/app/src/main/res/layout/activity_import_book.xml b/app/src/main/res/layout/activity_import_book.xml index c602d95b9..21cb2b69a 100644 --- a/app/src/main/res/layout/activity_import_book.xml +++ b/app/src/main/res/layout/activity_import_book.xml @@ -49,6 +49,7 @@ android:id="@+id/refresh_progress_bar" android:layout_width="match_parent" android:layout_height="wrap_content" + android:visibility="gone" android:indeterminate="true" app:layout_constraintTop_toBottomOf="@id/lay_top" /> diff --git a/app/src/main/res/layout/dialog_book_change_source.xml b/app/src/main/res/layout/dialog_book_change_source.xml index afcac27e9..eb0eda643 100644 --- a/app/src/main/res/layout/dialog_book_change_source.xml +++ b/app/src/main/res/layout/dialog_book_change_source.xml @@ -79,29 +79,13 @@ - - - - - - - + app:messageText="还没有源!"/> - + app:messageText="@string/empty"/> diff --git a/app/src/main/res/layout/dialog_select_section_export.xml b/app/src/main/res/layout/dialog_select_section_export.xml index 94e489c50..c3825aab5 100644 --- a/app/src/main/res/layout/dialog_select_section_export.xml +++ b/app/src/main/res/layout/dialog_select_section_export.xml @@ -17,7 +17,7 @@ android:layout_marginTop="12dp" android:orientation="horizontal"> - - + android:layout_height="match_parent" + xmlns:app="http://schemas.android.com/apk/res-auto"> - - - - - + app:messageText="@string/bookshelf_empty"/> diff --git a/app/src/main/res/layout/fragment_explore.xml b/app/src/main/res/layout/fragment_explore.xml index a29339f49..109bed147 100644 --- a/app/src/main/res/layout/fragment_explore.xml +++ b/app/src/main/res/layout/fragment_explore.xml @@ -55,29 +55,16 @@ tools:listitem="@layout/item_find_book" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> - - - - + android:gravity="center" + app:messageText="@string/explore_empty"/> \ No newline at end of file diff --git a/app/src/main/res/values-zh/arrays.xml b/app/src/main/res/values-zh/arrays.xml index a2e7ec2c9..130b427a8 100644 --- a/app/src/main/res/values-zh/arrays.xml +++ b/app/src/main/res/values-zh/arrays.xml @@ -131,4 +131,9 @@ 关闭 + + 全局 + 仅强调色 + + \ No newline at end of file diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index d08309983..33b8d32c6 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -613,7 +613,7 @@ 当前位置: 精准搜索 正在启动服务 - + 内容为空 文件选择 文件夹选择 我是有底线的 @@ -786,7 +786,7 @@ 导入 导出 保存主题配置 - 保存白天主题配置以供调用和分享 + 保存主题配置以供调用和分享 保存夜间主题配置以供调用和分享 主题列表 使用、保存、导入或分享主题 diff --git a/app/src/main/res/values/array_values.xml b/app/src/main/res/values/array_values.xml index eff278840..9962ebce3 100644 --- a/app/src/main/res/values/array_values.xml +++ b/app/src/main/res/values/array_values.xml @@ -39,6 +39,7 @@ 9 10 11 + 12 @@ -75,4 +76,9 @@ off + + global + accent + + \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 3956c1ce1..4379ec222 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -66,6 +66,7 @@ 千禧年 隐海修会 乐队 + 自定义 透明 @@ -163,6 +164,11 @@ Off + + Global + Accent + + BookSource RssSource diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 570ccb408..ea732a5b3 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -254,4 +254,8 @@ + + + +