手把手教程,先看效果,能用得上的再继续往下看……

Android实现雷达扫描效果_雷达图

注:生成的gif图扫描有点慢,下面代码有参数可以控制速度。

针对上图效果,以UI方不方便切图,可以有两种实现方式。


  • 方式一:UI将整个雷达切图(除中间头像外)

针对整个雷达图做rotation动画

完整代码:

布局文件:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http:///apk/res/android"
    xmlns:app="http:///apk/res-auto"
    xmlns:tools="http:///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(.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:///apk/res/android"
    xmlns:app="http:///apk/res-auto"
    xmlns:tools="http:///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(.ivWave)
        ivSweep = findViewById(.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:///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:///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等各种动画,就不细说了

结束~~~