Visitar URL original
新增路径动画 · jacker-java/AndroidCustomView@685a8fe · GitHub
Skip to content

Commit 685a8fe

Browse files
committed
新增路径动画
1 parent 637ebb5 commit 685a8fe

5 files changed

Lines changed: 225 additions & 0 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.allen.androidcustomview.activity
2+
3+
import android.os.Bundle
4+
import android.support.v7.app.AppCompatActivity
5+
import com.allen.androidcustomview.R
6+
import kotlinx.android.synthetic.main.activity_path.*
7+
8+
/**
9+
* <pre>
10+
* @author : Allen
11+
* date : 2019/07/23
12+
* desc :
13+
* </pre>
14+
*/
15+
class PathActivity : AppCompatActivity() {
16+
17+
override fun onCreate(savedInstanceState: Bundle?) {
18+
super.onCreate(savedInstanceState)
19+
setContentView(R.layout.activity_path)
20+
start_btn.setOnClickListener {
21+
car_anim_view.startAnim()
22+
}
23+
}
24+
25+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package com.allen.androidcustomview.widget
2+
3+
import android.animation.Animator
4+
import android.animation.ValueAnimator
5+
import android.content.Context
6+
import android.graphics.*
7+
import android.graphics.drawable.BitmapDrawable
8+
import android.graphics.drawable.Drawable
9+
import android.util.AttributeSet
10+
import android.view.MotionEvent
11+
import android.view.View
12+
import com.allen.androidcustomview.R
13+
import kotlin.math.atan2
14+
15+
16+
/**
17+
* <pre>
18+
* @author : Allen
19+
* date : 2019/07/23
20+
* desc : 小汽车跟随轨迹运动
21+
* </pre>
22+
*/
23+
class CarMoveView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
24+
25+
private var mWidth = 0
26+
private var mHeight = 0
27+
28+
/**
29+
* 背景颜色
30+
*/
31+
private var mPathColor = Color.RED
32+
private var mPaint = Paint()
33+
private var mCarPaint = Paint()
34+
35+
private var mRect = Rect()
36+
private var mMovePath = Path()
37+
38+
private var mStartX = 0f
39+
private var mStartY = 0f
40+
41+
private var pathMeasure: PathMeasure = PathMeasure()
42+
43+
private val pos = FloatArray(2)
44+
private val tan = FloatArray(2)
45+
46+
private var isMoveCar = false
47+
48+
private var mRectWidth = 30
49+
50+
private var mDuration = 5
51+
private var mCarDrawableRes: Drawable? = null
52+
private var mCarBitmapRes: Bitmap? = null
53+
54+
init {
55+
initView(context, attrs, defStyleAttr)
56+
initPaint()
57+
mCarBitmapRes = (mCarDrawableRes as? BitmapDrawable)?.bitmap
58+
}
59+
60+
private fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
61+
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarMoveView)
62+
mPathColor = typedArray.getColor(R.styleable.CarMoveView_carMovePathColor, mPathColor)
63+
mDuration = typedArray.getInt(R.styleable.CarMoveView_carMoveDuration, mDuration)
64+
mCarDrawableRes = typedArray.getDrawable(R.styleable.CarMoveView_carMoveDrawableRes)
65+
typedArray.recycle()
66+
}
67+
68+
private fun initPaint() {
69+
mPaint.color = mPathColor
70+
mPaint.style = Paint.Style.STROKE
71+
mPaint.isAntiAlias = true
72+
73+
mCarPaint.color = mPathColor
74+
mCarPaint.style = Paint.Style.FILL
75+
mCarPaint.isAntiAlias = true
76+
}
77+
78+
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
79+
super.onSizeChanged(w, h, oldw, oldh)
80+
mWidth = w
81+
mHeight = h
82+
}
83+
84+
override fun onDraw(canvas: Canvas?) {
85+
super.onDraw(canvas)
86+
drawPath(canvas)
87+
drawMoveCar(canvas)
88+
}
89+
90+
private fun drawPath(canvas: Canvas?) {
91+
canvas?.drawPath(mMovePath, mPaint)
92+
}
93+
94+
private fun drawMoveCar(canvas: Canvas?) {
95+
pathMeasure.setPath(mMovePath, false)
96+
if (isMoveCar) {
97+
// 计算图片旋转角度
98+
val degrees = (atan2(tan[1].toDouble(), tan[0].toDouble()) * 180.0 / Math.PI).toFloat()
99+
canvas?.rotate(degrees, pos[0], pos[1])
100+
//小车中心点在运行轨道上
101+
mRect.set((pos[0] - mRectWidth).toInt(), (pos[1] - mRectWidth).toInt(), (pos[0] + mRectWidth).toInt(), (pos[1] + mRectWidth).toInt())
102+
//小车轮子在运行轨道上
103+
//mRect.set((pos[0] - mRectWidth).toInt(), (pos[1] - mRectWidth * 2).toInt(), (pos[0] + mRectWidth).toInt(), (pos[1]).toInt())
104+
if (mCarBitmapRes == null) {
105+
canvas?.drawRect(mRect, mCarPaint)
106+
} else {
107+
canvas?.drawBitmap(mCarBitmapRes, null, mRect, mPaint)
108+
}
109+
}
110+
}
111+
112+
override fun onTouchEvent(event: MotionEvent): Boolean {
113+
when (event.action) {
114+
MotionEvent.ACTION_DOWN -> {
115+
mStartX = event.x
116+
mStartY = event.y
117+
mMovePath.reset()
118+
mMovePath.moveTo(mStartX, mStartY)
119+
return true
120+
}
121+
MotionEvent.ACTION_MOVE -> {
122+
val endX = (mStartX + event.x) / 2
123+
val endY = (mStartY + event.y) / 2
124+
mMovePath.quadTo(mStartX, mStartY, endX, endY)
125+
mStartX = event.x
126+
mStartY = event.y
127+
invalidate()
128+
return true
129+
}
130+
}
131+
return super.onTouchEvent(event)
132+
}
133+
134+
fun startAnim() {
135+
isMoveCar = true
136+
val valueAnimator = ValueAnimator.ofFloat(0f, pathMeasure.length)
137+
valueAnimator.duration = mDuration * 1000L
138+
valueAnimator.addUpdateListener {
139+
val distance: Float = it.animatedValue as Float
140+
pathMeasure.getPosTan(distance, pos, tan)
141+
invalidate()
142+
}
143+
valueAnimator.addListener(object : Animator.AnimatorListener {
144+
override fun onAnimationRepeat(animation: Animator?) {}
145+
146+
override fun onAnimationEnd(animation: Animator?) {
147+
isMoveCar = false
148+
}
149+
150+
override fun onAnimationCancel(animation: Animator?) {
151+
isMoveCar = false
152+
}
153+
154+
override fun onAnimationStart(animation: Animator?) {}
155+
156+
})
157+
valueAnimator.start()
158+
}
159+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
android:layout_width="match_parent"
5+
android:layout_height="match_parent"
6+
android:orientation="vertical">
7+
8+
<TextView
9+
android:layout_width="wrap_content"
10+
android:layout_height="wrap_content"
11+
android:layout_centerInParent="true"
12+
android:alpha="0.3"
13+
android:gravity="center"
14+
android:text="手指画一个连续路径,然后点击动画" />
15+
16+
<com.allen.androidcustomview.widget.CarMoveView
17+
android:id="@+id/car_anim_view"
18+
android:layout_width="match_parent"
19+
android:layout_height="match_parent"
20+
android:layout_above="@+id/start_btn"
21+
app:carMoveDrawableRes="@mipmap/car"
22+
app:carMoveDuration="10" />
23+
24+
<Button
25+
android:id="@+id/start_btn"
26+
android:layout_width="match_parent"
27+
android:layout_height="wrap_content"
28+
android:layout_alignParentBottom="true"
29+
android:text="启动动画" />
30+
31+
</RelativeLayout>
78.7 KB
Loading

‎app/src/main/res/values/colors.xml‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,14 @@
2222
<color name="white">#ffffff</color>
2323
<color name="aliPay_bar_color">#1983d1</color>
2424
<color name="aliPay_search_bg_color">#11222222</color>
25+
26+
27+
<color name="border_color">#e6e6e6</color>
28+
<color name="checked_progress_color">#1AFF7C05</color>
29+
<color name="unchecked_progress_color">#F3F3F3</color>
30+
<color name="unchecked_content_text_color">#1a1a1a</color>
31+
<color name="checked_content_text_color">#FF7C05</color>
32+
<color name="unchecked_result_text_color">#333333</color>
33+
<color name="checked_result_text_color">#FF7C05</color>
34+
2535
</resources>

0 commit comments

Comments
 (0)