Commit 8653ab97 authored by jyx's avatar jyx

屏幕适配及添加Base类

parent 5ecf1aaa
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
package="com.mints.cleaner"> package="com.mints.cleaner">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application <application
android:name=".App" android:name=".App"
android:allowBackup="true" android:allowBackup="true"
...@@ -12,15 +13,15 @@ ...@@ -12,15 +13,15 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<!--屏幕适配--> <!--屏幕适配-->
<meta-data <meta-data
android:name="android.max_aspect" android:name="android.max_aspect"
android:value="2.4" /> android:value="2.4" />
<activity android:name=".ui.login.LoginActivity" />
<activity android:name=".ui.SplashActivity">
<activity android:name=".ui.login.LoginActivity"/> </activity>
<activity android:name=".ui.SplashActivity" />
<activity android:name=".ui.MainActivity"> <activity android:name=".ui.MainActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
......
...@@ -3,6 +3,11 @@ package com.mints.cleaner ...@@ -3,6 +3,11 @@ package com.mints.cleaner
import android.app.Application import android.app.Application
import android.content.Context import android.content.Context
import com.mints.cleaner.di.appModule import com.mints.cleaner.di.appModule
import com.mints.core.design_width
import com.mints.core.util.RudenessScreenHelperKt
import com.mints.core.util.SmartBarUtils
import com.mints.cleaner.util.lifecycle.LifeCycleCallBack
import com.mints.cleaner.util.lifecycle.LifeManager
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin import org.koin.core.context.startKoin
import kotlin.properties.Delegates import kotlin.properties.Delegates
...@@ -21,6 +26,21 @@ class App : Application() { ...@@ -21,6 +26,21 @@ class App : Application() {
androidContext(this@App) androidContext(this@App)
modules(appModule) modules(appModule)
} }
// 生命周期
LifeManager().install(this)
// 屏幕适配
initRudenessScreen()
}
/**
* 机型适配
*/
private fun initRudenessScreen() {
val hasSmartBar: Boolean = SmartBarUtils.hasSmartBar(this)
design_width = if (hasSmartBar) 800F else 750F
RudenessScreenHelperKt(this, design_width).activate()
} }
} }
\ No newline at end of file
package com.mints.cleaner.ui package com.mints.cleaner.ui
import androidx.appcompat.app.AppCompatActivity import android.util.Log
import android.os.Bundle
import com.mints.cleaner.R import com.mints.cleaner.R
import com.mints.core.base.BaseActivity
import com.mints.ktx.ext.antiShake
import com.mints.ktx.ext.dp2px
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : BaseActivity() {
override fun getLayoutResId() = R.layout.activity_main
override fun initView() {
btnClick.setOnClickListener {
if (!antiShake(R.id.btnClick)) {
Log.d("AAAAAAAAAAA", "点击了")
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
} }
override fun initData() {
}
} }
\ No newline at end of file
...@@ -17,6 +17,7 @@ class LoginActivity : BaseVMActivity() { ...@@ -17,6 +17,7 @@ class LoginActivity : BaseVMActivity() {
} }
override fun initData() { override fun initData() {
} }
override fun startObserve() { override fun startObserve() {
......
package com.mints.ktx.core.lifecycle package com.mints.cleaner.util.lifecycle
import android.app.Activity import android.app.Activity
import java.util.* import java.util.*
import java.lang.Class import java.lang.Class
object KtxManager { object ActivityManager {
private val mActivityList = LinkedList<Activity>() private val mActivityList = LinkedList<Activity>()
......
package com.mints.ktx.core.lifecycle package com.mints.cleaner.util.lifecycle
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.OnLifecycleEvent
class KtxAppLifeObserver : LifecycleObserver { class AppLifeObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START) @OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onForeground() { fun onForeground() {
......
package com.mints.ktx.core.lifecycle package com.mints.cleaner.util.lifecycle
import android.app.Activity import android.app.Activity
import android.app.Application import android.app.Application
import android.os.Bundle import android.os.Bundle
import com.mints.core.design_width
import com.mints.core.util.RudenessScreenHelperKt
import com.mints.ktx.ext.loge import com.mints.ktx.ext.loge
class KtxLifeCycleCallBack : Application.ActivityLifecycleCallbacks { class LifeCycleCallBack : Application.ActivityLifecycleCallbacks {
companion object {
private val INSTANCE: LifeCycleCallBack by lazy {
LifeCycleCallBack()
}
fun setUpLifecycle(application: Application) {
application.registerActivityLifecycleCallbacks(INSTANCE)
}
}
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
KtxManager.pushActivity(activity) RudenessScreenHelperKt.resetDensity(activity, design_width)
ActivityManager.pushActivity(activity)
"onActivityCreated : ${activity.localClassName}".loge() "onActivityCreated : ${activity.localClassName}".loge()
} }
override fun onActivityStarted(activity: Activity) { override fun onActivityStarted(activity: Activity) {
RudenessScreenHelperKt.resetDensity(activity, design_width)
"onActivityStarted : ${activity.localClassName}".loge() "onActivityStarted : ${activity.localClassName}".loge()
} }
override fun onActivityResumed(activity: Activity) { override fun onActivityResumed(activity: Activity) {
RudenessScreenHelperKt.resetDensity(activity, design_width)
"onActivityResumed : ${activity.localClassName}".loge() "onActivityResumed : ${activity.localClassName}".loge()
} }
...@@ -28,7 +46,7 @@ class KtxLifeCycleCallBack : Application.ActivityLifecycleCallbacks { ...@@ -28,7 +46,7 @@ class KtxLifeCycleCallBack : Application.ActivityLifecycleCallbacks {
override fun onActivityDestroyed(activity: Activity) { override fun onActivityDestroyed(activity: Activity) {
"onActivityDestroyed : ${activity.localClassName}".loge() "onActivityDestroyed : ${activity.localClassName}".loge()
KtxManager.popActivity(activity) ActivityManager.popActivity(activity)
} }
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle?) { override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle?) {
......
package com.mints.ktx.core.lifecycle package com.mints.cleaner.util.lifecycle
import android.os.Handler import android.os.Handler
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
...@@ -6,7 +6,7 @@ import androidx.lifecycle.LifecycleObserver ...@@ -6,7 +6,7 @@ import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.OnLifecycleEvent
class KtxHandler(lifecycleOwner: LifecycleOwner, callback: Callback) : Handler(callback), LifecycleObserver { class LifeHandler(lifecycleOwner: LifecycleOwner, callback: Callback) : Handler(callback), LifecycleObserver {
private val mLifecycleOwner: LifecycleOwner = lifecycleOwner private val mLifecycleOwner: LifecycleOwner = lifecycleOwner
......
package com.mints.cleaner.util.lifecycle
import android.app.Application
import androidx.lifecycle.ProcessLifecycleOwner
class LifeManager {
companion object {
lateinit var app: Application
var watchActivityLife = true
var watchAppLife = true
}
fun install(application: Application) {
app = application
if (watchActivityLife) application.registerActivityLifecycleCallbacks(LifeCycleCallBack())
if (watchAppLife) ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifeObserver())
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/colorAccent"
android:gravity="center"
android:orientation="vertical"
tools:context=".ui.MainActivity"> tools:context=".ui.MainActivity">
<TextView <TextView
android:id="@+id/textView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Hello World!" android:background="#ff0"
app:layout_constraintBottom_toBottomOf="parent" android:text="Hello World!" />
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> <Button
\ No newline at end of file android:id="@+id/btnClick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击" />
</LinearLayout>
\ No newline at end of file
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/colorPrimary"
tools:context="com.mints.cleaner.ui.SplashActivity"> tools:context="com.mints.cleaner.ui.SplashActivity">
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
package com.mints.core
/**
* 默认的屏蔽宽度
*/
var design_width = 750f
package com.mints.core.base package com.mints.core.base
import android.os.Bundle import android.os.Bundle
import android.os.PersistableBundle
import androidx.appcompat.app.AppCompatActivity
abstract class BaseActivity : AppCompatActivity() { /**
* 不使用ViewModel的BaseActivity
*/
abstract class BaseActivity : BaseAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState, persistentState) super.onCreate(savedInstanceState)
setContentView(getLayoutResId()) setContentView(getLayoutResId())
initView() initView()
initData() initData()
} }
abstract fun getLayoutResId(): Int
abstract fun initView() protected abstract fun getLayoutResId(): Int
abstract fun initData() protected abstract fun initView()
protected abstract fun initData()
override fun toggleOverridePendingTransition() = false
override fun getOverridePendingTransitionMode(): TransitionMode? = null
override fun getBundleExtras(extras: Bundle?) {}
override fun isApplyStatusBarTranslucency() = true
override fun toggleIsBack2Left() = false
} }
\ No newline at end of file
package com.mints.core.base
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.MenuItem
import android.view.WindowManager
import com.mints.core.R
import kotlin.properties.Delegates
abstract class BaseAppCompatActivity : TransitionActivity() {
companion object {
var TAG_LOG: String? = null
}
var savedInstanceState: Bundle? = null
var mContext: Context by Delegates.notNull()
/**
* Screen information
*/
protected var mScreenWidth = 0
protected var mScreenHeight = 0
protected var mScreenDensity = 0.0f
enum class TransitionMode {
LEFT,
RIGHT,
TOP,
BOTTOM,
SCALE,
FADE
}
override fun onCreate(savedInstanceState: Bundle?) {
// 界面从哪个位置弹出
if (toggleOverridePendingTransition()) {
getOverridePendingTransitionMode()?.let {
when (it) {
TransitionMode.LEFT -> overridePendingTransition(
R.anim.left_in,
R.anim.left_out
)
TransitionMode.RIGHT -> overridePendingTransition(
R.anim.right_in,
R.anim.right_out
)
TransitionMode.TOP -> overridePendingTransition(
R.anim.top_in,
R.anim.top_out
)
TransitionMode.BOTTOM -> overridePendingTransition(
R.anim.push_bottom_in,
R.anim.push_bottom_out
)
TransitionMode.SCALE -> overridePendingTransition(
R.anim.scale_in,
R.anim.scale_out
)
TransitionMode.FADE -> overridePendingTransition(
R.anim.fade_in,
R.anim.fade_out
)
}
}
}
this.savedInstanceState = savedInstanceState
super.onCreate(savedInstanceState)
// base extras
intent.extras?.let { getBundleExtras(it) }
setTranslucentStatus(isApplyStatusBarTranslucency())
mContext = this
TAG_LOG = javaClass.simpleName
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
displayMetrics.run {
mScreenDensity = density
mScreenHeight = heightPixels
mScreenWidth = widthPixels
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (item.itemId == android.R.id.home) {
finish()
true
} else
super.onOptionsItemSelected(item)
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
override fun onDestroy() {
super.onDestroy()
}
/**
* toggle overridePendingTransition
*
* @return
*/
protected abstract fun toggleOverridePendingTransition(): Boolean
/**
* get the overridePendingTransition mode
*/
protected abstract fun getOverridePendingTransitionMode(): TransitionMode?
/**
* get bundle data
*
* @param extras
*/
protected abstract fun getBundleExtras(extras: Bundle?)
/**
* is applyStatusBarTranslucency
*
* @return
*/
protected abstract fun isApplyStatusBarTranslucency(): Boolean
/**
* set status bar translucency
*
* @param on
*/
protected open fun setTranslucentStatus(on: Boolean) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val win = window
val winParams = win.attributes
val bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
if (on) {
winParams.flags = winParams.flags or bits
} else {
winParams.flags = winParams.flags and bits.inv()
}
win.attributes = winParams
}
}
}
\ No newline at end of file
package com.mints.core.base
import android.content.Context
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import com.mints.core.design_width
import com.mints.core.util.RudenessScreenHelperKt
import kotlin.properties.Delegates
abstract class BaseAppFragment : TransitionFragment {
constructor(layoutId: Int) : super(layoutId)
constructor() : super()
companion object {
/**
* Log tag
*/
protected lateinit var TAG_LOG: String
}
/**
* Screen information
*/
protected var mScreenWidth = 0
protected var mScreenHeight = 0
protected var mScreenDensity = 0.0f
var mContext: Context by Delegates.notNull()
override fun onAttach(context: Context) {
super.onAttach(context)
mContext = context
RudenessScreenHelperKt.resetDensity(activity, design_width)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
TAG_LOG = javaClass.simpleName
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return if (getContentViewLayoutID() != 0) {
inflater.inflate(getContentViewLayoutID(), null)
} else
super.onCreateView(inflater, container, savedInstanceState)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val displayMetrics = DisplayMetrics()
activity?.let {
it.windowManager.defaultDisplay.getMetrics(displayMetrics)
RudenessScreenHelperKt.resetDensity(activity, design_width)
mScreenDensity = displayMetrics.density
mScreenHeight = displayMetrics.heightPixels
mScreenWidth = displayMetrics.widthPixels
}
}
override fun onDetach() {
super.onDetach()
// for bug ---> java.lang.IllegalStateException: Activity has been destroyed
try {
val childFragmentManager =
Fragment::class.java.getDeclaredField("mChildFragmentManager")
childFragmentManager.isAccessible = true
childFragmentManager[this] = null
} catch (e: NoSuchFieldException) {
throw RuntimeException(e)
} catch (e: IllegalAccessException) {
throw RuntimeException(e)
}
}
/**
* get the support fragment manager
*
* @return
*/
protected open fun getSupportFragmentManager(): FragmentManager? {
return requireActivity().supportFragmentManager
}
/**
* bind layout resource file
*
* @return id of layout resource
*/
protected abstract fun getContentViewLayoutID(): Int
override fun toggleIsBack2Left(): Boolean {
return false
}
}
\ No newline at end of file
...@@ -4,9 +4,12 @@ import android.os.Bundle ...@@ -4,9 +4,12 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment
abstract class BaseFragment : Fragment() { /**
* 不使用ViewModel的BaseFragment
*/
abstract class BaseFragment : BaseAppFragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
......
...@@ -2,18 +2,22 @@ package com.mints.core.base ...@@ -2,18 +2,22 @@ package com.mints.core.base
import android.os.Bundle import android.os.Bundle
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding import androidx.databinding.ViewDataBinding
abstract class BaseVMActivity : AppCompatActivity() { /**
* 使用ViewModel及DataBinding
*/
abstract class BaseVMActivity : BaseAppCompatActivity() {
// dataBinding 绑定当前activity // dataBinding 绑定当前activity
protected inline fun <reified T : ViewDataBinding> binding( protected inline fun <reified T : ViewDataBinding> binding(
@LayoutRes resId: Int @LayoutRes resId: Int
): Lazy<T> = lazy { DataBindingUtil.setContentView<T>(this, resId).apply { ): Lazy<T> = lazy {
lifecycleOwner = this@BaseVMActivity DataBindingUtil.setContentView<T>(this, resId).apply {
} } lifecycleOwner = this@BaseVMActivity
}
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -25,4 +29,14 @@ abstract class BaseVMActivity : AppCompatActivity() { ...@@ -25,4 +29,14 @@ abstract class BaseVMActivity : AppCompatActivity() {
abstract fun initView() abstract fun initView()
abstract fun initData() abstract fun initData()
abstract fun startObserve() abstract fun startObserve()
override fun toggleOverridePendingTransition() = false
override fun getOverridePendingTransitionMode(): TransitionMode? = null
override fun getBundleExtras(extras: Bundle?) {}
override fun isApplyStatusBarTranslucency() = true
override fun toggleIsBack2Left() = false
} }
\ No newline at end of file
...@@ -9,8 +9,11 @@ import androidx.databinding.DataBindingUtil ...@@ -9,8 +9,11 @@ import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
/**
* 使用ViewModel及DataBinding
*/
abstract class BaseVMFragment<T : ViewDataBinding>(@LayoutRes val layoutId: Int) : abstract class BaseVMFragment<T : ViewDataBinding>(@LayoutRes val layoutId: Int) :
Fragment(layoutId) { BaseAppFragment(layoutId) {
lateinit var binding: T lateinit var binding: T
......
package com.mints.core.base
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import com.mints.core.R
abstract class TransitionActivity : AppCompatActivity() {
override fun startActivity(intent: Intent?) {
super.startActivity(intent)
if (toggleIsBack2Left()) {
setTransitionAnimation(false)
} else {
setTransitionAnimation(true)
}
}
override fun startActivityForResult(intent: Intent?, requestCode: Int) {
super.startActivityForResult(intent, requestCode)
/*
judge is the previous page from left to right
*/
if (toggleIsBack2Left()) {
setTransitionAnimation(false)
} else {
setTransitionAnimation(true)
}
}
override fun finish() {
super.finish()
if (toggleIsBack2Left()) {
setTransitionAnimation(true)
} else {
setTransitionAnimation(false)
}
}
/**
* finish from left
*/
protected open fun finish2Left() {
super.finish()
setTransitionAnimation(false)
}
/**
* finish from right
*/
protected open fun finish2Right() {
super.finish()
setTransitionAnimation(true)
}
/**
* finish normal
*/
protected open fun finish2Normal() {
super.finish()
}
/**
* toggle is back to left
*/
protected abstract fun toggleIsBack2Left(): Boolean
/**
* change activity transition animation
*
* @param newActivityIn
*/
private fun setTransitionAnimation(newActivityIn: Boolean) {
if (newActivityIn) {
// 新页面从右边进入 <---
overridePendingTransition(
R.anim.right_in,
R.anim.right_out
)
} else {
// 上一个页面从左边进入 --->
overridePendingTransition(
R.anim.left_in,
R.anim.left_out
)
}
}
}
\ No newline at end of file
package com.mints.core.base
import android.content.Intent
import androidx.fragment.app.Fragment
import com.mints.core.R
abstract class TransitionFragment : Fragment {
constructor(layoutId: Int) : super(layoutId)
constructor() : super()
override fun startActivity(intent: Intent?) {
super.startActivity(intent)
/*
judge is the previous page from left to right
*/
if (!toggleIsBack2Left()) {
setTransitionAnimation(true)
} else {
setTransitionAnimation(false)
}
}
override fun startActivityForResult(intent: Intent?, requestCode: Int) {
super.startActivityForResult(intent, requestCode)
/*
judge is the previous page from left to right
*/
if (!toggleIsBack2Left()) {
setTransitionAnimation(true)
} else {
setTransitionAnimation(false)
}
}
/**
* toggle is back to left
*/
protected abstract fun toggleIsBack2Left(): Boolean
/**
* change activity transition animation
*
* @param newActivityIn
*/
private fun setTransitionAnimation(newActivityIn: Boolean) {
if (newActivityIn) {
// 新页面从右边进入
activity?.let {
it.overridePendingTransition(
R.anim.right_in,
R.anim.right_out
)
}
} else {
// 上一个页面从左边进入
activity?.let {
it.overridePendingTransition(
R.anim.left_in,
R.anim.left_out
)
}
}
}
}
\ No newline at end of file
package com.mints.core.util
import android.app.Application
import android.content.Context
import android.content.res.Resources
import android.graphics.Point
import android.util.DisplayMetrics
import android.view.WindowManager
class RudenessScreenHelperKt
/**
* @param application application
* @param width 设计稿宽度
*/(application: Application, width: Float) {
private var mApplication: Application? = application
private var designWidth = width
companion object {
/**
* 重新计算displayMetrics.xhdpi, 使单位pt重定义为设计稿的相对长度
*
* @param context
* @param designWidth 设计稿的宽度
* @see .activate
*/
fun resetDensity(
context: Context?,
designWidth: Float
) {
if (context == null) return
val size = Point()
(context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
.getSize(size)
val resources = context.resources
val displayMetrics = resources.displayMetrics
displayMetrics.xdpi = size.x / designWidth * 72f
val metrics = getMetricsOnMiui(context.resources)
if (metrics != null) metrics.xdpi = size.x / designWidth * 72f
}
/**
* 恢复displayMetrics为系统原生状态,单位pt恢复为长度单位磅
*
* @param context
* @see .inactivate
*/
fun restoreDensity(context: Context) {
context.resources.displayMetrics.setToDefaults()
val metrics = getMetricsOnMiui(context.resources)
metrics?.setToDefaults()
}
//解决MIUI更改框架导致的MIUI7+Android5.1.1上出现的失效问题(以及极少数基于这部分miui去掉art然后置入xposed的手机)
private fun getMetricsOnMiui(resources: Resources): DisplayMetrics? {
return if ("MiuiResources" == resources.javaClass.simpleName || "XResources" == resources.javaClass.simpleName) {
try {
val field =
Resources::class.java.getDeclaredField("mTmpMetrics")
field.isAccessible = true
field[resources] as DisplayMetrics
} catch (e: Exception) {
null
}
} else null
}
}
/**
* 激活本方案
*/
fun activate() {
resetDensity(mApplication, designWidth)
}
/**
* 恢复系统原生方案
*/
fun inactivate() {
mApplication?.let { restoreDensity(it) }
}
}
\ No newline at end of file
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromYDelta="100%p"
android:toYDelta="0" />
<alpha
android:duration="750"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="750"
android:fromYDelta="0"
android:toYDelta="100%p" />
<alpha
android:duration="300"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015 [1076559197@qq.com | tchen0707@gmail.com]
~
~ Licensed under the Apache License, Version 2.0 (the "License”);
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<alpha
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015 [1076559197@qq.com | tchen0707@gmail.com]
~
~ Licensed under the Apache License, Version 2.0 (the "License”);
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<alpha
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
author:Remex Huang
website:feelyou.info
-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="-100%p"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="0" >
</translate>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
author:Remex Huang
website:feelyou.info
-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="100%p"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="0" >
</translate>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (c) 2015 [1076559197@qq.com | tchen0707@gmail.com]
~
~ Licensed under the Apache License, Version 2.0 (the "License”);
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="-100%p"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toXDelta="0" />
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (c) 2015 [1076559197@qq.com | tchen0707@gmail.com]
~
~ Licensed under the Apache License, Version 2.0 (the "License”);
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toXDelta="100%p" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
author:Remex Huang
website:feelyou.info
-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="-100%p"
android:toYDelta="0" >
</translate>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
author:Remex Huang
website:feelyou.info
-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%p"
android:toYDelta="0" >
</translate>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromYDelta="100%p"
android:toYDelta="0" />
<alpha
android:duration="200"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromYDelta="0"
android:toYDelta="50%p" />
<alpha
android:duration="200"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015 [1076559197@qq.com | tchen0707@gmail.com]
~
~ Licensed under the Apache License, Version 2.0 (the "License”);
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXDelta="100%p"
android:toXDelta="0"/>
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (c) 2015 [1076559197@qq.com | tchen0707@gmail.com]
~
~ Licensed under the Apache License, Version 2.0 (the "License”);
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toXDelta="-100%p" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (c) 2015 [1076559197@qq.com | tchen0707@gmail.com]
~
~ Licensed under the Apache License, Version 2.0 (the "License”);
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fillAfter="false"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (c) 2015 [1076559197@qq.com | tchen0707@gmail.com]
~
~ Licensed under the Apache License, Version 2.0 (the "License”);
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromAlpha="1.0"
android:toAlpha="0" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015 [1076559197@qq.com | tchen0707@gmail.com]
~
~ Licensed under the Apache License, Version 2.0 (the "License”);
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromYDelta="-100%p"
android:toYDelta="0"/>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015 [1076559197@qq.com | tchen0707@gmail.com]
~
~ Licensed under the Apache License, Version 2.0 (the "License”);
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromYDelta="0"
android:toYDelta="-100%p"/>
...@@ -5,31 +5,19 @@ import android.content.ContentProvider ...@@ -5,31 +5,19 @@ import android.content.ContentProvider
import android.content.ContentValues import android.content.ContentValues
import android.database.Cursor import android.database.Cursor
import android.net.Uri import android.net.Uri
import androidx.lifecycle.ProcessLifecycleOwner
import com.mints.ktx.core.lifecycle.KtxLifeCycleCallBack
import com.mints.ktx.core.lifecycle.KtxAppLifeObserver
class Ktx : ContentProvider() { class Ktx : ContentProvider() {
companion object { companion object {
lateinit var app: Application lateinit var app: Application
var watchActivityLife = true
var watchAppLife = false
} }
override fun onCreate(): Boolean { override fun onCreate(): Boolean {
val application = context!!.applicationContext as Application val application = context!!.applicationContext as Application
install(application)
return true return true
} }
private fun install(application: Application) {
app = application
if (watchActivityLife) application.registerActivityLifecycleCallbacks(KtxLifeCycleCallBack())
if (watchAppLife) ProcessLifecycleOwner.get().lifecycle.addObserver(KtxAppLifeObserver())
}
override fun insert(uri: Uri, values: ContentValues?): Uri? = null override fun insert(uri: Uri, values: ContentValues?): Uri? = null
override fun query( override fun query(
...@@ -41,7 +29,12 @@ class Ktx : ContentProvider() { ...@@ -41,7 +29,12 @@ class Ktx : ContentProvider() {
): Cursor? = null ): Cursor? = null
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int = 0 override fun update(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array<String>?
): Int = 0
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int = 0 override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int = 0
......
package com.mints.ktx.core.util.nodoubleclick
import java.util.*
class LimitQueue<E> {
private var limitedSize = 0
private val linkedList: LinkedList<E> = LinkedList<E>()
constructor(size: Int) {
limitedSize = size
}
fun offer(e: E) {
if (linkedList.size >= limitedSize) {
linkedList.poll()
}
linkedList.offer(e)
}
operator fun get(position: Int): E? {
return linkedList[position]
}
fun getLast(): E? {
return linkedList.last
}
fun getFirst(): E? {
return linkedList.first
}
fun getLimit(): Int {
return limitedSize
}
fun setLimitedSize(size: Int) {
limitedSize = size
}
fun size(): Int {
return linkedList.size
}
fun getArrayList(): ArrayList<E>? {
val arrayList: ArrayList<E> = ArrayList()
for (i in linkedList.indices) {
arrayList.add(linkedList[i])
}
return arrayList
}
override fun toString(): String {
val buffer = StringBuilder()
for (i in linkedList.indices) {
buffer.append(linkedList[i])
buffer.append(" ")
}
return buffer.toString()
}
}
\ No newline at end of file
package com.mints.ktx.core.util.nodoubleclick
import java.util.*
class OneClick {
private var methodName: String? = null
private val CLICK_DELAY_TIME = 2000
private var lastClickTime: Long = 0
constructor(methodName: String?) {
this.methodName = methodName
}
fun getMethodName(): String? {
return methodName
}
fun check(): Boolean {
val currentTime = Calendar.getInstance().timeInMillis
return if (currentTime - lastClickTime > CLICK_DELAY_TIME) {
lastClickTime = currentTime
false
} else {
true
}
}
}
\ No newline at end of file
package com.mints.ktx.ext
import com.mints.ktx.core.util.nodoubleclick.LimitQueue
import com.mints.ktx.core.util.nodoubleclick.OneClick
private val queue: LimitQueue<OneClick> = LimitQueue(20)
/**
* if (View is doubleClick) return true
* else return false
*/
fun antiShake(any: Any?): Boolean {
val flag: String = any?.toString() ?: Thread.currentThread().stackTrace[2].methodName
for (util in queue.getArrayList()!!) {
if (util.getMethodName().equals(flag)) {
return util.check()
}
}
val clickUtil = OneClick(flag)
queue.offer(clickUtil)
return clickUtil.check()
}
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