+
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 788937b..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index 7f68460..0000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 2f3f7d2..eef6e0a 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
或者手动加QQ群:688433795
## Demo示例下载
-
+[点击下载demo体验](http://d.firim.top/whez)
# [**炫酷的提交按钮**](https://github.com/lygttpod/AndroidCustomView/blob/master/animation_button.md)

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7df0ab8..ce59942 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -39,6 +39,7 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/allen/androidcustomview/activity/ClearScreenActivity.kt b/app/src/main/java/com/allen/androidcustomview/activity/ClearScreenActivity.kt
new file mode 100644
index 0000000..f6091f0
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/activity/ClearScreenActivity.kt
@@ -0,0 +1,39 @@
+package com.allen.androidcustomview.activity
+
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import android.widget.Toast
+import com.allen.androidcustomview.R
+import com.allen.androidcustomview.widget.ClearScreenMode
+import com.allen.androidcustomview.widget.ClearScreenView
+import kotlinx.android.synthetic.main.activity_clear_screen.*
+
+/**
+ *
+ * author : Allen
+ * date : 2021年1月28日
+ * desc :
+ *
+ */
+class ClearScreenActivity : AppCompatActivity(), ClearScreenView.OnClearScreenListener {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_clear_screen)
+
+ clear_screen_container.addClearView(iv_clear_content)
+
+ clear_screen_container.setOnClearScreenListener(this)
+
+ btn_quick_clear.setOnClickListener { clear_screen_container.clearScreenMode = ClearScreenMode.QUICK_SCROLL }
+ btn_slow_clear.setOnClickListener { clear_screen_container.clearScreenMode = ClearScreenMode.SLOW_SCROLL }
+ }
+
+ override fun onCleared() {
+ Toast.makeText(this, "清屏了", Toast.LENGTH_SHORT).show()
+ }
+
+ override fun onRestored() {
+ Toast.makeText(this, "恢复了", Toast.LENGTH_SHORT).show()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/allen/androidcustomview/activity/MainActivity.kt b/app/src/main/java/com/allen/androidcustomview/activity/MainActivity.kt
index b5dee27..5df548d 100644
--- a/app/src/main/java/com/allen/androidcustomview/activity/MainActivity.kt
+++ b/app/src/main/java/com/allen/androidcustomview/activity/MainActivity.kt
@@ -42,6 +42,7 @@ class MainActivity : AppCompatActivity(), BaseQuickAdapter.OnItemClickListener {
typeBeans.add(TypeBean("RecyclerView的item动画", 14))
typeBeans.add(TypeBean("路径path动画", 15))
typeBeans.add(TypeBean("仿新浪投票控件", 16))
+ typeBeans.add(TypeBean("直播侧滑清屏效果", 17))
return typeBeans
}
@@ -84,6 +85,7 @@ class MainActivity : AppCompatActivity(), BaseQuickAdapter.OnItemClickListener {
14 -> startActivity(Intent(this@MainActivity, RecyclerViewItemAnimActivity::class.java))
15 -> startActivity(Intent(this@MainActivity, PathActivity::class.java))
16 -> startActivity(Intent(this@MainActivity, SinaVoteActivity::class.java))
+ 17 -> startActivity(Intent(this@MainActivity, ClearScreenActivity::class.java))
}
}
}
diff --git a/app/src/main/java/com/allen/androidcustomview/activity/SinaVoteActivity.kt b/app/src/main/java/com/allen/androidcustomview/activity/SinaVoteActivity.kt
index 1a3a32b..2fee8ab 100644
--- a/app/src/main/java/com/allen/androidcustomview/activity/SinaVoteActivity.kt
+++ b/app/src/main/java/com/allen/androidcustomview/activity/SinaVoteActivity.kt
@@ -12,7 +12,6 @@ import kotlinx.android.synthetic.main.activity_sina_vote.*
/**
*
* @author : Allen
- * e-mail : yagang.li@yintech.cn
* date : 2019年08月06日
* desc :
*
diff --git a/app/src/main/java/com/allen/androidcustomview/bean/VoteBean.kt b/app/src/main/java/com/allen/androidcustomview/bean/VoteBean.kt
index 1b4e8d9..961f14c 100644
--- a/app/src/main/java/com/allen/androidcustomview/bean/VoteBean.kt
+++ b/app/src/main/java/com/allen/androidcustomview/bean/VoteBean.kt
@@ -4,7 +4,6 @@ package com.allen.androidcustomview.bean
/**
*
* @author : Allen
- * e-mail : yagang.li@yintech.cn
* date : 2019年08月01日
* desc :
*
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/ClearScreenView.kt b/app/src/main/java/com/allen/androidcustomview/widget/ClearScreenView.kt
new file mode 100644
index 0000000..3b5e0bf
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/ClearScreenView.kt
@@ -0,0 +1,371 @@
+package com.allen.androidcustomview.widget
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ValueAnimator
+import android.content.Context
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.view.VelocityTracker
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import kotlin.math.abs
+
+
+/**
+ *
+ * @author : Allen
+ * e-mail : lygttpod@163.com
+ * date : 2021年01月28日
+ * desc : 滑动清屏view
+ *
+ */
+enum class ClearScreenType {
+ LEFT_TO_RIGHT,//从左滑到右清屏
+ RIGHT_TO_LEFT //从右滑到左清屏
+}
+
+enum class ClearScreenStatus {
+ NORMAL,//正常状态
+ CLEARED//已经清屏状态
+}
+
+enum class ClearScreenMode {
+ QUICK_SCROLL,//快速滑动才触发清屏
+ SLOW_SCROLL//滑动出发清屏
+}
+
+class ClearScreenView @JvmOverloads constructor(private val mContext: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : FrameLayout(mContext, attrs, defStyleAttr) {
+
+ companion object {
+ /**
+ * 最小移动距离
+ */
+ private const val MIN_SCROLL_SIZE = 50
+
+ /**
+ * 水平方向最小滑动速度
+ */
+ private const val MIN_X_VELOCITY = 10
+
+ /**
+ * 清屏动画时长
+ */
+ private const val DURATION = 300L
+ }
+
+ /**
+ * 手指按下的x轴位置
+ */
+ private var mDownX = 0
+
+ /**
+ * 手指按下的y轴位置
+ */
+ private var mDownY = 0
+
+ /**
+ * 清屏view清屏时需要在x轴的偏移量
+ */
+ private var translateX = 0
+
+ /**
+ * 清屏view起始偏移量(例如:从无到有迁移量从-width到0)
+ */
+ private var startTranslateX = 0
+
+ /**
+ * 滑动速度对象
+ */
+ private var mVelocityTracker: VelocityTracker? = null
+
+ /**
+ * 清屏动画对象
+ */
+ private var mAnimator: ValueAnimator? = null
+
+ /**
+ * 需要清除的Views
+ */
+ private var listClearViews: ArrayList = ArrayList()
+
+ /**
+ * 清屏事件
+ */
+ private var clearScreenListener: OnClearScreenListener? = null
+
+ /**
+ * 清屏类型 左滑清屏 or 右滑清屏 (默认从左滑到右清屏)
+ */
+ private var clearScreenType = ClearScreenType.LEFT_TO_RIGHT
+
+ /**
+ * 当前清屏状态
+ */
+ private var clearScreenStatus = ClearScreenStatus.NORMAL
+
+ /**
+ * 清屏模式
+ */
+ var clearScreenMode = ClearScreenMode.QUICK_SCROLL
+
+ /**
+ * 是否正在处在滑动清屏状态
+ */
+ private var isScrolling = false
+
+ init {
+ initView()
+ initAnim()
+ }
+
+ private fun initView() {
+ val view = View(mContext)
+ view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
+ view.isClickable = true
+ addView(view, 0)
+ }
+
+ private fun initAnim() {
+ mVelocityTracker = VelocityTracker.obtain()
+ mAnimator = ValueAnimator.ofFloat(0f, 1.0f).setDuration(DURATION)
+ mAnimator?.addUpdateListener {
+ val value = it.animatedValue as Float
+ val translate = startTranslateX + value * translateX
+ translateChild(translate)
+ }
+ mAnimator?.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ when (clearScreenStatus) {
+ ClearScreenStatus.CLEARED -> {
+ clearScreenStatus = ClearScreenStatus.NORMAL
+ clearScreenListener?.onRestored()
+ }
+ ClearScreenStatus.NORMAL -> {
+ clearScreenStatus = ClearScreenStatus.CLEARED
+ clearScreenListener?.onCleared()
+ }
+ }
+ isScrolling = false
+ }
+ })
+ }
+
+ override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
+ if (clearScreenListener?.isForbidClearScreen() == true) {
+ return super.onInterceptTouchEvent(ev)
+ }
+ val x = ev.x.toInt()
+ val y = ev.y.toInt()
+ when (ev.action) {
+ MotionEvent.ACTION_DOWN -> {
+ mDownX = x
+ mDownY = y
+ }
+ }
+ return isInterceptClearScreenEvent(x, y)
+ }
+
+ private fun isInterceptClearScreenEvent(x: Int, y: Int): Boolean {
+ return when (clearScreenMode) {
+ ClearScreenMode.QUICK_SCROLL -> {
+ val isIntercept = isMoveForHorizontal(x, y) && !isAnimRunning() && isGreaterThanMinSize(mDownX, x)
+ requestDisallowInterceptTouchEvent(isIntercept)
+ isIntercept
+ }
+ ClearScreenMode.SLOW_SCROLL -> {
+ val isIntercept = isMoveForHorizontal(x, y) && !isAnimRunning() || isScrolling
+ requestDisallowInterceptTouchEvent(isIntercept)
+ isIntercept
+ }
+ }
+ }
+
+ /**
+ * 是否水平方向滑动
+ */
+ private fun isMoveForHorizontal(x: Int, y: Int): Boolean {
+ return abs(x - mDownX)> abs(y - mDownY)
+ }
+
+ private fun isAnimRunning(): Boolean {
+ return mAnimator?.isRunning == true
+ }
+
+ override fun onTouchEvent(event: MotionEvent): Boolean {
+ if (isAnimRunning()) return true
+ when (clearScreenMode) {
+ ClearScreenMode.QUICK_SCROLL -> {
+ handleQuickScrollMode(event)
+ }
+ ClearScreenMode.SLOW_SCROLL -> {
+ handleSlowScrollMode(event)
+ }
+ }
+ return true
+ }
+
+ private fun handleQuickScrollMode(event: MotionEvent) {
+ mVelocityTracker?.addMovement(event)
+ when (event.action) {
+ MotionEvent.ACTION_UP -> {
+ mVelocityTracker?.computeCurrentVelocity(10)
+ val xVelocity = mVelocityTracker?.xVelocity ?: 0f
+ when {
+ //从左往右滑动(是正数)速度大于阈值
+ xVelocity> MIN_X_VELOCITY -> {
+ setLeft2RightMoveTranslateX()
+ }
+ //从右往左滑动(是负数)速度大于阈值
+ xVelocity < -MIN_X_VELOCITY -> {
+ setRight2LeftMoveTranslateX()
+ }
+ else -> {
+ translateX = 0
+ }
+ }
+ if (translateX != 0) {
+ mAnimator?.start()
+ }
+ }
+ }
+ }
+
+ private fun handleSlowScrollMode(event: MotionEvent) {
+ val x = event.x.toInt()
+ when (event.action) {
+ MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
+ when (clearScreenStatus) {
+ ClearScreenStatus.NORMAL -> {
+ if (startTranslateX>= width / 2) {
+ translateX = width - startTranslateX
+ clearScreenStatus = ClearScreenStatus.NORMAL
+ } else {
+ translateX = -startTranslateX
+ clearScreenStatus = ClearScreenStatus.CLEARED
+ }
+ mAnimator?.start()
+ }
+ ClearScreenStatus.CLEARED -> {
+ if (startTranslateX>= width / 2) {
+ translateX = width - startTranslateX
+ clearScreenStatus = ClearScreenStatus.NORMAL
+ } else {
+ translateX = (-startTranslateX)
+ clearScreenStatus = ClearScreenStatus.CLEARED
+ }
+ mAnimator?.start()
+ }
+ }
+ }
+ MotionEvent.ACTION_MOVE -> {
+ translateX = 0
+ val move = x - mDownX
+ when (clearScreenStatus) {
+ ClearScreenStatus.NORMAL -> {
+ val translate = if (x <= mDownX) 0 else move + startTranslateX = translate + if (translate != 0) { + translateChild(translate.toFloat()) + } + } + ClearScreenStatus.CLEARED -> {
+ val translate = if (x> mDownX) 0 else mDownX - x
+ startTranslateX = width - translate
+ if (startTranslateX != 0) {
+ translateChild(startTranslateX.toFloat())
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun setLeft2RightMoveTranslateX() {
+ when (clearScreenType) {
+ ClearScreenType.LEFT_TO_RIGHT -> {
+ startTranslateX = 0
+ translateX = if (clearScreenStatus == ClearScreenStatus.NORMAL) width else 0
+ }
+ ClearScreenType.RIGHT_TO_LEFT -> {
+ startTranslateX = -width
+ translateX = if (clearScreenStatus == ClearScreenStatus.NORMAL) 0 else width
+ }
+ }
+ }
+
+ private fun setRight2LeftMoveTranslateX() {
+ when (clearScreenType) {
+ ClearScreenType.LEFT_TO_RIGHT -> {
+ startTranslateX = width
+ translateX = if (clearScreenStatus == ClearScreenStatus.NORMAL) 0 else -width
+ }
+ ClearScreenType.RIGHT_TO_LEFT -> {
+ startTranslateX = 0
+ translateX = if (clearScreenStatus == ClearScreenStatus.NORMAL) -width else 0
+ }
+ }
+ }
+
+ /**
+ * 是否大于清屏方向的最小值
+ */
+ private fun isGreaterThanMinSize(downX: Int, moveX: Int): Boolean {
+ return when (clearScreenType) {
+ ClearScreenType.LEFT_TO_RIGHT -> {
+ when (clearScreenStatus) {
+ ClearScreenStatus.NORMAL -> moveX - downX> MIN_SCROLL_SIZE
+ ClearScreenStatus.CLEARED -> downX - moveX> MIN_SCROLL_SIZE
+ }
+ }
+ ClearScreenType.RIGHT_TO_LEFT -> {
+ when (clearScreenStatus) {
+ ClearScreenStatus.NORMAL -> downX - moveX> MIN_SCROLL_SIZE
+ ClearScreenStatus.CLEARED -> moveX - downX> MIN_SCROLL_SIZE
+ }
+ }
+ }
+ }
+
+ private fun translateChild(translate: Float) {
+ isScrolling = true
+ for (view in listClearViews) {
+ view.translationX = translate
+ }
+ }
+
+ fun addClearViews(views: List) {
+ for (view in views) {
+ if (!listClearViews.contains(view)) {
+ listClearViews.add(view)
+ }
+ }
+ }
+
+ fun addClearView(view: View) {
+ if (!listClearViews.contains(view)) {
+ listClearViews.add(view)
+ }
+ }
+
+ fun removeClearViews(views: List) {
+ for (view in views) {
+ listClearViews.remove(view)
+ }
+ }
+
+ fun removeAllClearViews() {
+ listClearViews.clear()
+ }
+
+ fun setOnClearScreenListener(listener: OnClearScreenListener?) {
+ this.clearScreenListener = listener
+ }
+
+ interface OnClearScreenListener {
+ fun onCleared()
+ fun onRestored()
+ fun isForbidClearScreen(): Boolean = false
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/StudyPlanProgressView.kt b/app/src/main/java/com/allen/androidcustomview/widget/StudyPlanProgressView.kt
index 3340a7b..468cf0f 100644
--- a/app/src/main/java/com/allen/androidcustomview/widget/StudyPlanProgressView.kt
+++ b/app/src/main/java/com/allen/androidcustomview/widget/StudyPlanProgressView.kt
@@ -12,7 +12,6 @@ import kotlin.math.min
/**
*
* @author : Allen
- * e-mail : yagang.li@yintech.cn
* date : 2019年08月12日
* desc : 学习计划view
*
diff --git a/app/src/main/res/layout/activity_clear_screen.xml b/app/src/main/res/layout/activity_clear_screen.xml
new file mode 100644
index 0000000..675b590
--- /dev/null
+++ b/app/src/main/res/layout/activity_clear_screen.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/mipmap-xxhdpi/live_bg.jpeg b/app/src/main/res/mipmap-xxhdpi/live_bg.jpeg
new file mode 100644
index 0000000..b29c7f6
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/live_bg.jpeg differ
diff --git a/build.gradle b/build.gradle
index 3d9edfe..270f05a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,16 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = '1.3.20'
+ ext.kotlin_version = '1.4.21'
repositories {
jcenter()
- maven {
- url 'https://maven.google.com/'
- name 'Google'
- }
+ google()
+ mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.3.2'
+ classpath 'com.android.tools.build:gradle:4.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
@@ -22,10 +20,8 @@ allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
- maven {
- url 'https://maven.google.com/'
- name 'Google'
- }
+ google()
+ mavenCentral()
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index f869711..6533050 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
\ No newline at end of file