finish the push func

This commit is contained in:
zhongchao
2021-09-24 15:12:55 +08:00
parent 13dc01c0b7
commit fd02392b97
16 changed files with 1119 additions and 355 deletions

View File

@@ -79,11 +79,6 @@ public class PushModuleProvider implements IMogoModuleProvider {
@Override
public void init(final Context context) {
HandlerUtils.INSTANCE.getMBgHandler().post(new Runnable() {
@Override
public void run() {
PushRepository.Companion.init(context);
}
});
HandlerUtils.INSTANCE.getMBgHandler().post(() -> PushRepository.Companion.init(context));
}
}

View File

@@ -123,7 +123,9 @@ class PushRepository(mContext: Context) {
} else {
return
}
iterateNext()
mHandler.post {
iterateNext()
}
}
}

View File

@@ -1,22 +1,15 @@
package com.mogo.module.push.view
import android.animation.Animator
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.PixelFormat
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.view.*
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.Scroller
import android.widget.TextView
import androidx.annotation.LayoutRes
import androidx.core.animation.doOnEnd
import androidx.core.view.isVisible
import com.elegant.analytics.utils.Logger
import com.mogo.commons.context.ContextHolderUtil
import com.mogo.commons.voice.AIAssist
import com.mogo.module.push.Config
import com.mogo.module.push.R
@@ -27,14 +20,15 @@ import com.mogo.module.push.view.roundimage.RoundedImageView
import com.mogo.module.push.viewmodel.PushViewModel
import com.mogo.service.windowview.IMogoTopViewManager
import com.mogo.service.windowview.IMogoTopViewStatusListener
import com.mogo.utils.ResourcesHelper
import com.mogo.utils.ThreadPoolService
import com.mogo.utils.UiThreadHandler
import com.mogo.utils.glide.GlideApp
import com.mogo.utils.logger.Logger
import kotlin.math.log
class FloatView constructor(
private val pushViewModel: PushViewModel,
private val context: Context
private val pushViewModel: PushViewModel,
private val context: Context
) {
companion object {
@@ -46,44 +40,37 @@ class FloatView constructor(
interface PushViewController {
fun show(bean: PushBean?)
fun hide()
fun timer(time: Int)
fun inflateView(@LayoutRes layoutId: Int)
}
abstract inner class PushView(context: Context) : FrameLayout(context),
PushViewController {
private lateinit var appIcon: ImageView
PushViewController {
private lateinit var titleIconContainer: View
private lateinit var pushTitle: TextView
private lateinit var pushImage: RoundedImageView
private lateinit var pushContent: TextView
private lateinit var pushTimer: TextView
private lateinit var pushButtonLeft: TextView
private lateinit var pushButtonRight: TextView
lateinit var pushButton: View
private lateinit var pushCheck: TextView
private var pushData: PushBean? = null
override fun inflateView(layoutId: Int) {
LayoutInflater.from(context).inflate(layoutId, this, true)
appIcon = findViewById(R.id.module_push_app_icon)
pushTitle = findViewById(R.id.module_push_title)
pushCheck = findViewById(R.id.module_push_check)
pushImage = findViewById(R.id.module_push_image)
pushContent = findViewById(R.id.module_push_content)
pushButtonLeft = findViewById(R.id.module_push_button_left)
pushButtonRight = findViewById(R.id.module_push_button_right)
pushTimer = findViewById(R.id.module_push_timer)
titleIconContainer = findViewById(R.id.module_push_app_icon_title)
pushButton = findViewById(R.id.module_push_buttons)
setOnClickListener {
pushViewModel.dealCmd(PushViewModel.VOICE_ACTION_PUSH_MAIN, "1")
turnNextMessage()
}
pushButtonLeft.setOnClickListener {
pushViewModel.dealCmd(PushViewModel.VOICE_ACTION_PUSH_LEFT, "1")
turnNextMessage()
}
pushButtonRight.setOnClickListener {
pushViewModel.dealCmd(PushViewModel.VOICE_ACTION_PUSH_RIGHT, "1")
turnNextMessage()
pushCheck.setOnClickListener {
pushData?.let {
if (pushCheckDialog == null) {
pushCheckDialog = PushCheckDialog(ContextHolderUtil.getContext())
}
pushCheckDialog!!.showCheckDialog(it.title, it.content)
}
}
}
@@ -94,35 +81,11 @@ class FloatView constructor(
}
}
fun hasButtons(bean: PushBean?): Boolean {
bean?.buttons?.forEach {
if (it.text.isNotEmpty()) {
return true
}
}
return false
}
fun hasTextContent(bean: PushBean?): Boolean =
bean?.content?.isEmpty()?.not() ?: false
fun hasImgContent(bean: PushBean?): Boolean = bean?.QRCode?.isEmpty()?.not() ?: false
open fun setBean(bean: PushBean) {
// app icon
if (bean.appIcon.isNotEmpty()) {
appIcon.visible()
GlideApp.with(this).load(bean.appIcon).into(appIcon)
} else {
appIcon.gone()
}
pushData = bean
// title
pushTitle.text = bean.title
// decrease timer
pushTimer.text = if (bean.showTimeout > 99) "" else "${bean.showTimeout}s"
// image
if (bean.imageUrl.isEmpty() && bean.QRCode.isEmpty()) {
pushImage.gone()
@@ -140,9 +103,9 @@ class FloatView constructor(
pushImage.layoutParams = params
ThreadPoolService.execute {
val bmp = stringConverterBitmap(
bean.QRCode,
getQrImgWidth(),
getQrImgHeight()
bean.QRCode,
getQrImgWidth(),
getQrImgHeight()
)
UiThreadHandler.post {
pushImage.setImageBitmap(bmp)
@@ -151,22 +114,6 @@ class FloatView constructor(
}
}
// button
pushButton.gone()
pushButtonLeft.gone()
pushButtonRight.gone()
if (!bean.buttons.isNullOrEmpty()) {
if (bean.buttons[0].text.isNotEmpty()) {
pushButton.visible()
pushButtonLeft.text = bean.buttons[0].text
pushButtonLeft.visible()
}
if (bean.buttons.size > 1 && bean.buttons[1].text.isNotEmpty()) {
pushButtonRight.text = bean.buttons[1].text
pushButtonRight.visible()
}
}
// content
if (bean.content.isEmpty()) {
pushContent.gone()
@@ -186,12 +133,6 @@ class FloatView constructor(
abstract fun getQrImgWidth(): Int
abstract fun getQrImgHeight(): Int
@SuppressLint("SetTextI18n")
override fun timer(time: Int) {
Logger.d(TAG, "time = $time")
pushTimer.text = "${time}s"
}
override fun show(bean: PushBean?) {
isAddWindow = true
uiHandler.removeCallbacks(delayClosePush)
@@ -252,184 +193,175 @@ class FloatView constructor(
}
override fun getImgWidth(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_width)
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_width)
override fun getImgHeight(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height)
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height)
override fun getQrImgWidth(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height)
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height)
override fun getQrImgHeight(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height)
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height)
}
inner class PushViewInWindowView(context: Context) : PushView(context), View.OnTouchListener {
private val mContentContainer: View
private val mWindowManager =
context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
private val params = WindowManager.LayoutParams()
init {
@Suppress("DEPRECATION")
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
params.flags = (WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
or WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE
or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
params.width = WindowManager.LayoutParams.WRAP_CONTENT
params.height = WindowManager.LayoutParams.WRAP_CONTENT
params.gravity = Gravity.START or Gravity.BOTTOM
params.format = PixelFormat.TRANSLUCENT
params.x = context.resources.getDimensionPixelSize(R.dimen.module_push_window_x)
params.y = context.resources.getDimensionPixelSize(R.dimen.module_push_window_x)
if (Build.VERSION.SDK_INT > 25) {
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
}
inflateView(R.layout.module_push_item_vertical)
mContentContainer = findViewById(R.id.module_push_content_container)
setOnTouchListener(this)
}
override fun show(bean: PushBean?) {
super.show(bean)
mLastVisibleType = TYPE_WINDOW_MANAGER
setBean(bean!!)
try {
mWindowManager.addView(this, params)
} catch (e: Exception) {
mWindowManager.updateViewLayout(this, params)
}
translationXAnimation(
-ResourcesHelper.getDimension(context, R.dimen.module_push_ui_width_vertical),
0f
) {
if (pushViewModel.pushBean != null) {
startClosePush()
}
}
}
private fun translationXAnimation(
from: Float,
to: Float,
doOnEnd: (animator: Animator) -> Unit
) {
val transitionXAnimator: ObjectAnimator =
ObjectAnimator.ofFloat(
this,
View.TRANSLATION_X,
from,
to
)
transitionXAnimator.duration = 200
transitionXAnimator.doOnEnd(doOnEnd)
transitionXAnimator.start()
}
override fun setBean(bean: PushBean) {
super.setBean(bean)
var paddingBottom = 0
if (pushButton.isVisible) {
paddingBottom =
context.resources.getDimensionPixelSize(R.dimen.module_push_content_paddingBottom_vertical)
}
mContentContainer.setPadding(0, 0, 0, paddingBottom)
}
override fun hide() {
super.hide()
translationXAnimation(
this.x,
-ResourcesHelper.getDimension(context, R.dimen.module_push_ui_width_vertical)
) {
Logger.d(TAG, "here")
this.x = 0f
mWindowManager.removeViewImmediate(this)
}
}
override fun onTouch(v: View?, ev: MotionEvent?): Boolean {
if (mLastVisibleType != TYPE_WINDOW_MANAGER) {
return false
}
when (ev?.action) {
MotionEvent.ACTION_DOWN -> {
needInterceptClick = false
startX = ev.x
}
MotionEvent.ACTION_MOVE -> {
moveX = startX - ev.x
scrollBy(moveX.toInt(), 0)
startX = ev.x
if (scrollX < 0) {
scrollTo(0, 0)
}
if (!needInterceptClick && scrollX > 20) {
needInterceptClick = true
}
invalidate()
}
MotionEvent.ACTION_UP -> {
if (scrollX > 0) {
mScroller.startScroll(scrollX, 0, width - scrollX, 0)
invalidate()
return true
}
if (needInterceptClick) {
return true
}
}
else -> {
startX = 0f
moveX = 0f
}
}
return false
}
override fun computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.currX, mScroller.currY)
invalidate()
} else {
if (mScroller.currX == 0) {
return
}
mScroller.finalX = 0
removeCallbacks(delayClosePush)
if (isAddWindow) {
if (currentBean != null) {
AnalyticsUtils.track(Config.NEWS_CARD_SWIPE, "trigger_type", "1")
}
mWindowManager.removeView(this)
isAddWindow = false
}
pushViewModel.pushBean?.showTimeout = 0
updateTimer()
}
}
override fun getImgWidth(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_width_vertical)
override fun getImgHeight(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height_vertical)
override fun getQrImgWidth(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_image_qr_size_vertical)
override fun getQrImgHeight(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_image_qr_size_vertical)
}
// inner class PushViewInWindowView(context: Context) : PushView(context), View.OnTouchListener {
//
// private val mContentContainer: View
// private val mWindowManager =
// context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
//
// private val params = WindowManager.LayoutParams()
//
// init {
//
// @Suppress("DEPRECATION")
// params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
// params.flags = (WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
// or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
// or WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE
// or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
// or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
// params.width = WindowManager.LayoutParams.WRAP_CONTENT
// params.height = WindowManager.LayoutParams.WRAP_CONTENT
// params.gravity = Gravity.START or Gravity.BOTTOM
// params.format = PixelFormat.TRANSLUCENT
// params.x = context.resources.getDimensionPixelSize(R.dimen.module_push_window_x)
// params.y = context.resources.getDimensionPixelSize(R.dimen.module_push_window_x)
// if (Build.VERSION.SDK_INT > 25) {
// params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
// }
//
// inflateView(R.layout.module_push_item_vertical)
// mContentContainer = findViewById(R.id.module_push_content_container)
// setOnTouchListener(this)
// }
//
// override fun show(bean: PushBean?) {
// super.show(bean)
// mLastVisibleType = TYPE_WINDOW_MANAGER
// setBean(bean!!)
//
// try {
// mWindowManager.addView(this, params)
// } catch (e: Exception) {
// mWindowManager.updateViewLayout(this, params)
// }
// translationXAnimation(
// -ResourcesHelper.getDimension(context, R.dimen.module_push_ui_width_vertical),
// 0f
// ) {
// if (pushViewModel.pushBean != null) {
// startClosePush()
// }
// }
// }
//
// private fun translationXAnimation(
// from: Float,
// to: Float,
// doOnEnd: (animator: Animator) -> Unit
// ) {
// val transitionXAnimator: ObjectAnimator =
// ObjectAnimator.ofFloat(
// this,
// View.TRANSLATION_X,
// from,
// to
// )
// transitionXAnimator.duration = 200
// transitionXAnimator.doOnEnd(doOnEnd)
// transitionXAnimator.start()
// }
//
// override fun hide() {
// super.hide()
// translationXAnimation(
// this.x,
// -ResourcesHelper.getDimension(context, R.dimen.module_push_ui_width_vertical)
// ) {
// Logger.d(TAG, "here")
// this.x = 0f
// mWindowManager.removeViewImmediate(this)
// }
// }
//
// override fun onTouch(v: View?, ev: MotionEvent?): Boolean {
//
// if (mLastVisibleType != TYPE_WINDOW_MANAGER) {
// return false
// }
// when (ev?.action) {
// MotionEvent.ACTION_DOWN -> {
// needInterceptClick = false
// startX = ev.x
// }
// MotionEvent.ACTION_MOVE -> {
// moveX = startX - ev.x
// scrollBy(moveX.toInt(), 0)
// startX = ev.x
// if (scrollX < 0) {
// scrollTo(0, 0)
// }
// if (!needInterceptClick && scrollX > 20) {
// needInterceptClick = true
// }
// invalidate()
// }
// MotionEvent.ACTION_UP -> {
// if (scrollX > 0) {
// mScroller.startScroll(scrollX, 0, width - scrollX, 0)
// invalidate()
// return true
// }
// if (needInterceptClick) {
// return true
// }
// }
// else -> {
// startX = 0f
// moveX = 0f
// }
// }
// return false
// }
//
// override fun computeScroll() {
// if (mScroller.computeScrollOffset()) {
// scrollTo(mScroller.currX, mScroller.currY)
// invalidate()
// } else {
// if (mScroller.currX == 0) {
// return
// }
// mScroller.finalX = 0
// removeCallbacks(delayClosePush)
// if (isAddWindow) {
// if (currentBean != null) {
// AnalyticsUtils.track(Config.NEWS_CARD_SWIPE, "trigger_type", "1")
// }
// mWindowManager.removeView(this)
// isAddWindow = false
// }
// pushViewModel.pushBean?.showTimeout = 0
// updateTimer()
// }
// }
//
// override fun getImgWidth(): Int =
// context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_width_vertical)
//
// override fun getImgHeight(): Int =
// context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height_vertical)
//
// override fun getQrImgWidth(): Int =
// context.resources.getDimensionPixelSize(R.dimen.module_push_image_qr_size_vertical)
//
// override fun getQrImgHeight(): Int =
// context.resources.getDimensionPixelSize(R.dimen.module_push_image_qr_size_vertical)
// }
private var pushCheckDialog: PushCheckDialog? = null
private val delayClosePush: Runnable
private var isAddWindow = false
private val uiHandler = Handler(Looper.getMainLooper())
@@ -473,10 +405,8 @@ class FloatView constructor(
val time = pushViewModel.pushBean?.showTimeout ?: 0
if (time > 0) {
pushViewModel.pushBean!!.showTimeout--
pushViewController?.timer(time)
uiHandler.postDelayed(delayClosePush, 1000)
} else {
pushViewController?.timer(0)
pushViewModel.pushMessageFinish(true)
}
}
@@ -520,17 +450,17 @@ class FloatView constructor(
}
private fun showByWindowManager(bean: PushBean?) {
if (pushViewController !is PushViewInWindowView) {
pushViewController = PushViewInWindowView(context)
}
pushViewController?.show(bean)
// if (pushViewController !is PushViewInWindowView) {
// pushViewController = PushViewInWindowView(context)
// }
// pushViewController?.show(bean)
}
private fun startClosePush() {
uiHandler.removeCallbacks(delayClosePush)
uiHandler.postDelayed(
delayClosePush,
1000L
delayClosePush,
1000L
)
}

View File

@@ -0,0 +1,568 @@
package com.mogo.module.push.view
import android.animation.Animator
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.PixelFormat
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.view.*
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.Scroller
import android.widget.TextView
import androidx.annotation.LayoutRes
import androidx.core.animation.doOnEnd
import androidx.core.view.isVisible
import com.elegant.analytics.utils.Logger
import com.mogo.commons.voice.AIAssist
import com.mogo.module.push.Config
import com.mogo.module.push.R
import com.mogo.module.push.model.PushBean
import com.mogo.module.push.utils.AnalyticsUtils
import com.mogo.module.push.utils.stringConverterBitmap
import com.mogo.module.push.view.roundimage.RoundedImageView
import com.mogo.module.push.viewmodel.PushViewModel
import com.mogo.service.windowview.IMogoTopViewManager
import com.mogo.service.windowview.IMogoTopViewStatusListener
import com.mogo.utils.ResourcesHelper
import com.mogo.utils.ThreadPoolService
import com.mogo.utils.UiThreadHandler
import com.mogo.utils.glide.GlideApp
class FloatViewOrigin constructor(
private val pushViewModel: PushViewModel,
private val context: Context
) {
companion object {
const val TYPE_TOP_VIEW = 1
const val TYPE_WINDOW_MANAGER = 2
const val TAG: String = "FloatViewOrigin.kt"
}
interface PushViewController {
fun show(bean: PushBean?)
fun hide()
fun timer(time: Int)
fun inflateView(@LayoutRes layoutId: Int)
}
abstract inner class PushViewOrigin(context: Context) : FrameLayout(context),
PushViewController {
private lateinit var appIcon: ImageView
private lateinit var titleIconContainer: View
private lateinit var pushTitle: TextView
private lateinit var pushImage: RoundedImageView
private lateinit var pushContent: TextView
private lateinit var pushTimer: TextView
private lateinit var pushButtonLeft: TextView
private lateinit var pushButtonRight: TextView
lateinit var pushButton: View
override fun inflateView(layoutId: Int) {
LayoutInflater.from(context).inflate(layoutId, this, true)
appIcon = findViewById(R.id.module_push_app_icon)
pushTitle = findViewById(R.id.module_push_title)
pushImage = findViewById(R.id.module_push_image)
pushContent = findViewById(R.id.module_push_content)
pushButtonLeft = findViewById(R.id.module_push_button_left)
pushButtonRight = findViewById(R.id.module_push_button_right)
pushTimer = findViewById(R.id.module_push_timer)
titleIconContainer = findViewById(R.id.module_push_app_icon_title)
pushButton = findViewById(R.id.module_push_buttons)
setOnClickListener {
pushViewModel.dealCmd(PushViewModel.VOICE_ACTION_PUSH_MAIN, "1")
turnNextMessage()
}
pushButtonLeft.setOnClickListener {
pushViewModel.dealCmd(PushViewModel.VOICE_ACTION_PUSH_LEFT, "1")
turnNextMessage()
}
pushButtonRight.setOnClickListener {
pushViewModel.dealCmd(PushViewModel.VOICE_ACTION_PUSH_RIGHT, "1")
turnNextMessage()
}
}
private fun turnNextMessage() {
pushViewModel.pushBean?.apply {
showTimeout = 0
updateTimer()
}
}
fun hasButtons(bean: PushBean?): Boolean {
bean?.buttons?.forEach {
if (it.text.isNotEmpty()) {
return true
}
}
return false
}
fun hasTextContent(bean: PushBean?): Boolean =
bean?.content?.isEmpty()?.not() ?: false
fun hasImgContent(bean: PushBean?): Boolean = bean?.QRCode?.isEmpty()?.not() ?: false
open fun setBean(bean: PushBean) {
// app icon
if (bean.appIcon.isNotEmpty()) {
appIcon.visible()
GlideApp.with(this).load(bean.appIcon).into(appIcon)
} else {
appIcon.gone()
}
// title
pushTitle.text = bean.title
// decrease timer
pushTimer.text = if (bean.showTimeout > 99) "" else "${bean.showTimeout}s"
// image
if (bean.imageUrl.isEmpty() && bean.QRCode.isEmpty()) {
pushImage.gone()
} else if (bean.imageUrl.isNotEmpty()) {
val params = pushImage.layoutParams
params.width = getImgWidth()
params.height = getImgHeight()
pushImage.layoutParams = params
pushImage.visible()
GlideApp.with(this).load(bean.imageUrl).into(pushImage)
} else if (bean.QRCode.isNotEmpty()) {
val params = pushImage.layoutParams
params.width = getQrImgWidth()
params.height = getQrImgHeight()
pushImage.layoutParams = params
ThreadPoolService.execute {
val bmp = stringConverterBitmap(
bean.QRCode,
getQrImgWidth(),
getQrImgHeight()
)
UiThreadHandler.post {
pushImage.setImageBitmap(bmp)
pushImage.visible()
}
}
}
// button
pushButton.gone()
pushButtonLeft.gone()
pushButtonRight.gone()
if (!bean.buttons.isNullOrEmpty()) {
if (bean.buttons[0].text.isNotEmpty()) {
pushButton.visible()
pushButtonLeft.text = bean.buttons[0].text
pushButtonLeft.visible()
}
if (bean.buttons.size > 1 && bean.buttons[1].text.isNotEmpty()) {
pushButtonRight.text = bean.buttons[1].text
pushButtonRight.visible()
}
}
// content
if (bean.content.isEmpty()) {
pushContent.gone()
} else {
pushContent.text = bean.content
pushContent.visible()
}
// tts
if (bean.tts.isNotEmpty()) {
AIAssist.getInstance(context).speakTTSVoice(bean.tts)
}
}
abstract fun getImgWidth(): Int
abstract fun getImgHeight(): Int
abstract fun getQrImgWidth(): Int
abstract fun getQrImgHeight(): Int
@SuppressLint("SetTextI18n")
override fun timer(time: Int) {
Logger.d(TAG, "time = $time")
pushTimer.text = "${time}s"
}
override fun show(bean: PushBean?) {
isAddWindow = true
uiHandler.removeCallbacks(delayClosePush)
}
override fun hide() {
isAddWindow = false
}
}
open inner class PushViewInTopView(context: Context) : PushViewOrigin(context) {
private val mTopViewManager: IMogoTopViewManager = getApis(context).topViewManager
init {
inflateView(R.layout.module_push_item_origin)
}
private var topViewStatusListener = object : IMogoTopViewStatusListener {
override fun onViewRemoved(view: View?) {
isAddWindow = false
if (pushViewModel.pushBean?.showTimeout ?: 0 > 0) {
if (getApis(context).statusManagerApi.isV2XShow) {
// 被中断的消息,需要再次被显示一次
uiHandler.removeCallbacks(delayClosePush)
pushViewModel.push()
pushViewModel.pushMessageFinish()
return
}
}
pushViewModel.pushBean?.showTimeout = 0
updateTimer()
}
override fun onViewAdded(view: View?) {
if (pushViewModel.pushBean != null) {
startClosePush()
}
}
override fun beforeViewRemoveAnim(view: View?) {
}
override fun beforeViewAddAnim(view: View?) {
}
}
override fun show(bean: PushBean?) {
super.show(bean)
mLastVisibleType = TYPE_TOP_VIEW
mTopViewManager.addView(this, topViewStatusListener)
setBean(bean!!)
}
override fun hide() {
super.hide()
mTopViewManager.removeView(this)
}
override fun getImgWidth(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_width)
override fun getImgHeight(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height)
override fun getQrImgWidth(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height)
override fun getQrImgHeight(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height)
}
inner class PushViewInWindowView(context: Context) : PushViewOrigin(context), View.OnTouchListener {
private val mContentContainer: View
private val mWindowManager =
context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
private val params = WindowManager.LayoutParams()
init {
@Suppress("DEPRECATION")
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
params.flags = (WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
or WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE
or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
params.width = WindowManager.LayoutParams.WRAP_CONTENT
params.height = WindowManager.LayoutParams.WRAP_CONTENT
params.gravity = Gravity.START or Gravity.BOTTOM
params.format = PixelFormat.TRANSLUCENT
params.x = context.resources.getDimensionPixelSize(R.dimen.module_push_window_x)
params.y = context.resources.getDimensionPixelSize(R.dimen.module_push_window_x)
if (Build.VERSION.SDK_INT > 25) {
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
}
inflateView(R.layout.module_push_item_vertical)
mContentContainer = findViewById(R.id.module_push_content_container)
setOnTouchListener(this)
}
override fun show(bean: PushBean?) {
super.show(bean)
mLastVisibleType = TYPE_WINDOW_MANAGER
setBean(bean!!)
try {
mWindowManager.addView(this, params)
} catch (e: Exception) {
mWindowManager.updateViewLayout(this, params)
}
translationXAnimation(
-ResourcesHelper.getDimension(context, R.dimen.module_push_ui_width_vertical),
0f
) {
if (pushViewModel.pushBean != null) {
startClosePush()
}
}
}
private fun translationXAnimation(
from: Float,
to: Float,
doOnEnd: (animator: Animator) -> Unit
) {
val transitionXAnimator: ObjectAnimator =
ObjectAnimator.ofFloat(
this,
View.TRANSLATION_X,
from,
to
)
transitionXAnimator.duration = 200
transitionXAnimator.doOnEnd(doOnEnd)
transitionXAnimator.start()
}
override fun setBean(bean: PushBean) {
super.setBean(bean)
var paddingBottom = 0
if (pushButton.isVisible) {
paddingBottom =
context.resources.getDimensionPixelSize(R.dimen.module_push_content_paddingBottom_vertical)
}
mContentContainer.setPadding(0, 0, 0, paddingBottom)
}
override fun hide() {
super.hide()
translationXAnimation(
this.x,
-ResourcesHelper.getDimension(context, R.dimen.module_push_ui_width_vertical)
) {
Logger.d(TAG, "here")
this.x = 0f
mWindowManager.removeViewImmediate(this)
}
}
override fun onTouch(v: View?, ev: MotionEvent?): Boolean {
if (mLastVisibleType != TYPE_WINDOW_MANAGER) {
return false
}
when (ev?.action) {
MotionEvent.ACTION_DOWN -> {
needInterceptClick = false
startX = ev.x
}
MotionEvent.ACTION_MOVE -> {
moveX = startX - ev.x
scrollBy(moveX.toInt(), 0)
startX = ev.x
if (scrollX < 0) {
scrollTo(0, 0)
}
if (!needInterceptClick && scrollX > 20) {
needInterceptClick = true
}
invalidate()
}
MotionEvent.ACTION_UP -> {
if (scrollX > 0) {
mScroller.startScroll(scrollX, 0, width - scrollX, 0)
invalidate()
return true
}
if (needInterceptClick) {
return true
}
}
else -> {
startX = 0f
moveX = 0f
}
}
return false
}
override fun computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.currX, mScroller.currY)
invalidate()
} else {
if (mScroller.currX == 0) {
return
}
mScroller.finalX = 0
removeCallbacks(delayClosePush)
if (isAddWindow) {
if (currentBean != null) {
AnalyticsUtils.track(Config.NEWS_CARD_SWIPE, "trigger_type", "1")
}
mWindowManager.removeView(this)
isAddWindow = false
}
pushViewModel.pushBean?.showTimeout = 0
updateTimer()
}
}
override fun getImgWidth(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_width_vertical)
override fun getImgHeight(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_ui_image_height_vertical)
override fun getQrImgWidth(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_image_qr_size_vertical)
override fun getQrImgHeight(): Int =
context.resources.getDimensionPixelSize(R.dimen.module_push_image_qr_size_vertical)
}
private val delayClosePush: Runnable
private var isAddWindow = false
private val uiHandler = Handler(Looper.getMainLooper())
private var startX = 0f
private var moveX = 0f
private val mScroller: Scroller = Scroller(context)
private var needInterceptClick = false
private var pause = false
private var currentBean: PushBean? = null
private var mLastVisibleType = -1
private var pushViewController: PushViewController? = null
init {
delayClosePush = Runnable {
updateTimer()
}
}
fun pushBeanChanged(bean: PushBean?) {
uiHandler.post {
uiHandler.removeCallbacks(delayClosePush)
if (bean == null) {
if (currentBean != null) {
AnalyticsUtils.track(Config.NEWS_CARD_DISAPPEAR, "title", currentBean!!.title)
}
hide()
} else {
show(bean)
AnalyticsUtils.track(Config.NEWS_CARD_SHOW, "title", bean.title)
}
currentBean = bean
}
}
private fun updateTimer() {
uiHandler.removeCallbacks(delayClosePush)
val time = pushViewModel.pushBean?.showTimeout ?: 0
if (time > 0) {
pushViewModel.pushBean!!.showTimeout--
pushViewController?.timer(time)
uiHandler.postDelayed(delayClosePush, 1000)
} else {
pushViewController?.timer(0)
pushViewModel.pushMessageFinish(true)
}
}
private fun show(bean: PushBean) {
if (isAddWindow) {
if (getApis(context).statusManagerApi.isMainPageOnResume) {
if (mLastVisibleType != TYPE_TOP_VIEW) {
hide()
(pushViewController as View).postDelayed({
show(bean)
}, 750L)
} else {
showByTopView(bean)
}
} else {
if (mLastVisibleType != TYPE_WINDOW_MANAGER) {
hide()
(pushViewController as View).postDelayed({
show(bean)
}, 750L)
} else {
showByWindowManager(bean)
}
}
startClosePush()
} else {
if (getApis(context).statusManagerApi.isMainPageOnResume) {
showByTopView(bean)
} else {
showByWindowManager(bean)
}
}
}
private fun showByTopView(bean: PushBean) {
if (pushViewController !is PushViewInTopView) {
pushViewController = PushViewInTopView(context)
}
pushViewController?.show(bean)
}
private fun showByWindowManager(bean: PushBean?) {
if (pushViewController !is PushViewInWindowView) {
pushViewController = PushViewInWindowView(context)
}
pushViewController?.show(bean)
}
private fun startClosePush() {
uiHandler.removeCallbacks(delayClosePush)
uiHandler.postDelayed(
delayClosePush,
1000L
)
}
fun hide() {
if (!isAddWindow) {
return
}
try {
pushViewController?.hide()
} catch (e: Exception) {
e.printStackTrace()
}
}
fun pauseTimer(on: Boolean) {
if (on) {
uiHandler.removeCallbacks(delayClosePush)
} else {
updateTimer()
uiHandler.post {
if (on) {
pause = true
uiHandler.removeCallbacks(delayClosePush)
} else if (pause) {
pause = false
updateTimer()
}
}
}
}
fun isAddWindow(): Boolean = isAddWindow
}

View File

@@ -0,0 +1,37 @@
package com.mogo.module.push.view
import android.content.Context
import android.widget.ImageView
import android.widget.TextView
import com.mogo.module.common.dialog.BaseFloatDialog
import com.mogo.module.push.R
class PushCheckDialog(context: Context) : BaseFloatDialog(context) {
private var pushCheckClose: ImageView? = null
private var pushCheckTitle: TextView? = null
private var pushCheckContent: TextView? = null
init {
setContentView(R.layout.module_push_dialog_check)
setCanceledOnTouchOutside(true)
pushCheckClose = findViewById(R.id.module_push_dialog_close)
pushCheckTitle = findViewById(R.id.module_push_dialog_title)
pushCheckContent = findViewById(R.id.module_push_dialog_content)
pushCheckClose?.setOnClickListener {
dismiss()
}
}
fun showCheckDialog(title: String, content: String) {
if (isShowing) {
return
}
if (title.isBlank() || content.isBlank()) {
return
}
pushCheckTitle?.text = title
pushCheckContent?.text = content
show()
}
}