手把手教程,先看效果,能用得上的再继续往下看……
注:生成的gif图扫描有点慢,下面代码有参数可以控制速度。
针对上图效果,以UI方不方便切图,可以有两种实现方式。
- 方式一:UI将整个雷达切图(除中间头像外)
针对整个雷达图做rotation动画
完整代码:
布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1A071D"
tools:context=".MainActivity">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivRadar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:src="@drawable/img_radar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/ic_launcher_round"
app:layout_constraintBottom_toBottomOf="@id/ivRadar"
app:layout_constraintEnd_toEndOf="@id/ivRadar"
app:layout_constraintStart_toStartOf="@id/ivRadar"
app:layout_constraintTop_toTopOf="@id/ivRadar" />
</androidx.constraintlayout.widget.ConstraintLayout>
Activity代码:MainActivity
class MainActivity : AppCompatActivity() {
private var radarScanAnim: ObjectAnimator? = null
private lateinit var ivRadar: AppCompatImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ivRadar = findViewById(R.id.ivRadar)
}
override fun onResume() {
super.onResume()
startScan()
}
override fun onPause() {
super.onPause()
stopScan()
}
/**
* 开始扫描
*/
private fun startScan() {
if (radarScanAnim == null) {
radarScanAnim = ObjectAnimator.ofFloat(ivRadar, "rotation", 0f, 360f)
}
radarScanAnim?.duration = 3000 //扫描一圈的时间
radarScanAnim?.interpolator = LinearInterpolator()
radarScanAnim?.repeatCount = ObjectAnimator.INFINITE //循环 -1
radarScanAnim?.start()
}
/**
* 结束扫描
*/
private fun stopScan() {
radarScanAnim?.cancel()
}
}
资源文件:img_radar.png
- 方式二:UI不切图
将雷达分为两部分:底座图(即4个同心圆)和扫描图,针对扫描图做rotation动画
完整代码:
布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1A071D"
tools:context=".MainActivity">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivWave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:src="@drawable/shape_wave"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivSweep"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/shape_sweep"
app:layout_constraintBottom_toBottomOf="@id/ivWave"
app:layout_constraintEnd_toEndOf="@id/ivWave"
app:layout_constraintStart_toStartOf="@id/ivWave"
app:layout_constraintTop_toTopOf="@id/ivWave" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/ic_launcher_round"
app:layout_constraintBottom_toBottomOf="@id/ivWave"
app:layout_constraintEnd_toEndOf="@id/ivWave"
app:layout_constraintStart_toStartOf="@id/ivWave"
app:layout_constraintTop_toTopOf="@id/ivWave" />
</androidx.constraintlayout.widget.ConstraintLayout>
Activity代码:MainActivity
class MainActivity : AppCompatActivity() {
private var radarScanAnim: ObjectAnimator? = null
private lateinit var ivWave: AppCompatImageView
private lateinit var ivSweep: AppCompatImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ivWave = findViewById(R.id.ivWave)
ivSweep = findViewById(R.id.ivSweep)
}
override fun onResume() {
super.onResume()
startScan()
}
override fun onPause() {
super.onPause()
stopScan()
}
/**
* 开始扫描
*/
private fun startScan() {
if (radarScanAnim == null) {
radarScanAnim = ObjectAnimator.ofFloat(ivSweep, "rotation", 0f, 360f)
}
radarScanAnim?.duration = 3000 //扫描一圈的时间
radarScanAnim?.interpolator = LinearInterpolator()
radarScanAnim?.repeatCount = ObjectAnimator.INFINITE //循环 -1
radarScanAnim?.start()
ivSweep.visibility = View.VISIBLE
}
/**
* 结束扫描
*/
private fun stopScan() {
radarScanAnim?.cancel()
ivSweep.visibility = View.INVISIBLE
}
}
资源文件:res/drawable/shape_wave.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!--最外层圆-->
<item>
<shape android:shape="oval">
<!--颜色值按UI图来,这里我随便写的-->
<solid android:color="#AAF4F4F5" />
</shape>
</item>
<!--次外层圆-->
<item
android:bottom="40dp"
android:left="40dp"
android:right="40dp"
android:top="40dp">
<shape android:shape="oval">
<solid android:color="#AAECECF4" />
</shape>
</item>
<!--次内层圆-->
<item
android:bottom="80dp"
android:left="80dp"
android:right="80dp"
android:top="80dp">
<shape android:shape="oval">
<solid android:color="#AAFCFCFC" />
</shape>
</item>
<!--内层圆-->
<item
android:bottom="140dp"
android:left="140dp"
android:right="140dp"
android:top="140dp">
<shape android:shape="oval">
<size
android:width="100dp"
android:height="100dp" />
<solid android:color="#AAE4E4EC" />
</shape>
</item>
</layer-list>
资源文件:res/drawable/shape_sweep.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size
android:width="300dp"
android:height="300dp" />
<gradient
android:endColor="#1AF4E8F8"
android:startColor="#AAF8F8F4"
android:type="sweep" />
</shape>
以上就是两种实现方式,关键点是Android动画ObjectAnimator类,这里我们使用了rotation动画,当然ObjectAnimator还支持其他如alpha等各种动画,就不细说了
结束~~~