diff --git a/app/src/main/java/com/wanglu/wlikeview/MainActivity.kt b/app/src/main/java/com/wanglu/wlikeview/MainActivity.kt
index dc1993e..1323bd7 100644
--- a/app/src/main/java/com/wanglu/wlikeview/MainActivity.kt
+++ b/app/src/main/java/com/wanglu/wlikeview/MainActivity.kt
@@ -2,6 +2,8 @@ package com.wanglu.wlikeview
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
+import com.wanglu.lib.juejin.WJueJinLikeAnim
+import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
@@ -9,5 +11,18 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
+ var liked = false
+ val likeAnim = WJueJinLikeAnim.Builder(iv, R.mipmap.fd_zan_press).create()
+ iv.setOnClickListener {
+ if(liked){
+ iv.setImageResource(R.mipmap.fd_zan)
+ liked = false
+ }else{
+ iv.setImageResource(R.mipmap.fd_zan_press)
+ liked = true
+ likeAnim.show()
+ }
+ }
+
}
}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index c63d8cd..8c153a1 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -5,12 +5,12 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#fff"
tools:context=".MainActivity">
-
-
+ android:src="@mipmap/fd_zan"/>
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/fd_zan.png b/app/src/main/res/mipmap-hdpi/fd_zan.png
new file mode 100755
index 0000000..885450a
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/fd_zan.png differ
diff --git a/app/src/main/res/mipmap-hdpi/fd_zan_press.png b/app/src/main/res/mipmap-hdpi/fd_zan_press.png
new file mode 100755
index 0000000..70621a2
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/fd_zan_press.png differ
diff --git a/lib/src/main/AndroidManifest.xml b/lib/src/main/AndroidManifest.xml
index 5305769..bc3d732 100644
--- a/lib/src/main/AndroidManifest.xml
+++ b/lib/src/main/AndroidManifest.xml
@@ -1,2 +1,5 @@
+ package="com.wanglu.lib">
+
+
+
diff --git a/lib/src/main/java/com/wanglu/lib/juejin/CircleView.kt b/lib/src/main/java/com/wanglu/lib/juejin/CircleView.kt
index c7e28cd..771d09c 100644
--- a/lib/src/main/java/com/wanglu/lib/juejin/CircleView.kt
+++ b/lib/src/main/java/com/wanglu/lib/juejin/CircleView.kt
@@ -1,5 +1,7 @@
package com.wanglu.lib.juejin
+import android.animation.Animator
+import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
@@ -13,17 +15,21 @@ class CircleView : View {
private val outerCirclePaint = Paint()
private val innerCirclePaint = Paint()
- private var viewWidth = 174
- private var viewHeight = 174
+ private var viewWidth = 0
+ private var viewHeight = 0
private var outerCircleColor = Color.parseColor("#5BA2E9")
private var innerCircleColor = Color.parseColor("#48CFC2")
-
+
private var outerCircleRadius = 0f
private var innerCircleRadius = 0f
- private var outerCircleMaxRadius = viewWidth / 2f - 30
- private var innerCircleMaxRadius = viewWidth / 2f - 35
+ private var outerStrokeWidth = 10f
+ private var outerCircleMaxRadius = 0f
+ private var innerCircleMaxRadius = 0f
+
+ private var animSet = AnimatorSet()
+ private lateinit var dv: DotsView
constructor(context: Context?) : this(context, null)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
@@ -33,32 +39,25 @@ class CircleView : View {
outerCirclePaint.color = outerCircleColor
outerCirclePaint.isAntiAlias = true
outerCirclePaint.style = Paint.Style.STROKE
- outerCirclePaint.strokeWidth = 5f
+ outerCirclePaint.strokeWidth = outerStrokeWidth
innerCirclePaint.color = innerCircleColor
innerCirclePaint.isAntiAlias = true
innerCirclePaint.style = Paint.Style.FILL
-
-
- val outerRadiusAnim = ValueAnimator.ofFloat(outerCircleRadius, outerCircleMaxRadius)
- outerRadiusAnim.duration = 400
- outerRadiusAnim.addUpdateListener{
- outerCircleRadius = it.animatedValue as Float
- invalidate()
- }
-
- val innerRadiusAnim = ValueAnimator.ofFloat(outerCircleRadius, innerCircleMaxRadius)
- innerRadiusAnim.duration = 400
- innerRadiusAnim.addUpdateListener{
- outerCircleRadius = it.animatedValue as Float
- invalidate()
- }
+
+ }
+
+
+ fun startAnim() {
+ animSet.start()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
- setMeasuredDimension(viewWidth, viewHeight)
+ if (viewWidth != 0 && viewHeight != 0) {
+ setMeasuredDimension(viewWidth, viewHeight)
+ }
}
override fun onDraw(canvas: Canvas?) {
@@ -74,6 +73,100 @@ class CircleView : View {
fun setSize(width: Int, height: Int) {
this.viewWidth = width
this.viewHeight = height
+ outerStrokeWidth = (viewWidth / 2 * 0.1).toFloat()
+ outerCircleMaxRadius = viewWidth / 2f - 30
+ innerCircleMaxRadius = outerCircleMaxRadius - outerStrokeWidth / 2
+
+
+ val outerRadiusAnim = ValueAnimator.ofFloat(outerCircleRadius, outerCircleMaxRadius)
+ outerRadiusAnim.duration = 200
+ outerRadiusAnim.addUpdateListener {
+ outerCircleRadius = it.animatedValue as Float
+ invalidate()
+ }
+
+ val innerRadiusAnim = ValueAnimator.ofFloat(innerCircleRadius, innerCircleMaxRadius)
+ innerRadiusAnim.duration = 200
+ innerRadiusAnim.addUpdateListener {
+ innerCircleRadius = it.animatedValue as Float
+ invalidate()
+ }
+
+ val outerStrokeWidthAnim = ValueAnimator.ofFloat(outerStrokeWidth, 0f)
+ outerStrokeWidthAnim.duration = 100
+ outerStrokeWidthAnim.addUpdateListener {
+ outerStrokeWidth = it.animatedValue as Float
+ outerCirclePaint.strokeWidth = outerStrokeWidth
+ invalidate()
+ }
+
+ innerRadiusAnim.addListener(object : Animator.AnimatorListener {
+ override fun onAnimationRepeat(animation: Animator?) {
+
+ }
+
+ override fun onAnimationCancel(animation: Animator?) {
+ }
+
+ override fun onAnimationStart(animation: Animator?) {
+ }
+
+ override fun onAnimationEnd(animation: Animator?) {
+ innerCirclePaint.color = Color.TRANSPARENT
+ invalidate()
+ }
+
+ })
+
+ outerRadiusAnim.addListener(object : Animator.AnimatorListener {
+ override fun onAnimationRepeat(animation: Animator?) {
+
+ }
+
+ override fun onAnimationCancel(animation: Animator?) {
+ }
+
+ override fun onAnimationStart(animation: Animator?) {
+ }
+
+ override fun onAnimationEnd(animation: Animator?) {
+ innerCirclePaint.color = Color.TRANSPARENT
+ invalidate()
+ }
+
+ })
+
+
+
+ animSet.play(outerRadiusAnim).with(innerRadiusAnim).before(outerStrokeWidthAnim)
+ animSet.addListener(object : Animator.AnimatorListener {
+ override fun onAnimationRepeat(animation: Animator?) {
+
+ }
+
+ override fun onAnimationCancel(animation: Animator?) {
+ outerCircleRadius = 0f
+ innerCircleRadius = 0f
+ outerStrokeWidth = (viewWidth / 2 * 0.1).toFloat()
+ outerCirclePaint.strokeWidth = outerStrokeWidth
+ innerCirclePaint.color = innerCircleColor
+ dv.cancelAnim()
+ }
+
+ override fun onAnimationStart(animation: Animator?) {
+ dv.show()
+ }
+
+ override fun onAnimationEnd(animation: Animator?) {
+ outerCircleRadius = 0f
+ innerCircleRadius = 0f
+ outerStrokeWidth = (viewWidth / 2 * 0.1).toFloat()
+ outerCirclePaint.strokeWidth = outerStrokeWidth
+ innerCirclePaint.color = innerCircleColor
+ dv.dismiss()
+ }
+
+ })
invalidate()
}
@@ -86,4 +179,15 @@ class CircleView : View {
invalidate()
}
+ fun cancelAnim() {
+ animSet.cancel()
+ }
+
+ fun isAnimRunning(): Boolean {
+ return animSet.isRunning
+ }
+
+ fun setDv(dv: DotsView){
+ this.dv = dv
+ }
}
\ No newline at end of file
diff --git a/lib/src/main/java/com/wanglu/lib/juejin/DotsView.kt b/lib/src/main/java/com/wanglu/lib/juejin/DotsView.kt
index d258ea2..a27026b 100644
--- a/lib/src/main/java/com/wanglu/lib/juejin/DotsView.kt
+++ b/lib/src/main/java/com/wanglu/lib/juejin/DotsView.kt
@@ -1,5 +1,7 @@
package com.wanglu.lib.juejin
+import android.animation.Animator
+import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
@@ -14,11 +16,11 @@ class DotsView : View {
private val smallDotPaint = Paint()
- private var viewWidth = 174
- private var viewHeight = 174
+ private var viewWidth = 0
+ private var viewHeight = 0
private var centerX = 0
private var centerY = 0
- private var bitDotColor = Color.parseColor("#48CFC2")
+ private var bigDotColor = Color.parseColor("#48CFC2")
private var smallDotColor = Color.parseColor("#5BA2E9")
private var bigDotRadius = MAX_BIG_DOT_RADIUS // 大点的半径
@@ -38,11 +40,11 @@ class DotsView : View {
init {
- bigDotPaint.color = bitDotColor
+ bigDotPaint.color = Color.TRANSPARENT
bigDotPaint.isAntiAlias = true
bigDotPaint.style = Paint.Style.FILL
- smallDotPaint.color = smallDotColor
+ smallDotPaint.color = Color.TRANSPARENT
smallDotPaint.isAntiAlias = true
smallDotPaint.style = Paint.Style.FILL
}
@@ -52,7 +54,7 @@ class DotsView : View {
* 设置颜色
*/
fun setColor(color1: Int, color2: Int){
- bitDotColor = color1
+ bigDotColor = color1
smallDotColor = color2
invalidate()
}
@@ -67,6 +69,14 @@ class DotsView : View {
invalidate()
}
+ fun show(){
+ bigDotPaint.color = bigDotColor
+ smallDotPaint.color = smallDotColor
+ invalidate()
+ }
+
+
+ private var animSet = AnimatorSet()
/**
* 消失
@@ -74,8 +84,8 @@ class DotsView : View {
fun dismiss(){
val bigDotAnim = ValueAnimator.ofFloat(bigDotRadius, 0f)
val smallDotAnim = ValueAnimator.ofFloat(smallDotRadius, 0f)
- bigDotAnim.duration = 400
- smallDotAnim.duration = 400
+ bigDotAnim.duration = 300
+ smallDotAnim.duration = 300
bigDotAnim.addUpdateListener {
bigDotRadius = it.animatedValue as Float
invalidate()
@@ -86,8 +96,35 @@ class DotsView : View {
invalidate()
}
- bigDotAnim.start()
- smallDotAnim.start()
+ animSet.playTogether(bigDotAnim, smallDotAnim)
+ animSet.addListener(object : Animator.AnimatorListener{
+ override fun onAnimationRepeat(animation: Animator?) {
+
+ }
+
+ override fun onAnimationCancel(animation: Animator?) {
+ bigDotPaint.color = Color.TRANSPARENT
+ smallDotPaint.color = Color.TRANSPARENT
+
+ bigDotRadius = MAX_BIG_DOT_RADIUS
+ smallDotRadius = MAX_SMALL_DOT_RADIUS
+ }
+
+ override fun onAnimationStart(animation: Animator?) {
+ }
+
+ override fun onAnimationEnd(animation: Animator?) {
+ // 动画结束后还原
+ bigDotPaint.color = Color.TRANSPARENT
+ smallDotPaint.color = Color.TRANSPARENT
+
+ bigDotRadius = MAX_BIG_DOT_RADIUS
+ smallDotRadius = MAX_SMALL_DOT_RADIUS
+ invalidate()
+ }
+
+ })
+ animSet.start()
}
@@ -95,10 +132,11 @@ class DotsView : View {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
// 测量的时候如果宽高都不为0再设置
-// if (width != 0 && height != 0)
- setMeasuredDimension(viewWidth, viewHeight)
- centerX = viewWidth / 2
- centerY = viewHeight / 2
+ if (viewWidth != 0 && viewHeight != 0) {
+ setMeasuredDimension(viewWidth, viewHeight)
+ centerX = viewWidth / 2
+ centerY = viewHeight / 2
+ }
}
@@ -121,5 +159,8 @@ class DotsView : View {
}
+ fun cancelAnim(){
+ animSet.cancel()
+ }
}
\ No newline at end of file
diff --git a/lib/src/main/java/com/wanglu/lib/juejin/WJueJinAnim.kt b/lib/src/main/java/com/wanglu/lib/juejin/WJueJinAnim.kt
deleted file mode 100644
index 47e0e30..0000000
--- a/lib/src/main/java/com/wanglu/lib/juejin/WJueJinAnim.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.wanglu.lib.juejin
-
-class WJueJinAnim{
-
- companion object {
- var defaultColor1 = "#48CFC2"
- var defaultColor2 = "#5BA2E9"
- }
-}
\ No newline at end of file
diff --git a/lib/src/main/java/com/wanglu/lib/juejin/WJueJinLikeAnim.kt b/lib/src/main/java/com/wanglu/lib/juejin/WJueJinLikeAnim.kt
new file mode 100644
index 0000000..98a7bbb
--- /dev/null
+++ b/lib/src/main/java/com/wanglu/lib/juejin/WJueJinLikeAnim.kt
@@ -0,0 +1,138 @@
+package com.wanglu.lib.juejin
+
+import android.animation.Animator
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
+import android.content.Context
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.animation.BounceInterpolator
+import android.widget.ImageView
+import android.widget.PopupWindow
+import com.wanglu.lib.R
+
+class WJueJinLikeAnim(context: Context?, private val builder: Builder) : PopupWindow(context) {
+
+ private val imgScaleXAnim: ObjectAnimator
+ private val imgScaleYAnim: ObjectAnimator
+ private val animSet = AnimatorSet()
+ private val iv: ImageView
+ private val cv: CircleView
+ private val dv: DotsView
+
+ private val SCALE_FACTOR = 3
+
+ init {
+ contentView = LayoutInflater.from(context).inflate(R.layout.view_jue_jin, null)
+ iv = contentView.findViewById(R.id.iv)
+ cv = contentView.findViewById(R.id.cv)
+ dv = contentView.findViewById(R.id.dv)
+ cv.setDv(dv)
+
+// isTouchable = false
+// setTouchInterceptor { v, event ->
+//
+// cv.cancelAnim()
+// dismiss()
+// false
+// }
+ imgScaleXAnim = ObjectAnimator.ofFloat(iv, "scaleX", 1.5f, 1f)
+ imgScaleYAnim = ObjectAnimator.ofFloat(iv, "scaleY", 1.5f, 1f)
+ setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+ builder.view.post {
+
+ // 如果没有设置padding,则把iv的宽高设置为view的宽高
+ val params = iv.layoutParams
+ if (builder.view.paddingBottom == 0 && builder.view.paddingTop == 0 && builder.view.paddingLeft == 0 && builder.view.paddingRight == 0) {
+ params.width = builder.width
+ params.height = builder.height
+ } else {
+ // 如果设置了padding,则获取图片原始的大小
+ params.width = builder.view.drawable.bounds.width()
+ params.height = builder.view.drawable.bounds.height()
+ }
+
+ iv.setImageResource(builder.imgRes)
+ iv.layoutParams = params
+
+
+
+ width = params.width * SCALE_FACTOR
+ height = params.height * SCALE_FACTOR
+
+ cv.setColor(builder.color1, builder.color2)
+ dv.setColor(builder.color1, builder.color2)
+
+ cv.setSize(width, height)
+ dv.setSize(width, height)
+
+ animSet.duration = 600
+ animSet.interpolator = BounceInterpolator() // 设置插值器
+ animSet.playTogether(imgScaleXAnim, imgScaleYAnim)
+ animSet.addListener(object : Animator.AnimatorListener {
+ override fun onAnimationRepeat(animation: Animator?) {
+
+ }
+
+ override fun onAnimationCancel(animation: Animator?) {
+ }
+
+ override fun onAnimationStart(animation: Animator?) {
+
+ }
+
+ override fun onAnimationEnd(animation: Animator?) {
+ dismiss()
+ }
+
+ })
+ }
+
+ }
+
+ fun show() {
+// if(cv.isAnimRunning()){
+// cv.cancelAnim()
+// animSet.cancel()
+// dismiss()
+// }
+ val viewLocation = IntArray(2)
+ builder.view.getLocationInWindow(viewLocation)
+ val x = viewLocation[0] + builder.width / 2 - width / 2
+ val y = viewLocation[1] + builder.height / 2 - height / 2
+ showAtLocation(iv, Gravity.NO_GRAVITY, x, y)
+ cv.startAnim()
+ animSet.start()
+ }
+
+ class Builder(val view: ImageView, val imgRes: Int) {
+
+ internal var color1 = Color.parseColor("#48CFC2")
+ internal var color2 = Color.parseColor("#5BA2E9")
+
+ internal var width: Int = 0
+ internal var height: Int = 0
+
+ init {
+ view.post {
+ width = view.width
+ height = view.height
+ }
+ }
+
+ /**
+ * 设置颜色
+ */
+ fun setColor(color1: Int, color2: Int) {
+ this.color1 = color1
+ this.color2 = color2
+ }
+
+
+ fun create(): WJueJinLikeAnim {
+ return WJueJinLikeAnim(view.context, this)
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/src/main/res/layout/view_jue_jin.xml b/lib/src/main/res/layout/view_jue_jin.xml
new file mode 100644
index 0000000..4856d9a
--- /dev/null
+++ b/lib/src/main/res/layout/view_jue_jin.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/src/main/res/values/attr.xml b/lib/src/main/res/values/attr.xml
index bf6ffc4..b86edc8 100644
--- a/lib/src/main/res/values/attr.xml
+++ b/lib/src/main/res/values/attr.xml
@@ -1,6 +1,6 @@
-
+