共计 12900 个字符,预计需要花费 33 分钟才能阅读完成。
一、前言
<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,有须要的能够去下载。