Skip to content

Commit

Permalink
[修复] 空指针问题
Browse files Browse the repository at this point in the history
[新增] 搜索栏动画
  • Loading branch information
YenalyLiew committed Jul 6, 2024
1 parent b0fa1a9 commit cbf829f
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AlertDialog
import androidx.core.os.BuildCompat.PrereleaseSdkCheck
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
Expand Down Expand Up @@ -45,7 +44,6 @@ class LoginActivity : FrameActivity() {
SystemStatusUtil.fullScreen(window, true)
}

@PrereleaseSdkCheck
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_login)
Expand Down Expand Up @@ -76,6 +74,13 @@ class LoginActivity : FrameActivity() {
binding.srlLogin.autoRefresh()
}

override fun onDestroy() {
super.onDestroy()
binding.wvLogin.removeAllViews()
binding.wvLogin.destroy()
binding.unbind()
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
Expand Down Expand Up @@ -131,8 +136,12 @@ class LoginActivity : FrameActivity() {
description: String?,
failingUrl: String?,
) {
binding.srlLogin.finishRefresh()
dialog.show()
// #issue-146
// #issue-160: 修复字段销毁后调用引发的错误
if (!isDestroyed && !isFinishing) {
binding.srlLogin.finishRefresh()
dialog.show()
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.yenaly.han1meviewer.R
import com.yenaly.han1meviewer.VIDEO_CODE
import com.yenaly.han1meviewer.databinding.ActivityMainBinding
import com.yenaly.han1meviewer.hanimeSpannable
import com.yenaly.han1meviewer.logic.exception.CloudFlareBlockedException
import com.yenaly.han1meviewer.logic.state.WebsiteState
import com.yenaly.han1meviewer.logout
import com.yenaly.han1meviewer.ui.viewmodel.AppViewModel
Expand Down Expand Up @@ -105,6 +106,17 @@ class MainActivity : YenalyActivity<ActivityMainBinding, MainViewModel>() {
}
}
}
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
viewModel.homePageFlow.collect { state ->
if (state is WebsiteState.Error) {
if (state.throwable is CloudFlareBlockedException) {
// TODO: 被屏蔽时的处理
}
}
}
}
}
}

