在实际生活中我们使用的每一款App都会有一个引导页和欢迎页面,这两个页面主要是增加用户体验,引导页是在你第一次安装该APP的时候显示的,而欢迎页你你每次进入应用的时候出现的。先了解功能,再来实现逻辑方法,首先引导页是几张不同的图片,下面会有一个表示原点,指明当前是第几页。
我们先来看效果图,万一不是你想要的,那不是浪费你宝贵的时间吗。第一次安装应用打开如下
然后是第二次进去
文章最后有项目的GIt地址,你也可以直接下载然后导入到自己AS里面,我的AS是3.0.1, 我们可以看到直接就是从欢迎页面进入到应用程序主页面了。
实现过程
从头开始 创建一个名为 GuidePageDemo 的项目 ,然后新建两个类,GuideActivity,SplashActivity,第一个类用于实现引导页,第二个用于判断APP是否为第一次进入,是就启动引导页,不是的话进入主页面。然后我们来看引导页这个Activity怎么写。
这个是整个项目的目录,一目了然,接下来我们一个一个的打开看。首先是这个GuideActivity
package lanjing.com.guidepagedemo.activity;
import android.os.Build;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
import lanjing.com.guidepagedemo.R;
import lanjing.com.guidepagedemo.adapter.GuidePageAdapter;
import lanjing.com.guidepagedemo.fragment.GuidePageOneFragment;
import lanjing.com.guidepagedemo.fragment.GuidePageThreeFragment;
import lanjing.com.guidepagedemo.fragment.GuidePageTwoFragment;
public class GuideActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
private GuidePageAdapter mPageAdapter;
private List<Fragment> mFragments;
private LinearLayout mDotLayout;
private ImageView[] dots;
private int currentIndex;
private void initView() {
mViewPager = (ViewPager) findViewById(R.id.guide_view_pager);
mDotLayout = (LinearLayout) findViewById(R.id.dots_layout);
}
private void initData() {
mFragments = new ArrayList<Fragment>();
mFragments.add(GuidePageOneFragment.newInstance());
mFragments.add(GuidePageTwoFragment.newInstance());
mFragments.add(GuidePageThreeFragment.newInstance());
mPageAdapter = new GuidePageAdapter(getSupportFragmentManager(), mFragments);
mViewPager.setAdapter(mPageAdapter);
}
private void initListeners() {
mViewPager.addOnPageChangeListener(this);
}
private void initDots() {
dots = new ImageView[mFragments.size()];
for (int i = 0; i < mFragments.size(); i++) {
dots[i] = (ImageView) mDotLayout.getChildAt(i);
if (i != 0) {
dots[i].setImageResource(R.drawable.ic_circle_dot);
}
}
currentIndex = 0;
dots[currentIndex].setImageResource(R.drawable.ic_rect_dot);
}
private void setCurrentDot(int position) {
if (position < 0 || position > mFragments.size() - 1
|| currentIndex == position) {
return;
}
dots[position].setImageDrawable(null);
dots[position].setImageResource(R.drawable.ic_rect_dot);
dots[currentIndex].setImageDrawable(null);
dots[currentIndex].setImageResource(R.drawable.ic_circle_dot);
currentIndex = position;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guide);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 透明状态栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 透明导航栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
initView();
initData();
initDots();
initListeners();
}
// 当前页面被滑动时调用
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
// 当新的页面被选中时调用
@Override
public void onPageSelected(int position) {
// 设置底部小点选中状态
setCurrentDot(position);
}
// 当滑动状态改变时调用
@Override
public void onPageScrollStateChanged(int state) {
}
}
上面有注释我就不过多, 我们初始化的时候有一个GuidePageAdapter,这是一个适配器,用于装载我们的碎片,然后配置之后就可以显示出来,然后我们看这个里面的内容:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import java.util.List;
public class GuidePageAdapter extends FragmentStatePagerAdapter {
// 界面列表
private List<Fragment> fragments;
public GuidePageAdapter(FragmentManager manager, List<Fragment> fragments) {
super(manager);
this.fragments = fragments;
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
}
这里面的内容也是比较简单,就是对碎片进行一些配置。然后我们来看这个下部原点是怎么做,这个并不是图片,而是自己画出来的,有两个文件。ic_circle_dot.xml,ic_rect_dot.xml,第一个是还未选中的状态,为白色,第二个是选中时的状态,为蓝色。 ic_circle_dot.xml内容如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!--圆角-->
<corners android:radius="4dp" />
<size
android:width="8dp"
android:height="8dp" />
<!--填充-->
<solid android:color="@android:color/white" />
</shape>
ic_rect_dot.xml内容如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!--圆角-->
<corners android:radius="4dp" />
<size
android:width="8dp"
android:height="8dp" />
<!--填充-->
<solid android:color="@android:color/holo_blue_light" />
</shape>
应该不难理解吧,这个图形的长宽为8dp ,圆角为4dp,所以效果就是一个半径4dp的圆。两个图只是颜色不一样而已,这两个文件我们在GuideActivity里已经用到了,来看一下:
private void setCurrentDot(int position) {
if (position < 0 || position > mFragments.size() - 1
|| currentIndex == position) {
return;
}
dots[position].setImageDrawable(null);
dots[position].setImageResource(R.drawable.ic_rect_dot);
dots[currentIndex].setImageDrawable(null);
dots[currentIndex].setImageResource(R.drawable.ic_circle_dot);
currentIndex = position;
}
通过碎片的大小来设置显示效果。 然后来看碎片,有三个碎片,这里展示第一个,其余用个只是明明不一样和加载的布局文件不一样而已, GuidePageOneFragment.java
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import lanjing.com.guidepagedemo.R;
public class GuidePageOneFragment extends Fragment {
public static GuidePageOneFragment newInstance() {
return new GuidePageOneFragment();
}
private void initView(View view) {
}
private void initListeners() {
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(final LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_guide_page_one,
container, false);
initView(view);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initListeners();
}
}
GuidePageTwoFragment.java
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import lanjing.com.guidepagedemo.R;
public class GuidePageTwoFragment extends Fragment {
public static GuidePageTwoFragment newInstance() {
return new GuidePageTwoFragment();
}
private void initView(View view) {
}
private void initListeners() {
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(final LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_guide_page_two,
container, false);
initView(view);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initListeners();
}
}
GuidePageThreeFragment.java
import android.content.Intent;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import lanjing.com.guidepagedemo.R;
import lanjing.com.guidepagedemo.activity.MainActivity;
public class GuidePageThreeFragment extends Fragment {
public static GuidePageThreeFragment newInstance() {
return new GuidePageThreeFragment();
}
private void initView(View view) {
}
private void initListeners() {
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(final LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_guide_page_three,
container, false);
Button openMain = (Button)view.findViewById(R.id.into_app_btn);
openMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), MainActivity.class);
startActivity(intent);
}
});
initView(view);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initListeners();
}
}
第三个的内容 就是多了一个按钮,点击这个按钮进入到主页面。然后就是是在欢迎页里面去判断你是否为第一次进入。 SplashActivity.java
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import lanjing.com.guidepagedemo.R;
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
new Thread() {
public void run() {
try {
Thread.sleep(1500);// 在欢迎界面停留1500毫秒 也就是1.5秒
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = hand.obtainMessage();
hand.sendMessage(msg);
}
}.start();
}
Handler hand = new Handler() {
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
if (isFristRun()) {
// 如果是第一次启动程序则进入引导界面
Intent intent = new Intent(SplashActivity.this,
GuideActivity.class);
startActivity(intent);
} else {
// 如果不是第一次启动则进入主页
Intent intent = new Intent(SplashActivity.this,
MainActivity.class);
startActivity(intent);
}
finish();
};
};
// 判断是否是第一次启动程序 利用 SharedPreferences 将数据保存在本地
private boolean isFristRun() {
//实例化SharedPreferences对象(第一步)
SharedPreferences sharedPreferences = this.getSharedPreferences(
"share", MODE_PRIVATE);
//实例化SharedPreferences.Editor对象(第二步)
boolean isFirstRun = sharedPreferences.getBoolean("isFirstRun", true);
SharedPreferences.Editor editor = sharedPreferences.edit();
if (!isFirstRun) {
return false;
} else {
//保存数据 (第三步)
editor.putBoolean("isFirstRun", false);
//提交当前数据 (第四步)
editor.commit();
return true;
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
}
return true;
}
}
上面都写好注释了,理解应该没问题,到此为止就写完了,对了在你的AndroidManifest.xml文件中你需要把启动程序的第一个改为SplashActivity,默认是MainActivity.如果你不设置的,刚才的东西,你是看不见效果的。我们来看一下这个文件。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="lanjing.com.guidepagedemo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".activity.MainActivity"/>
<activity android:name=".activity.GuideActivity"/>
<activity android:name=".activity.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
以上就算是写完了。
Demo地址:引导页Demo 有问题可以评论,或者私信我,尽力为你解答,不过我相信代码都有了,应该没问题的。