一、前言
<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,有须要的能够去下载。