我记得之前写过一篇关于ViewPager+Fragment制作引导页的Blog。
使用ViewPager+Fragment制作一个简单的引导页,外加一个简易的Indicator圆形指示器
这篇文章实现的效果还不错,但是肯定比不上今天的这篇文章中最后运行的效果。
让我们重新使用ViewPager+Fragment,来制作一个Material Design(MD)风格的炫酷引导页吧。
引导页,用少量的文字表达出明确的含义,这在引导用户领域是个很讨巧的方法。简单明了的三张图片,就把APP的主要作用功能全面的展示出来,会给用户留下一种操作起来一点也不复杂的第一印象,好像只需三步就能轻轻松松满足自己的需求。可爱的界面风格也很有针对性的引起了主要客户群的兴趣,为APP整体加分不少。
引导页面的主要作用是介绍APP的基本功能,根据基础功能进行操作演示也不失为引导用户的好方法。将使用方法直接用最简单的图示按顺序展示在用户面前,一定能让用户最快速的掌握。
首先就是要添加依赖了,在Module的build.gradle文件中,添加支持库的依赖。
dependencies {
......
// design
implementation 'com.android.support:design:28.0.0'
}
然后开始编写代码,步骤如下:
- 使用ViewPager + Fragment创建引导页(FragmentPagerAdapter,Fragment)
- 当页面滑动时,控制背景色的渐变(使用ArgbEvaluator用于更新颜色,在前一个页面和后一个页面的颜色之间进行过渡。)
- 当App第一次加载时,显示引导页(使用SharedPreferences保存标记)
先看一下引导页面的布局文件activity_pager.xml
然后就是引导页的Activity文件
import android.animation.ArgbEvaluator;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import com.yunyang.yunyangblogdemo.adapter.GuidePagerAdapter;
import com.yunyang.yunyangblogdemo.utils.Utils;
public class PagerActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "yunyang";
private ViewPager mViewPager;
private Button btn_skip;
private ImageView image_indicator_zero;
private ImageView image_indicator_one;
private ImageView image_indicator_two;
private Button btn_finish;
private ImageButton mNextBtn;
private GuidePagerAdapter mGuidePagerAdapter;
private int lastLeftValue = 0;
private ImageView[] indicators;
// 当前页面位置
private int currentPage = 0;
// 是否首次进入引导页的标记
private boolean isFirstGuide;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// 沉浸式状态栏
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
// 更改状态栏颜色
getWindow().setStatusBarColor(ContextCompat.getColor(this, R.color.black_trans80));
}
setContentView(R.layout.activity_pager);
// 首次进入App,展示引导页。
isFirstGuide = Utils.readSharedSetting(PagerActivity.this, "isGuide", false);
if (isFirstGuide) {
gotoMain();
}
initView();
initMDViewPager();
}
/**
* 跳转首页
*/
private void gotoMain() {
finish();
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
/*
注意:
1、overridePendingTransition方法必须在startActivity()或者finish()方法的后面。
2、如果参数是0,表示没有动画
public void overridePendingTransition(int enterAnim, int exitAnim) {}
在A启动B时:
enterAnim:是B进入的动画
exitAnim:是A退出的动画
*/
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
private void initMDViewPager() {
mGuidePagerAdapter = new GuidePagerAdapter(getSupportFragmentManager());
mNextBtn = (ImageButton) findViewById(R.id.btn_next);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP)
mNextBtn.setImageDrawable(
Utils.tintMyDrawable(ContextCompat.getDrawable(this, R.drawable.ic_chevron_right_24dp), Color.WHITE)
);
indicators = new ImageView[]{
image_indicator_zero,
image_indicator_one,
image_indicator_two
};
mViewPager.setAdapter(mGuidePagerAdapter);
mViewPager.setCurrentItem(currentPage);
updateIndicators(currentPage);
final int color1 = ContextCompat.getColor(this, R.color.cyan);
final int color2 = ContextCompat.getColor(this, R.color.green);
final int color3 = ContextCompat.getColor(this, R.color.orange);
final int[] colorList = new int[]{color1, color2, color3};
// 使用ArgbEvaluator用于更新颜色,在前一个页面和后一个页面的颜色之间进行过渡。
final ArgbEvaluator evaluator = new ArgbEvaluator();
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// 更新颜色
int colorUpdate =
(Integer) evaluator.evaluate(
positionOffset,
colorList[position],
colorList[position == 2 ? position : position + 1]);
mViewPager.setBackgroundColor(colorUpdate);
}
@Override
public void onPageSelected(int position) {
// 更新当前角标位置
currentPage = position;
updateIndicators(currentPage);
switch (position) {
case 0:
mViewPager.setBackgroundColor(color1);
break;
case 1:
mViewPager.setBackgroundColor(color2);
break;
case 2:
mViewPager.setBackgroundColor(color3);
break;
}
btn_skip.setVisibility(position == 0 ? View.VISIBLE : View.GONE);
btn_finish.setVisibility(position == 2 ? View.VISIBLE : View.GONE);
mNextBtn.setVisibility(position == 2 ? View.GONE : View.VISIBLE);
}
@Override
public void onPageScrollStateChanged(int i) {
}
});
}
/**
* 通过切换两个不同的drawable来更新指示器。
*/
private void updateIndicators(int position) {
for (int i = 0; i < indicators.length; i++) {
indicators[i].setBackgroundResource(
i == position ? R.drawable.indicator_selected : R.drawable.indicator_unselected
);
}
}
private void initView() {
mViewPager = (ViewPager) findViewById(R.id.container);
btn_skip = (Button) findViewById(R.id.btn_skip);
image_indicator_zero = (ImageView) findViewById(R.id.image_indicator_zero);
image_indicator_one = (ImageView) findViewById(R.id.image_indicator_one);
image_indicator_two = (ImageView) findViewById(R.id.image_indicator_two);
btn_finish = (Button) findViewById(R.id.btn_finish);
mNextBtn = (ImageButton) findViewById(R.id.btn_next);
btn_skip.setOnClickListener(this);
btn_finish.setOnClickListener(this);
mNextBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_skip:
gotoMain();
break;
case R.id.btn_finish:
Utils.saveSharedSetting(PagerActivity.this, "isGuide", true);
gotoMain();
break;
case R.id.btn_next:
currentPage += 1;
if (currentPage > 2) {
currentPage = 2;
}
mViewPager.setCurrentItem(currentPage, true);
break;
default:
break;
}
}
}
注释写的很清楚,看代码完全OK的呢。
然后就是ViewPager的适配器
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.yunyang.yunyangblogdemo.fragment.GuideFragment;
/**
* 作者 yunyang
* 时间 2018/11/13 11:20
* 文件 YunyangBlogDemo
* 描述 引导页ViewPager的适配器
*/
public class GuidePagerAdapter extends FragmentPagerAdapter {
public GuidePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return GuideFragment.newInstance(position + 1);
}
@Override
public int getCount() {
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "PAGE ONE";
case 1:
return "PAGE TWO";
case 2:
return "PAGE THREE";
}
return null;
}
}
以及ViewPager中包含的Fragment文件
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.yunyang.yunyangblogdemo.R;
/**
* 作者 yunyang
* 时间 2018/11/13 11:23
* 文件 YunyangBlogDemo
* 描述 引导页ViewPager中Fragment
*/
public class GuideFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "guide_number";
private ImageView mImageView;
private int[] bgs = new int[]{
R.drawable.ic_like_24dp,
R.drawable.ic_house_24dp,
R.drawable.ic_helper_24dp};
public static GuideFragment newInstance(int sectionNumber) {
GuideFragment fragment = new GuideFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pager, container, false);
TextView textView = (TextView) view.findViewById(R.id.fragment_pager_text_label);
textView.setText(getString(R.string.guide_format, getArguments().getInt(ARG_SECTION_NUMBER)));
mImageView = (ImageView) view.findViewById(R.id.fragment_pager_img);
mImageView.setBackgroundResource(bgs[getArguments().getInt(ARG_SECTION_NUMBER) - 1]);
return view;
}
}
GuideFragment的布局文件fragment_pager.xml
以及上面所用到的工具类Utils.java文件
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.v4.graphics.drawable.DrawableCompat;
/**
* 作者 yunyang
* 时间 2018/11/13 11:39
* 文件 YunyangBlogDemo
* 描述 工具类
*/
public class Utils {
private static final String PREFERENCES_FILE = "sp_settings";
public static boolean readSharedSetting(Context context, String settingSPName, boolean defaultValue) {
SharedPreferences sharedPref = context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
return sharedPref.getBoolean(settingSPName, defaultValue);
}
public static void saveSharedSetting(Context context, String settingSPName, boolean settingValue) {
SharedPreferences sharedPref = context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean(settingSPName, settingValue);
editor.apply();
}
public static Drawable tintMyDrawable(Drawable drawable, int color) {
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(drawable, color);
DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_IN);
return drawable;
}
}
以及最后引导页结束后跳转到的首页页面。
首页布局文件
首页Activity文件
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.yunyang.yunyangblogdemo.utils.Utils;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
OK,代码编写完成后,运行一下,看一下效果图:
展示引导页面,点击“跳过”按钮,跳转到首页。
首次启动,展示引导页面,点击“跳转首页”,跳转到首页;第二次启动,直接加载首页页面。
嗯,很完美嘛。