override fun onSupportNavigateUp(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,19 @@ class HanimeDownloadedRvAdapter(private val fragment: DownloadedFragment) :
}
viewHolder.binding.btnDelete.setOnClickListener {
val position = viewHolder.bindingAdapterPosition
val item = getItem(position).notNull()
val file = item.videoUri.toUri().toFile()
context.showAlertDialog {
setTitle(R.string.sure_to_delete)
setMessage(context.getString(R.string.prepare_to_delete_s, file.name))
setPositiveButton(R.string.confirm) { _, _ ->
if (file.exists()) file.delete()
fragment.viewModel.deleteDownloadHanimeBy(item.videoCode, item.quality)
// #issue-158: 这里可能为空
val item = getItem(position)
item?.let {
val file = it.videoUri.toUri().toFile()
context.showAlertDialog {
setTitle(R.string.sure_to_delete)
setMessage(context.getString(R.string.prepare_to_delete_s, file.name))
setPositiveButton(R.string.confirm) { _, _ ->
if (file.exists()) file.delete()
fragment.viewModel.deleteDownloadHanimeBy(it.videoCode, it.quality)
}
setNegativeButton(R.string.cancel, null)
}
setNegativeButton(R.string.cancel, null)
}
}
viewHolder.binding.btnLocalPlayback.setOnClickListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ class VideoColumnTitleAdapter : BaseSingleItemAdapter<Unit, QuickViewHolder> {

private val notifyWhenSet: Boolean

var title: String
var title: String = EMPTY_STRING
set(value) = if (notifyWhenSet) {
field = value
notifyItemChanged(0)
} else field = value

var subtitle: String?
var subtitle: String? = null
set(value) = if (notifyWhenSet) {
field = value
notifyItemChanged(0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,34 +241,37 @@ class HomePageFragment : YenalyFragment<FragmentHomePageBinding, MainViewModel>(
}
}

// #issue-160: 修复字段销毁后调用引发的错误
private fun handlePalette(p: Palette) {
val darkVibrant = p.getDarkVibrantColor(Color.RED)
val lightVibrant = p.getLightVibrantColor(Color.RED)
bindingOrNull?.let { binding ->
val darkVibrant = p.getDarkVibrantColor(Color.RED)
val lightVibrant = p.getLightVibrantColor(Color.RED)

val darkVibrantForContentScrim =
p.darkVibrantSwatch?.rgb ?: p.darkMutedSwatch?.rgb ?: p.lightVibrantSwatch?.rgb
?: p.lightMutedSwatch?.rgb ?: Color.BLACK
binding.collapsingToolbar.setContentScrimColor(darkVibrantForContentScrim)
colorTransition(
fromColor = binding.btnBanner.iconTint.defaultColor,
toColor = darkVibrant
) {
interpolator = animInterpolator
duration = animDuration
addUpdateListener(viewLifecycleOwner.lifecycle) {
val color = it.animatedValue as Int
binding.btnBanner.iconTint = ColorStateList.valueOf(color)
val darkVibrantForContentScrim =
p.darkVibrantSwatch?.rgb ?: p.darkMutedSwatch?.rgb ?: p.lightVibrantSwatch?.rgb
?: p.lightMutedSwatch?.rgb ?: Color.BLACK
binding.collapsingToolbar.setContentScrimColor(darkVibrantForContentScrim)
colorTransition(
fromColor = binding.btnBanner.iconTint.defaultColor,
toColor = darkVibrant
) {
interpolator = animInterpolator
duration = animDuration
addUpdateListener(viewLifecycleOwner.lifecycle) {
val color = it.animatedValue as Int
binding.btnBanner.iconTint = ColorStateList.valueOf(color)
}
}
}
colorTransition(
fromColor = (binding.aColor.background as ColorDrawable).color,
toColor = lightVibrant
) {
interpolator = animInterpolator
duration = animDuration
addUpdateListener(viewLifecycleOwner.lifecycle) {
val color = it.animatedValue as Int
binding.aColor.setBackgroundColor(color)
colorTransition(
fromColor = (binding.aColor.background as ColorDrawable).color,
toColor = lightVibrant
) {
interpolator = animInterpolator
duration = animDuration
addUpdateListener(viewLifecycleOwner.lifecycle) {
val color = it.animatedValue as Int
binding.aColor.setBackgroundColor(color)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package com.yenaly.han1meviewer.ui.view

import android.animation.ValueAnimator
import android.animation.LayoutTransition
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.FrameLayout
import androidx.core.view.updateLayoutParams
import androidx.core.widget.addTextChangedListener
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.recyclerview.widget.LinearLayoutManager
Expand Down Expand Up @@ -42,28 +41,25 @@ class HanimeSearchBar @JvmOverloads constructor(

private val window = checkNotNull(context.activity?.window)

private val searchBar: ViewGroup
private val back: MaterialButton
private val search: MaterialButton
private val tag: MaterialButton
private val rvHistory: RecyclerView
private val etSearch: TextInputEditText
private val root = inflate(context, R.layout.layout_hanime_search_bar, this) as ViewGroup
private val back: MaterialButton = findViewById(R.id.btn_back)
private val search: MaterialButton = findViewById(R.id.btn_search)
private val tag: MaterialButton = findViewById(R.id.btn_tag)
private val rvHistory: RecyclerView = findViewById(R.id.rv_history)
private val etSearch: TextInputEditText = findViewById(R.id.et_search)

/**
* 历史记录是否折叠
*/
private var isCollapsed = true

init {
inflate(context, R.layout.layout_hanime_search_bar, this)
searchBar = findViewById(R.id.search_bar)
back = findViewById(R.id.btn_back)
search = findViewById(R.id.btn_search)
tag = findViewById(R.id.btn_tag)
rvHistory = findViewById(R.id.rv_history)
etSearch = findViewById(R.id.et_search)

// init
root.layoutTransition = LayoutTransition().apply {
enableTransitionType(LayoutTransition.CHANGING)
setDuration(LayoutTransition.CHANGING, animDuration)
setInterpolator(LayoutTransition.CHANGING, animInterpolator)
}
rvHistory.layoutManager = LinearLayoutManager(context)
rvHistory.itemAnimator?.removeDuration = 0
etSearch.setOnEditorActionListener { _, actionId, _ ->
Expand Down Expand Up @@ -152,13 +148,14 @@ class HanimeSearchBar @JvmOverloads constructor(
}

fun showHistory() {
rvHistory.animate()
.setInterpolator(animInterpolator)
.setDuration(animDuration)
.alpha(1F)
.withStartAction { rvHistory.visibility = VISIBLE }
.start()

// val slide = Slide(Gravity.BOTTOM).apply {
// duration = animDuration
// interpolator = animInterpolator
// addTarget(rvHistory)
// }
// TransitionManager.beginDelayedTransition(searchBar, slide)

rvHistory.visibility = View.VISIBLE
back.animate()
.setInterpolator(animInterpolator)
.setDuration(animDuration)
Expand All @@ -168,44 +165,24 @@ class HanimeSearchBar @JvmOverloads constructor(
}

fun hideHistory(): Boolean {
if (!isCollapsed) {
etSearch.hideIme(window)
Log.d("HanimeSearchBar", "History Height: ${rvHistory.height}")
rvHistory.visibility = GONE
back.animate()
.setInterpolator(animInterpolator)
.setDuration(animDuration)
.rotation(0F)
.start()
isCollapsed = true
return true
}
return false
}

private fun View.buildHeightAnimation(
from: Int, to: Int,
): ValueAnimator? {
if (from == to) return null
return ValueAnimator.ofInt(from, to).apply {
duration = animDuration
interpolator = animInterpolator
addUpdateListener {
val value = it.animatedValue as Int
updateLayoutParams {
height = value
}
}
}
}

private fun View.calcHeight(): Int {
val matchParentMeasureSpec =
MeasureSpec.makeMeasureSpec((parent as View).width, MeasureSpec.EXACTLY)
val wrapContentMeasureSpec =
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
measure(matchParentMeasureSpec, wrapContentMeasureSpec)
return measuredHeight
if (isCollapsed) return false
etSearch.hideIme(window)
Log.d("HanimeSearchBar", "History Height: ${rvHistory.height}")
// val slide = Slide(Gravity.TOP).apply {
// duration = animDuration
// interpolator = animInterpolator
// addTarget(rvHistory)
// }
// TransitionManager.beginDelayedTransition(searchBar, slide)

rvHistory.visibility = View.GONE
back.animate()
.setInterpolator(animInterpolator)
.setDuration(animDuration)
.rotation(0F)
.start()
isCollapsed = true
return true
}

// 使用 onBackPressedDispatcher.addCallback 替换
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<!-- Status bar color. -->
<item name="android:statusBarColor">?android:colorBackground</item>
<item name="android:navigationBarColor">?android:colorBackground</item>
<item name="android:windowTranslucentStatus">false</item>
<!-- Customize your theme here. -->
</style>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ abstract class YenalyFragment<DB : ViewDataBinding, VM : ViewModel> @JvmOverload

protected var _binding: DB? = null
val binding get() = _binding!!
val bindingOrNull get() = _binding

lateinit var viewModel: VM

Expand Down

0 comments on commit cbf829f

Please sign in to comment.