You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ViewPager切换引导页时播放对应Lottie动画的问题及解决方法

问题

我有一个包含3个引导页的Intro Activity,每个页面都包含一个Lottie动画,期望滑动到任意页面时,该页面的动画自动播放。当前实现滑动页面时出现错误,提示xx等变量未定义,需要正确的实现方式。

主布局 activity_welcome.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:showIn="@layout/activity_welcome">

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <LinearLayout
        android:id="@+id/layoutDots"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dots_height"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="@dimen/dots_margin_bottom"
        android:gravity="center"
        android:orientation="horizontal"
        android:visibility="gone">

    </LinearLayout>

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/btnEnter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:text="ورود"
        android:fontFamily="@font/koodak"
        android:textSize="19dp"
        android:layout_marginBottom="150dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:background="@color/appBlue"
        android:alpha="0"/>

</RelativeLayout>

引导页布局 slide.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:fontFamily="@font/aban"
            android:text="چت مت! چتِ راحت!"
            android:textColor="@color/black"
            android:textSize="25dp"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="10dp"
            android:layout_above="@id/textView2"/>

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:fontFamily="@font/koodak"
            android:text="یک پیام رسان بدون امکانات اضافه دست و پاگیر..."
            android:textSize="20dp"
            android:layout_centerHorizontal="true"
            android:layout_above="@id/animationView1" />

        <com.airbnb.lottie.LottieAnimationView
            android:id="@+id/animationView1"
            android:layout_width="229dp"
            android:layout_height="223dp"
            android:layout_centerInParent="true"
            app:lottie_autoPlay="true"
            app:lottie_fileName="chat.json"
            app:lottie_loop="false" />

    </RelativeLayout>
</RelativeLayout>

WelcomeActivity.java 原代码

public class WelcomeActivity extends AppCompatActivity {

    private ViewPager viewPager;
    private MyViewPagerAdapter myViewPagerAdapter;
    private int[] layouts;
    private PrefManager prefManager;
    LottieAnimationView xx,xx1,xx2;
//    LottieAnimationView lottieAnimationView2;

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();

        // Checking for first time launch - before calling setContentView()
        prefManager = new PrefManager(this);
        if (!prefManager.isFirstTimeLaunch()) {
            launchHomeScreen();
            finish();
        }

        // Making notification bar transparent
        if (Build.VERSION.SDK_INT >= 21) {
            getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
        }

        setContentView(R.layout.activity_welcome);

        appCompatButtonEnter = findViewById(R.id.btnEnter);

        viewPager = (ViewPager) findViewById(R.id.view_pager);

        // layouts of welcome sliders
        layouts = new int[]{
                R.layout.activity_welcome_slide1,
                R.layout.activity_welcome_slide2,
                R.layout.activity_welcome_slide3
        };
        myViewPagerAdapter = new MyViewPagerAdapter();
        viewPager.setAdapter(myViewPagerAdapter);
        viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
    }

    private int getItem(int i) {
        return viewPager.getCurrentItem() + i;
    }

    private void launchHomeScreen() {
        prefManager.setFirstTimeLaunch(true);
        startActivity(new Intent(WelcomeActivity.this, MainActivity.class));
        finish();
    }

    //  viewpager change listener
    ViewPager.OnPageChangeListener viewPagerPageChangeListener = new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            if(position == 0) {
                    View view = viewPager.getChildAt(0);
                    xx = view.findViewById(R.id.animationView1);
                }
                xx.playAnimation();
            }else if(position == 1){
                    View view = viewPager.getChildAt(1);
                    xx1 = view.findViewById(R.id.animationView2);
                    flag1 = true;
                xx1.playAnimation();
            }else {
                    View view = viewPager.getChildAt(2);
                    xx2 = view.findViewById(R.id.animationView3);
                    flag2 = true;
                xx2.playAnimation();
            }
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {

        }

        @Override
        public void onPageScrollStateChanged(int arg0) {

        }
    };

    private void changeStatusBarColor() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);
        }
    }

    public class MyViewPagerAdapter extends PagerAdapter {
        private LayoutInflater layoutInflater;

        public MyViewPagerAdapter() {
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            View view = layoutInflater.inflate(layouts[position], container, false);
            container.addView(view);

            return view;
        }

        @Override
        public int getCount() {
            return layouts.length;
        }

        @Override
        public boolean isViewFromObject(View view, Object obj) {
            return view == obj;
        }


        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            View view = (View) object;
            container.removeView(view);
        }
    }
}
解决方案

问题根源

  1. 语法错误:onPageSelected方法中if(position ==0)的代码块闭合错误,导致xx.playAnimation()处于分支外部,非0位置时xx未初始化就被调用,触发变量未定义异常。
  2. View获取不可靠:viewPager.getChildAt(position)无法稳定获取页面View,因为ViewPager仅缓存当前页和相邻页,非缓存页的View不存在。
  3. 未声明变量:appCompatButtonEnter、flag1、flag2未声明,引发编译错误。
  4. 自动播放冲突:布局中app:lottie_autoPlay="true"会导致页面初始化时自动播放,不符合滑动触发的需求。

修复实现

1. 修改引导页布局(移除自动播放)

删除Lottie标签中的app:lottie_autoPlay="true",改为手动控制:

<com.airbnb.lottie.LottieAnimationView
    android:id="@+id/animationView1"
    android:layout_width="229dp"
    android:layout_height="223dp"
    android:layout_centerInParent="true"
    app:lottie_fileName="chat.json"
    app:lottie_loop="false" />

(注:三个引导页的动画ID保持animationView1、animationView2、animationView3各自不变)

2. 修正WelcomeActivity.java

import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.airbnb.lottie.LottieAnimationView;
import java.util.ArrayList;

public class WelcomeActivity extends AppCompatActivity {

    private ViewPager viewPager;
    private MyViewPagerAdapter myViewPagerAdapter;
    private int[] layouts;
    private PrefManager prefManager;
    private Button appCompatButtonEnter;
    // 保存所有页面的View引用,确保可靠获取
    private ArrayList<View> pageViews = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();

        // 首次启动判断
        prefManager = new PrefManager(this);
        if (!prefManager.isFirstTimeLaunch()) {
            launchHomeScreen();
            finish();
            return;
        }

        // 透明状态栏
        if (Build.VERSION.SDK_INT >= 21) {
            getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
        }

        setContentView(R.layout.activity_welcome);

        appCompatButtonEnter = findViewById(R.id.btnEnter);
        viewPager = findViewById(R.id.view_pager);

        // 引导页布局数组
        layouts = new int[]{
                R.layout.activity_welcome_slide1,
                R.layout.activity_welcome_slide2,
                R.layout.activity_welcome_slide3
        };

        myViewPagerAdapter = new MyViewPagerAdapter();
        viewPager.setAdapter(myViewPagerAdapter);
        viewPager.addOnPageChangeListener(viewPagerPageChangeListener);

        // 进入页面时自动播放第一页动画
        playAnimationForPosition(0);
    }

    private int getItem(int i) {
        return viewPager.getCurrentItem() + i;
    }

    private void launchHomeScreen() {
        prefManager.setFirstTimeLaunch(true);
        startActivity(new Intent(WelcomeActivity.this, MainActivity.class));
        finish();
    }

    // ViewPager页面切换监听
    private final ViewPager.OnPageChangeListener viewPagerPageChangeListener = new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            playAnimationForPosition(position);
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) { }

        @Override
        public void onPageScrollStateChanged(int arg0) { }
    };

    // 统一处理指定位置的动画播放
    private void playAnimationForPosition(int position) {
        if (position >= pageViews.size()) return;

        View pageView = pageViews.get(position);
        LottieAnimationView lottie = null;

        // 根据页面位置匹配对应的Lottie控件
        switch (position) {
            case 0:
                lottie = pageView.findViewById(R.id.animationView1);
                break;
            case 1:
                lottie = pageView.findViewById(R.id.animationView2);
                break;
            case 2:
                lottie = pageView.findViewById(R.id.animationView3);
                break;
        }

        if (lottie != null) {
            lottie.cancelAnimation(); // 先取消之前的动画,避免重复播放
            lottie.playAnimation();
        }
    }

    private void changeStatusBarColor() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(android.graphics.Color.TRANSPARENT);
        }
    }

    // 自定义ViewPager适配器,保存页面View引用
    public class MyViewPagerAdapter extends PagerAdapter {
        private LayoutInflater layoutInflater;

        public MyViewPagerAdapter() {
            layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = layoutInflater.inflate(layouts[position], container, false);
            container.addView(view);
            pageViews.add(view); // 保存当前页面的View
            return view;
        }

        @Override
        public int getCount() {
            return layouts.length;
        }

        @Override
        public boolean isViewFromObject(View view, Object obj) {
            return view == obj;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            View view = (View) object;
            container.removeView(view);
            pageViews.remove(view); // 移除销毁页面的View引用
        }
    }
}

实现说明

  • 通过pageViews数组保存每个页面的View实例,确保能稳定获取当前页的Lottie控件。
  • playAnimationForPosition方法统一处理动画逻辑,先取消之前的动画再重新播放,避免重复播放问题。
  • 修复了原代码中的语法错误和未声明变量问题,确保编译运行正常。
  • 移除布局中的自动播放属性,完全由代码控制动画触发时机,符合滑动到页面才播放的需求。

内容的提问来源于stack exchange,提问作者Mohsen Mokhtari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 05:20:29