App下载下来第一次进入时,一般情况都会有一个欢迎界面,滑动过几个界面后才会真正进入到应用中去。今天主要是利用ViewPager来制作欢迎界面。主要思路是:点击app时进入启动界面,然后判断是否第一次打开app,是则转到欢迎界面,否则直接转到应用主界面。换言之,我们重点关注的就是启动界面和欢迎界面。
一般而言,启动跟欢迎界面大部分是全屏显示的,所以我们需要通过setSystemUiVisibility来实现全屏的功能。下面我们一步一步来讲解如果使用ViewPager实现App欢迎界面。
启动界面
我们打开App的时候,有时看到有一个Logo显示的界面,比如打开微博或者赤兔时,会看到app先在Logo页停留一段时间,然后才会进入到主界面中,如果是第一次打开app时,还会先进入到一个欢迎界面,之后再跳转。看起来有点绕口,还是直接看代码吧。
// WelcomeActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
imageView = findViewById(R.id.imgWelcome);
// 下面的代码实现全屏
imageView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
);
// 对显示的图片进行压缩处理,否则容易造成OOM问题
bitmap = GuideActivity.readBitMap(this, R.drawable.img_welcome);
((ImageView)imageView).setImageBitmap(bitmap);
// 本地记录是否第一次打开app
SharedPreferences sharedPreferences = getSharedPreferences("config", Context.MODE_PRIVATE);
isFirstIn = sharedPreferences.getBoolean("isFirstIn", true);
if (isFirstIn){
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("isFirstIn", false);
editor.apply();
// 第一次打开,跳转到欢迎界面
// 这里利用handler来实现延迟跳转
handler.sendEmptyMessageDelayed(GO_GUIDE, TRANSLATE_DELAY);
} else {
// 非第一次打开,跳转到主界面
handler.sendEmptyMessageDelayed(GO_MAIN, TRANSLATE_DELAY);
}
}
// 通过msg.what接受消息,判断跳转到那个页面
// goMain跟goGuide两个函数很简单,就是利用intent和startActivity
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == GO_MAIN){
goMain();
} else {
goGuide();
}
}
};
启动界面到这里就完成了,调用setSystemUiVisibility实现全屏效果,其他都很简单。还有一点要注意的就是,为了全屏效果看起来不会太过生硬(启动白屏问题),我们需要设置一下主题,然后在AndroidManifest里面修改对应的theme属性。这里直接贴出style的代码
<style name="AppLoad" parent="AppTheme.NoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
接下我们看看欢迎界面,这也是本文的重点。主要是ViewPager的使用
欢迎界面
欢迎界面显示三张图片,滑动到最后一张图片后,点击按钮,进入主界面。滑动的功能通过ViewPager来实现,layout的代码这里就补贴出来了,比较简单,跟之前blog介绍过的很相似。滑动时底部显示的点可以通过shape来实现
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"
android:useLevel="false">
<solid android:color="@android:color/white" />
<size
android:width="5dp"
android:height="5dp" />
</shape>
下面是GuideActivity的主要代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guide);
textView = findViewById(R.id.textView);
textView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
initView();
initDots();
}
public void initView(){
viewPager = (ViewPager) findViewById(R.id.viewPager);
// adapter里面是需要显示的内容
viewPager.setAdapter(new MyViewPagerAdapter(this));
// 滑动时触发
viewPager.setOnPageChangeListener(this);
}
// 初始化点图案,在滑动的时候,底部显示点点,表明现在所处位置
// 这里的点不是图片资源,而是通过shape生成的
public void initDots(){
dots = new ImageView[ids.length];
for (int i = 0; i < ids.length; i++){
dots[i] = (ImageView) findViewById(ids[i]);
}
@Override
public void onPageSelected(int position) {
for (int i = 0; i < ids.length; i++){
if (i == position){
dots[i].setImageResource(R.drawable.dot_red);
}else {
dots[i].setImageResource(R.drawable.dot_white);
}
}
}
MyViewPagerAdapter继承至PagerAdapter需要复写instantiateItem
、destroyItem
、 getCount
、isViewFromObject
这几个方法,还要有一个构造函数
public MyViewPagerAdapter(Context context) {
this.context = context;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// 把布局文件加载rootView中
LayoutInflater inflater = LayoutInflater.from(context);
rootView = inflater.inflate(R.layout.three,container,false);
Button button = (Button) rootView.findViewById(R.id.btnStart);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(context, MainActivity.class);
context.startActivity(intent);
}
});
if (position == imgDrawableResource.length - 1){
button.setVisibility(View.VISIBLE);
} else {
button.setVisibility(View.GONE);
}
imageView = (ImageView) rootView.
findViewById(R.id.imgThree);
bitmap = GuideActivity.readBitMap(context, imgDrawableResource[position]);
imageView.setImageBitmap(bitmap);
// 把rootView添加到主容器中,即GuideActivity中
container.addView(rootView);
return rootView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
Bitmap bm = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
if (bm !=null && !bm.isRecycled()){
bm.recycle();
bm = null;
Log.e("GuideActivity", "destroyItem");
}
}
@Override
public int getCount() {
// 返回需要显示的图片的张数
return imgDrawableResource.length;
}
@Override
public boolean isViewFromObject(View view, Object object) {
// 没有这个,图片无法显示
return view == object;
}
利用ViewPager简单地实现了欢迎界面,但还有很多地方可以改进,比如图片的加载、缓存,如何解决OOM问题,启动界面时,通过线程加载本地数据等等,这些以后碰到的时候再来讨论。