diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 96cc43e..61a9130 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,22 +1,6 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index afaee01..57af74c 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -1,8 +1,10 @@ + 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下载](https://github.com/lygttpod/AndroidCustomView/blob/master/app/src/main/res/mipmap-xxhdpi/app_download.png?raw=true) +[点击下载demo体验](http://d.firim.top/whez) # [**炫酷的提交按钮**](https://github.com/lygttpod/AndroidCustomView/blob/master/animation_button.md) ![99.gif](http://upload-images.jianshu.io/upload_images/2057501-0d1119721429bf71.gif?imageMogr2/auto-orient/strip) 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 @@ + + + + + + + + + +