Commit a83e8c92 authored by wanglei's avatar wanglei

Merge remote-tracking branch 'origin/master'

parents 13dfc236 e3e7f24f
package com.base.scanqrclear.luma
import android.animation.ValueAnimator
import android.view.View
import android.view.animation.LinearInterpolator
import android.widget.ProgressBar
object AnimationHelps {
fun rotation(view: View, durationTime: Long) {
ValueAnimator.ofFloat(0f, 360f).apply {
duration = durationTime
interpolator = LinearInterpolator()
repeatCount = ValueAnimator.INFINITE
repeatMode = ValueAnimator.RESTART
addUpdateListener { animation ->
val animatedValue = animation.animatedValue as Float
view.rotation = animatedValue
}
}.start()
}
fun progress(progressBar: ProgressBar, start: Int = 0, end: Int = 100, durationTime: Long = 1500) {
ValueAnimator.ofInt(start, end).apply {
duration = durationTime
interpolator = LinearInterpolator()
addUpdateListener { animation ->
progressBar.progress = animation.animatedValue as Int
}
}.start()
}
fun progress(progressBar: CircleProgressBar, endProgress: Int, durationTime: Long = 1500): ValueAnimator {
val animator = ValueAnimator.ofInt(0, endProgress).apply {
duration = durationTime
interpolator = LinearInterpolator()
addUpdateListener { animation ->
val progress = animation.animatedValue as Int
progressBar.setProgress(progress / 100f)
}
}
animator.start()
return animator
}
fun progress(progressBar: MyProgressBar, endProgress: Int, durationTime: Long = 1500, complete: (() -> Unit?)? = null): ValueAnimator {
return progress(progressBar, 0, endProgress, durationTime, complete)
}
fun progress(
progressBar: MyProgressBar,
startProgress: Int,
endProgress: Int,
durationTime: Long = 1500,
complete: (() -> Unit?)? = null
): ValueAnimator {
val animator = ValueAnimator.ofInt(startProgress, endProgress).apply {
duration = durationTime
interpolator = LinearInterpolator()
addUpdateListener { animation ->
val progress = animation.animatedValue as Int
progressBar.setProgress(progress)
if (progress == endProgress) {
complete?.invoke()
}
}
}
animator.start()
return animator
}
}
\ No newline at end of file
package com.base.scanqrclear.luma
import android.os.Bundle
import androidx.fragment.app.Fragment
import com.base.scanqrclear.utils.ActivityLauncher
open class BaseFragment : Fragment() {
protected lateinit var launcher: ActivityLauncher
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
launcher = ActivityLauncher(this)
}
}
\ No newline at end of file
package com.base.scanqrclear.luma
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.base.scanqrclear.R
import com.base.scanqrclear.databinding.ItemFunction2Binding
import com.base.scanqrclear.luma.AppHelps.dpToPx
class FunctionAdapter(
data: List<FunctionBean>,
private val isShowHot: Boolean = false
) : BaseAdapter<FunctionBean, ItemFunction2Binding>(data) {
override fun getViewBinding(
layoutInflater: LayoutInflater,
parent: ViewGroup
): ItemFunction2Binding {
return ItemFunction2Binding.inflate(layoutInflater, parent, false)
}
override fun bind(
holder: BaseViewHolder<ItemFunction2Binding>,
position: Int,
item: FunctionBean
) {
if (!isShowHot) {
val width = holder.itemView.context.resources.displayMetrics.widthPixels
val margin = holder.itemView.context.dpToPx(58).toInt()
val imageWidth = (width - margin) / 3
holder.itemView.layoutParams.width = imageWidth
holder.itemView.layoutParams.height = (imageWidth * 0.85).toInt()
// holder.itemView.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
holder.binding.ivIcon.setImageResource(item.icon)
holder.binding.tvHot.visibility = if (isShowHot && item.name == R.string.junk_scan) View.VISIBLE else View.GONE
val name = holder.itemView.context.getString(item.name)
holder.binding.tvName.text = name
if (item.backgroundId != 0)
holder.itemView.setBackgroundResource(item.backgroundId)
holder.itemView.setOnClickListener { callback?.onClicked(it, position, item) }
}
}
\ No newline at end of file
package com.base.scanqrclear.luma
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.base.scanqrclear.databinding.ItemFunctionMoreBinding
class FunctionMoreAdapter(
data: List<FunctionBean>
) : BaseAdapter<FunctionBean, ItemFunctionMoreBinding>(data) {
override fun getViewBinding(
layoutInflater: LayoutInflater,
parent: ViewGroup
): ItemFunctionMoreBinding {
return ItemFunctionMoreBinding.inflate(layoutInflater, parent, false)
}
override fun bind(
holder: BaseViewHolder<ItemFunctionMoreBinding>,
position: Int,
item: FunctionBean
) {
holder.binding.ivIcon.setImageResource(item.icon)
holder.binding.tvName.setText(item.name)
holder.binding.viewLine.visibility = if (position + 1 == itemCount) View.INVISIBLE else View.VISIBLE
holder.itemView.setOnClickListener { callback?.onClicked(it, position, item) }
}
}
\ No newline at end of file
package com.base.scanqrclear.luma
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import androidx.core.animation.doOnEnd
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.base.scanqrclear.R
import com.base.scanqrclear.databinding.FragmentHomeBinding
import com.base.scanqrclear.luma.AdmobHelps.KEY_INSTALL_TIME
import com.base.scanqrclear.luma.AppHelps.dpToPx
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.TimeUnit
class HomeFragment : BaseFragment() {
private val binding by lazy {
FragmentHomeBinding.inflate(layoutInflater)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val functionAdapter = FunctionAdapter(getData(), true)
functionAdapter.callback = object : BaseAdapter.OnClickCallback<FunctionBean> {
override fun onClicked(view: View, position: Int, item: FunctionBean) {
ActivityJumpHelps.start(requireContext(), launcher, item.name)
}
}
binding.rvFunction.adapter = functionAdapter
binding.rvFunction.layoutManager =
GridLayoutManager(requireContext(), 3, GridLayoutManager.VERTICAL, false)
val functionMoreAdapter = FunctionMoreAdapter(getMoreData())
functionMoreAdapter.callback = object : BaseAdapter.OnClickCallback<FunctionBean> {
override fun onClicked(view: View, position: Int, item: FunctionBean) {
ActivityJumpHelps.start(requireContext(), launcher, item.name)
}
}
binding.rvMore.adapter = functionMoreAdapter
binding.rvMore.layoutManager = LinearLayoutManager(requireContext())
binding.ivShan.setOnClickListener {
ActivityJumpHelps.start(requireContext(), launcher, R.string.junk_scan)
}
binding.tvClean.setOnClickListener {
ActivityJumpHelps.start(requireContext(), launcher, R.string.junk_scan)
}
binding.ivUpward.setOnClickListener {
val targetY = binding.svNested.getChildAt(0).measuredHeight
binding.svNested.smoothScrollTo(0, targetY)
}
startAnimation()
initData()
showDay()
}
private fun initData() {
lifecycleScope.launch(Dispatchers.IO) {
val totalStorage = async { AppHelps.getTotalExternalSize() }
val availableStorage = async { AppHelps.getAvailableExternalSize() }
val totalStorageSize = totalStorage.await()
val availableStorageSize = availableStorage.await()
val usedMemoryStorageSize = totalStorageSize - availableStorageSize
val usedMemoryStorageScale = usedMemoryStorageSize * 100 / totalStorageSize
val totalMemoryUsed = async { AppHelps.getMemTotal(requireContext()) }
val availableMemoryUsed = async { AppHelps.getMemAvailable(requireContext()) }
val totalMemoryUsedSize = totalMemoryUsed.await()
val availableMemoryUsedSize = availableMemoryUsed.await()
val usedMemoryUsedSize = totalMemoryUsedSize - availableMemoryUsedSize
val usedMemoryUsedScale: Long = usedMemoryUsedSize * 100 / totalMemoryUsedSize
withContext(Dispatchers.Main) {
binding.tvStorageUsed.text = "${usedMemoryStorageScale.toInt()}%"
binding.tvMemoryUsed.text = "${usedMemoryUsedScale.toInt()}%"
binding.llStorageUsed.visibility = View.VISIBLE
binding.llMemoryUsed.visibility = View.VISIBLE
AnimationHelps.progress(binding.pbStorageUsed, usedMemoryStorageScale.toInt())
AnimationHelps.progress(binding.pbMemoryUsed, usedMemoryUsedScale.toInt())
}
}
}
private fun showDay() {
val installTime = SpUtils.getInstance().getLong(KEY_INSTALL_TIME)
val result = calculateDaysBetween(installTime, System.currentTimeMillis())
binding.tvDay.text = "${result.toInt()} ${getString(R.string.days)}"
}
fun calculateDaysBetween(timestamp1: Long, timestamp2: Long): Long {
val diffInMillis = Math.abs(timestamp2 - timestamp1)
val diffInDays = TimeUnit.MILLISECONDS.toDays(diffInMillis)
return if (diffInDays < 1) 1 else diffInDays
}
private fun getData(): List<FunctionBean> {
return mutableListOf<FunctionBean>().apply {
add(FunctionBean(R.mipmap.icon_junk_scan_t, R.string.junk_scan))
add(
FunctionBean(
R.mipmap.icon_whatsapp_clean_t,
R.string.whatsapp_clean
)
)
add(FunctionBean(R.mipmap.icon_app_t, R.string.app_process))
}
}
private fun getMoreData(): List<FunctionBean> {
return mutableListOf<FunctionBean>().apply {
add(
FunctionBean(
R.mipmap.icon_screenshots_1,
R.string.screenshot_clean
)
)
add(FunctionBean(R.mipmap.icon_similar, R.string.similar_photos))
}
}
private fun startAnimation() {
binding.ivCircleBorder.visibility = View.GONE
val delay: Long = 1200
ValueAnimator.ofFloat(0f, 360f).apply {
duration = delay
interpolator = LinearInterpolator()
addUpdateListener { animation ->
val animatedValue = animation.animatedValue as Float
binding.ivShan.rotation = animatedValue * 2
}
doOnEnd {
binding.ivCircleBorder.visibility = View.VISIBLE
AnimationHelps.rotation(binding.ivShan, 2000)
}
}.start()
binding.tvJunkFiles.alpha = 0f
ValueAnimator.ofFloat(0f, 1f).apply {
this.duration = 1000
this.startDelay = delay
addUpdateListener { animation ->
val value = animation.animatedValue as Float
binding.tvJunkFiles.alpha = value
binding.tvJunkFiles.translationY = (binding.tvClean.height * (1 - value))
}
start()
}
val scaleXAnim =
ObjectAnimator.ofFloat(binding.ivCircleBorder, "scaleX", 0.85f, 1.35f).apply {
duration = 2000
startDelay = delay
repeatCount = ValueAnimator.INFINITE
repeatMode = ValueAnimator.RESTART
}
val scaleYAnim =
ObjectAnimator.ofFloat(binding.ivCircleBorder, "scaleY", 0.85f, 1.35f).apply {
duration = 2000
startDelay = delay
repeatCount = ValueAnimator.INFINITE
repeatMode = ValueAnimator.RESTART
}
val alphaAnim = ObjectAnimator.ofFloat(binding.ivCircleBorder, "alpha", 0f, 1f).apply {
duration = 2000
startDelay = delay
repeatCount = ValueAnimator.INFINITE
repeatMode = ValueAnimator.RESTART
}
val widthAnim = ObjectAnimator.ofInt(binding.ivCircleBorder, "width", 1, 4).apply {
duration = 2000
startDelay = delay
repeatCount = ValueAnimator.INFINITE
repeatMode = ValueAnimator.RESTART
addUpdateListener { animation ->
val animatedValue = animation.animatedValue as Int
binding.ivCircleBorder.setStrokeWidth(animatedValue)
}
}
val animatorSet = AnimatorSet()
animatorSet.playTogether(scaleXAnim, scaleYAnim, alphaAnim, widthAnim)
animatorSet.start()
val top = requireContext().dpToPx(5)
ObjectAnimator.ofFloat(binding.ivUpward, "translationY", 0f, top).apply {
duration = 1000
repeatCount = ValueAnimator.INFINITE
repeatMode = ValueAnimator.REVERSE
start()
}
}
}
\ No newline at end of file
......@@ -19,6 +19,7 @@ import com.base.scanqrclear.bean.NotificationSendBean.Companion.ACTION_ID_STAY_S
import com.base.scanqrclear.bean.config.AdConfigBean
import com.base.scanqrclear.databinding.ActivityMainBinding
import com.base.scanqrclear.databinding.ItemHomeTabBinding
import com.base.scanqrclear.luma.HomeFragment
import com.base.scanqrclear.qr.CameraUtils
import com.base.scanqrclear.ui.widget.AppExitDialog.showAppExitDialog
import com.base.scanqrclear.ui.widget.NotificationDialog.showNotificationTurnOn
......@@ -41,6 +42,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
HomeTabUIBean(R.drawable.bg_selector_create, getString(R.string.create)),
HomeTabUIBean(R.drawable.bg_selector_scan, getString(R.string.scan)),
HomeTabUIBean(R.drawable.bg_selector_history, getString(R.string.history)),
HomeTabUIBean(R.drawable.bg_selector_clean, getString(R.string.files)),
HomeTabUIBean(R.drawable.bg_selector_settings, getString(R.string.settings)),
)
}
......@@ -61,7 +63,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
SettingsFragment()
}
private val fragments = arrayOf(createFragment, scanFragment, historyFragment, settingFragment)
private val homeFragment by lazy(LazyThreadSafetyMode.NONE) {
HomeFragment()
}
private val fragments = arrayOf(createFragment, scanFragment, historyFragment, homeFragment,settingFragment)
private var pageAdapter: FragmentStateAdapter? = null
......@@ -148,7 +154,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
//https://www.jianshu.com/p/f69bd30cf5b0
//FragmentStateAdapter 这里必须传人fragment
adapter = pageAdapter
offscreenPageLimit = 4
offscreenPageLimit = 5
}
binding.viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
......
package com.base.scanqrclear.utils
import com.base.scanqrclear.R
import com.tool.luma.smart.cleaner.R
enum class ExitType(val title: Int, val content: Int) {
APP_MANAGER(R.string.exit_app_manager, R.string.exit_app_manager_content),
......
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/tob_home" android:state_checked="true"/>
<item android:drawable="@mipmap/tob_home_n" />
<item android:drawable="@mipmap/tab_cleaner_s" android:state_selected="true" />
<item android:drawable="@mipmap/tab_cleaner_n" android:state_selected="false" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/tob_tools_s" android:state_checked="true"/>
<item android:drawable="@mipmap/tob_tools_n" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners android:radius="12dp" />
</shape>
\ No newline at end of file
......@@ -20,6 +20,12 @@
android:name="com.base.scanqrclear.ui.main.HistoryFragment"
android:label="fragment_history"
tools:layout="@layout/fragment_history" />
<fragment
android:id="@+id/homeFragment"
android:name="com.base.scanqrclear.luma.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home" />
<fragment
android:id="@+id/settingsFragment"
android:name="com.base.scanqrclear.ui.main.SettingsFragment"
......
......@@ -122,4 +122,5 @@
<string name="junk_scan">Junk Scan</string>
<string name="whatsapp_clean">WhatsApp Clean</string>
<string name="app_process">App Process</string>
<string name="files">Files</string>
</resources>
\ No newline at end of file
......@@ -122,4 +122,5 @@
<string name="junk_scan">Junk Scan</string>
<string name="whatsapp_clean">WhatsApp Clean</string>
<string name="app_process">App Process</string>
<string name="files">Files</string>
</resources>
\ No newline at end of file
......@@ -123,4 +123,5 @@
<string name="junk_scan">Junk Scan</string>
<string name="whatsapp_clean">WhatsApp Clean</string>
<string name="app_process">App Process</string>
<string name="files">Files</string>
</resources>
\ No newline at end of file
......@@ -122,4 +122,5 @@
<string name="junk_scan">Junk Scan</string>
<string name="whatsapp_clean">WhatsApp Clean</string>
<string name="app_process">App Process</string>
<string name="files">Files</string>
</resources>
\ No newline at end of file
......@@ -123,4 +123,5 @@
<string name="junk_scan">Junk Scan</string>
<string name="whatsapp_clean">WhatsApp Clean</string>
<string name="app_process">App Process</string>
<string name="files">Files</string>
</resources>
\ No newline at end of file
......@@ -117,19 +117,6 @@
<string name="continue_">Continue</string>
<string name="complete">Complete</string>
<string name="files_manager">Files Manager</string>
<string name="storage_used">Storage Used</string>
<string name="memory_used">Memory Used</string>
<string name="junk_files">Junk Files</string>
<string name="hot_tools">Hot Tools</string>
<string name="have_been_with_you_for">Have been with you for</string>
<string name="days">days</string>
<string name="hot">Hot</string>
<string name="screenshot_clean">Screenshot Clean</string>
<string name="similar_photos">Similar Photos</string>
<string name="junk_scan">Junk Scan</string>
<string name="whatsapp_clean">WhatsApp Clean</string>
<string name="app_process">App Process</string>
<string name="junk_scan">Junk Scan</string>
<string name="clean_junk">Clean Junk</string>
......@@ -293,5 +280,6 @@
<string name="initialize_engine">Initialize engine</string>
<string name="device_ready">Device Ready</string>
<string name="loading_point">loading...</string>
<string name="files">Files</string>
</resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment