一、前言

<font face=黑体>当初很多 App 都有疏导页,明天咱们就利用 ViewPager 来实现疏导页,并且在疏导页中退出帧动画属性动画音乐播放等性能。

<font face=黑体>性能目录如下:

二、最终成果展现

<font face=黑体>最终成果如下所示:

三、实现步骤

3.1、引入ViewPager

<font face=黑体>布局采纳 ConstraintLayout 实现,整体还是很简略的,就是一个全屏的 ViewPager加上右上角的音乐播放按钮以及底部的小圆点。
<?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"    android:layout_width="match_parent"    android:layout_height="match_parent">    <androidx.viewpager.widget.ViewPager        android:id="@+id/mViewPager"        android:layout_width="match_parent"        android:layout_height="match_parent"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toTopOf="parent" />    <ImageView        android:id="@+id/iv_music_switch"        android:layout_width="30dp"        android:layout_height="30dp"        android:layout_marginTop="30dp"        android:layout_marginEnd="20dp"        android:src="@drawable/img_guide_music"        app:layout_constraintEnd_toStartOf="@+id/tv_guide_skip"        app:layout_constraintTop_toTopOf="parent" />    <TextView        android:id="@+id/tv_guide_skip"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_margin="30dp"        android:text="跳过"        android:textSize="20sp"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintTop_toTopOf="parent" />    <ImageView        android:id="@+id/iv_guide_point_1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginBottom="50dp"        android:src="@drawable/img_guide_point_p"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintHorizontal_bias="0.45"        app:layout_constraintStart_toStartOf="parent" />    <ImageView        android:id="@+id/iv_guide_point_2"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginBottom="50dp"        android:src="@drawable/img_guide_point"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent" />    <ImageView        android:id="@+id/iv_guide_point_3"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginBottom="50dp"        android:src="@drawable/img_guide_point"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintHorizontal_bias="0.55"        app:layout_constraintStart_toStartOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

3.2、实现 ViewPager 成果

3.2.1、引入ViewPager的三个子View

<font face=黑体>三个子View的布局都一样,这里就以一个为例子,子View的布局也很简略,就是一个图片加上一个文字。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center"    android:orientation="vertical">    <ImageView        android:id="@+id/iv_guide_star"        android:layout_width="200dp"        android:layout_height="200dp"        android:background="@drawable/guide_star_anim" />    <TextView        android:id="@+id/tv_guide_star"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="10dp"        android:text="身在井隅,心向璀璨"        android:textSize="18sp" /></LinearLayout>

3.2.2、创立ViewPager适配器

public class BasePageAdapter extends PagerAdapter {    private List<View> mList;    public BasePageAdapter(List<View> mList) {        this.mList = mList;    }    @Override    public int getCount() {        return mList.size();    }    @Override    public boolean isViewFromObject(View view, Object object) {        return view == object;    }    @Override    public Object instantiateItem(ViewGroup container, int position) {        container.addView(mList.get(position));        return mList.get(position);    }    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        container.removeView(mList.get(position));    }}

3.2.3、代码实现

public class MainActivity extends AppCompatActivity {    private ImageView iv_music_switch;    private TextView tv_guide_skip;    private ImageView iv_guide_point_1;    private ImageView iv_guide_point_2;    private ImageView iv_guide_point_3;    private ViewPager mViewPager;    private View view1;    private View view2;    private View view3;    private List<View> mPageList = new ArrayList<>();    private BasePageAdapter mPageAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();    }    private void initView() {        iv_music_switch = findViewById(R.id.iv_music_switch);        tv_guide_skip = findViewById(R.id.tv_guide_skip);        iv_guide_point_1 = findViewById(R.id.iv_guide_point_1);        iv_guide_point_2 = findViewById(R.id.iv_guide_point_2);        iv_guide_point_3 = findViewById(R.id.iv_guide_point_3);        mViewPager = findViewById(R.id.mViewPager);        view1 = View.inflate(this, R.layout.layout_pager_guide_1, null);        view2 = View.inflate(this, R.layout.layout_pager_guide_2, null);        view3 = View.inflate(this, R.layout.layout_pager_guide_3, null);        mPageList.add(view1);        mPageList.add(view2);        mPageList.add(view3);        //预加载        mViewPager.setOffscreenPageLimit(mPageList.size());        mPageAdapter = new BasePageAdapter(mPageList);        mViewPager.setAdapter(mPageAdapter);    }}

3.2.4、成果展现

<font face=黑体>当初咱们曾经实现类滑动,然而上面的小圆点并没有随着咱们的滑动而变动。

3.3、实现小圆点逻辑

<font face=黑体>小圆点的逻辑很简略,只须要去监听 ViewPager 的页面变动,而后动静的扭转小圆点的图片就能够了。

<font face=黑体>监听ViewPager的页面变动:

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {    @Override    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {    }    @Override    public void onPageSelected(int position) {        swlectPoint(position);    }    @Override    public void onPageScrollStateChanged(int state) {    }});

<font face=黑体>动静抉择小圆点:

private void swlectPoint(int position) {    switch (position) {        case 0:            iv_guide_point_1.setImageResource(R.drawable.img_guide_point_p);            iv_guide_point_2.setImageResource(R.drawable.img_guide_point);            iv_guide_point_3.setImageResource(R.drawable.img_guide_point);            break;        case 1:            iv_guide_point_1.setImageResource(R.drawable.img_guide_point);            iv_guide_point_2.setImageResource(R.drawable.img_guide_point_p);            iv_guide_point_3.setImageResource(R.drawable.img_guide_point);            break;        case 2:            iv_guide_point_1.setImageResource(R.drawable.img_guide_point);            iv_guide_point_2.setImageResource(R.drawable.img_guide_point);            iv_guide_point_3.setImageResource(R.drawable.img_guide_point_p);            break;    }}

<font face=黑体>成果展现:

<font face=黑体>能够看到,上面的小圆点曾经随着咱们的滑动而动静的变动了。

3.4、实现帧动画

<font face=黑体>帧动画的实质就是将一张张的图片,通过代码对这些图片进行间断的流动,从而造成动画。帧动画的实现能够通过 xml形式 实现和 代码形式 实现,咱们这里利用的是 xml形式 来实现的。

3.4.1、在/res/drawable新建animation-list

<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android"    android:oneshot="false">    <item android:drawable="@mipmap/img_star_1" android:duration="2000"/>    <item android:drawable="@mipmap/img_star_2" android:duration="2000"/>    <item android:drawable="@mipmap/img_star_3" android:duration="2000"/>    <item android:drawable="@mipmap/img_star_4" android:duration="2000"/>    <item android:drawable="@mipmap/img_star_5" android:duration="2000"/>    <item android:drawable="@mipmap/img_star_6" android:duration="2000"/>    <item android:drawable="@mipmap/img_star_7" android:duration="2000"/></animation-list>

3.4.2、在布局中引入

<ImageView    android:id="@+id/iv_guide_smile"    android:layout_width="200dp"    android:layout_height="200dp"    android:background="@drawable/guide_smile_anim" />

3.4.3、开启帧动画

<font face=黑体>开启帧动画须要获取背景,并将其强转成 AnimationDrawable。

 //帧动画iv_guide_star = view1.findViewById(R.id.iv_guide_star);iv_guide_night = view2.findViewById(R.id.iv_guide_night);iv_guide_smile = view3.findViewById(R.id.iv_guide_smile);//播放帧动画AnimationDrawable animStar = (AnimationDrawable) iv_guide_star.getBackground();if (!animStar.isRunning()) {    animStar.start();}AnimationDrawable animNight = (AnimationDrawable) iv_guide_night.getBackground();if (!animNight.isRunning()) {    animNight.start();}AnimationDrawable animSmile = (AnimationDrawable) iv_guide_smile.getBackground();if (!animSmile.isRunning()) {    animSmile.start();}

3.4.4、成果展现

3.5、实现音乐播放

<font face=黑体>音乐播放是用 MediaPlayer实现的,我这里封装了一个 MediaPlayerManager 音乐播放工具类,其实就是对 MediaPlayer 一些 API 的调用,源码中会提供这个工具类,这里就不细讲了,播放的音乐文件是存储在本地 raw 文件夹下的。

/*** 播放音乐 */private void startMusic() {    mGuideMusic = new MediaPlayerManager();    mGuideMusic.setLooping(true);    final AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.guide);    mGuideMusic.startPlay(file);    mGuideMusic.setOnComplteionListener(new MediaPlayer.OnCompletionListener() {        @Override        public void onCompletion(MediaPlayer mp) {            mGuideMusic.startPlay(file);        }    });}

3.6、属性动画

<font face=黑体>当咱们在播放音乐的时候,须要让音乐图片始终旋转,咱们这里就用属性动画的 ObjectAnimator 对象动画来实现。

public class AnimUtils {    /**     * 旋转动画     * @param view     * @return     */    public static ObjectAnimator rotation(View view) {        ObjectAnimator mAnim = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f);        mAnim.setDuration(2 * 1000);        mAnim.setRepeatMode(ValueAnimator.RESTART);        mAnim.setRepeatCount(ValueAnimator.INFINITE);        mAnim.setInterpolator(new LinearInterpolator());        return mAnim;    }}

<font face=黑体>在播放音乐的时候开启:

 private void startMusic() {   mGuideMusic = new MediaPlayerManager();    mGuideMusic.setLooping(true);    final AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.guide);    mGuideMusic.startPlay(file);    mGuideMusic.setOnComplteionListener(new MediaPlayer.OnCompletionListener() {        @Override        public void onCompletion(MediaPlayer mp) {            mGuideMusic.startPlay(file);        }    });    //旋转动画    mAnim = AnimUtils.rotation(iv_music_switch);    mAnim.start();}

<font face=黑体>成果展现:

能够看到音乐图片曾经在旋转了。

四、MainActivity 残缺代码

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private ImageView iv_music_switch;    private TextView tv_guide_skip;    private ImageView iv_guide_point_1;    private ImageView iv_guide_point_2;    private ImageView iv_guide_point_3;    private ViewPager mViewPager;    private View view1;    private View view2;    private View view3;    private List<View> mPageList = new ArrayList<>();    private BasePageAdapter mPageAdapter;    private ImageView iv_guide_star;    private ImageView iv_guide_night;    private ImageView iv_guide_smile;    private MediaPlayerManager mGuideMusic;    private ObjectAnimator mAnim;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();    }    private void initView() {        iv_music_switch = findViewById(R.id.iv_music_switch);        tv_guide_skip = findViewById(R.id.tv_guide_skip);        iv_guide_point_1 = findViewById(R.id.iv_guide_point_1);        iv_guide_point_2 = findViewById(R.id.iv_guide_point_2);        iv_guide_point_3 = findViewById(R.id.iv_guide_point_3);        mViewPager = findViewById(R.id.mViewPager);        iv_music_switch.setOnClickListener(this);        view1 = View.inflate(this, R.layout.layout_pager_guide_1, null);        view2 = View.inflate(this, R.layout.layout_pager_guide_2, null);        view3 = View.inflate(this, R.layout.layout_pager_guide_3, null);        mPageList.add(view1);        mPageList.add(view2);        mPageList.add(view3);        //预加载        mViewPager.setOffscreenPageLimit(mPageList.size());        mPageAdapter = new BasePageAdapter(mPageList);        mViewPager.setAdapter(mPageAdapter);        //帧动画        iv_guide_star = view1.findViewById(R.id.iv_guide_star);        iv_guide_night = view2.findViewById(R.id.iv_guide_night);        iv_guide_smile = view3.findViewById(R.id.iv_guide_smile);        //播放帧动画        AnimationDrawable animStar = (AnimationDrawable) iv_guide_star.getBackground();        animStar.start();        AnimationDrawable animNight = (AnimationDrawable) iv_guide_night.getBackground();        animNight.start();        AnimationDrawable animSmile = (AnimationDrawable) iv_guide_smile.getBackground();        animSmile.start();        //小圆点逻辑        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {            @Override            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {            }            @Override            public void onPageSelected(int position) {                seletePoint(position);            }            @Override            public void onPageScrollStateChanged(int state) {            }        });        //歌曲的逻辑        startMusic();    }    /**     * 播放音乐     */    private void startMusic() {        mGuideMusic = new MediaPlayerManager();        mGuideMusic.setLooping(true);        final AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.guide);        mGuideMusic.startPlay(file);        mGuideMusic.setOnComplteionListener(new MediaPlayer.OnCompletionListener() {            @Override            public void onCompletion(MediaPlayer mp) {                mGuideMusic.startPlay(file);            }        });        //旋转动画        mAnim = AnimUtils.rotation(iv_music_switch);        mAnim.start();    }    /**     * 动静抉择小圆点     *     * @param position     */    private void seletePoint(int position) {        switch (position) {            case 0:                iv_guide_point_1.setImageResource(R.drawable.img_guide_point_p);                iv_guide_point_2.setImageResource(R.drawable.img_guide_point);                iv_guide_point_3.setImageResource(R.drawable.img_guide_point);                break;            case 1:                iv_guide_point_1.setImageResource(R.drawable.img_guide_point);                iv_guide_point_2.setImageResource(R.drawable.img_guide_point_p);                iv_guide_point_3.setImageResource(R.drawable.img_guide_point);                break;            case 2:                iv_guide_point_1.setImageResource(R.drawable.img_guide_point);                iv_guide_point_2.setImageResource(R.drawable.img_guide_point);                iv_guide_point_3.setImageResource(R.drawable.img_guide_point_p);                break;        }    }    @Override    public void onClick(View view) {        switch (view.getId()) {            case R.id.iv_music_switch:                if (mGuideMusic.MEDIA_STATUS == MediaPlayerManager.MEDIA_STATUS_PAUSE) {                    mAnim.start();                    mGuideMusic.continuePlay();                    iv_music_switch.setImageResource(R.drawable.img_guide_music);                } else if (mGuideMusic.MEDIA_STATUS == MediaPlayerManager.MEDIA_STATUS_PLAY) {                    mAnim.pause();                    mGuideMusic.pausePlay();                    iv_music_switch.setImageResource(R.drawable.img_guide_music_off);                }                break;        }    }    @Override    protected void onDestroy() {        super.onDestroy();        mGuideMusic.stopPlay();    }}

五、源码

<font face=黑体>源码已上传至 github,有须要的能够去下载。