Android 欢迎页面两步实现splash+viewpager+point(详细解析+源码实例)
本篇博文对快速实现滑动欢迎页该功能详细代码与解析,读者喜欢直接上代码的,可跳过第一二点,直接奔第三点完整所有代码详细(写好注释与命名规范,方便自己或者团队方便查看与后期维护),博主早期代码,一把梭哈敲的爽,后期增加需求就MMP(谁写的代码,没点注释,看的贼难受,一看都是自己写的),后面写的时候,只要时间充裕基本写好相应注释和增加该需求时间节点
实现效果如图,本博文基于此图实现功能(指示器点,可以修改大小或者添加指定图片selector),为了节目效果,点放大于颜色鲜艳处理
一 实现页面滑动功能
了解兰博基尼(布局),加点油(代码)就可以跑(写)起来了
splash页面布局,ViewPager(滑动页)+LinearLayout(点容器)+ImageView(最后一个页面跳转按钮)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/splash_viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/bt"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@mipmap/anniu"
android:textColor="@color/white"
android:layout_marginBottom="50dp"
android:textSize="18sp"
android:visibility="invisible"
/>
<LinearLayout
android:id="@+id/splash_points"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="30dp"
android:gravity="center"
android:orientation="horizontal"/>
</RelativeLayout>
设置滑动页面数据
/**
* 初始化页面数据
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void setDatas() {
//添加背景图片
addBackgroundImg();
mViewPager.setAdapter(new SplashAdapter(mViews, this));
mViewPager.addOnPageChangeListener(new PageChangeListener());
//设置点数据
setCurDot();
}
/**
* 设置背景图
*/
private void addBackgroundImg() {
for (int i = 0; i < PICS.length; i++) {
View view = LayoutInflater.from(this).inflate(R.layout.activity_pic, null);
ImageView img = view.findViewById(R.id.img);
img.setBackgroundResource(PICS[i]);
//添加页面数据
mViews.add(view);
}
}
viewpager适配器代码
package com.kx.mysplash;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
/**
* @ 创建: kx
* @ 时间: 2018/9/17
* @ 描述:
*/
public class SplashAdapter extends PagerAdapter {
private final List<View> mData;
private final Context mContext;
public SplashAdapter(List<View> views, Context context) {
mData = views;
mContext = context;
}
/**
* 初始化item
* @param container 容器
* @param position 位置
* @return
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
//添加对应位置view到容器中
((ViewPager)container).addView(mData.get(position));
return mData.get(position);
}
/**
* 获取孩子数量
* @return
*/
@Override
public int getCount() {
return mData.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager)container).removeView(mData.get(position));
}
}
二 实现动态添加指示器功能
在LinearLayout容器,动态添加指示器(点)
/**
* 设置点数据
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void setCurDot() {
//页面大于1,才显示点
if (PICS.length > 1) {
mIvPoints = new ImageView[PICS.length];
for (int i = 0; i < mIvPoints.length; i++) {
ImageView imageView = new ImageView(this);
//图片设置属性 宽高
imageView.setLayoutParams(new ViewGroup.LayoutParams(10, 10));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
//设置左右边距
layoutParams.leftMargin = (int) getResources().getDimension(R.dimen.app_home_points_item_margin);
layoutParams.rightMargin = (int) getResources().getDimension(R.dimen.app_home_points_item_margin);
//默认第一个选中
if (i == 0) {
// imageView.setBackgroundResource(R.mipmap.page_selected_indicator);
imageView.setBackground(getResources().getDrawable(R.drawable.shape_point_solid_selcted));
} else {
// imageView.setBackgroundResource(R.mipmap.page_normal_indicator);
imageView.setBackground(getResources().getDrawable(R.drawable.shape_point_solid_normal));
}
mIvPoints[i] = imageView;
mPoints.addView(imageView, layoutParams);
}
mPoints.setVisibility(View.VISIBLE);
} else {
mPoints.setVisibility(View.GONE);
}
}
设置viewpager页面监听,处理页面对应点UI逻辑
/**
* viewpager 页面监听
*/
private class PageChangeListener implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onPageSelected(int position) {
//最后一个页面显示按钮
if (position == PICS.length - 1) {
mBt.setVisibility(View.VISIBLE);
mPoints.setVisibility(View.GONE);
} else {
mBt.setVisibility(View.GONE);
mPoints.setVisibility(View.VISIBLE);
}
// 设置底部小点选中状态
setPointBg(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
/**
* 设置点跟随页面切换切换状态
*
* @param position
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void setPointBg(int position) {
for (int i = 0; i < mIvPoints.length; i++) {
if (i==position) {
//两种方式设置
// mIvPoints[i].setBackgroundResource(R.mipmap.page_selected_indicator);
mIvPoints[i].setBackground(getResources().getDrawable(R.drawable.shape_point_solid_selcted));
} else {
//mIvPoints[i].setBackgroundResource(R.mipmap.page_normal_indicator);
mIvPoints[i].setBackground(getResources().getDrawable(R.drawable.shape_point_solid_normal));
}
}
}
三 相应完整所有代码文件
SplashActivity页面
package com.kx.mysplash;
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
/**
* @ 创建: kx
* @ 时间: 2018/9/17
* @ 描述:
*/
public class SplashActivity extends AppCompatActivity {
/**
* 引导页图片资源
*/
private static final int[] PICS = {R.mipmap.splash_01, R.mipmap.splash_02, R.mipmap.splash_03};
/**
* 滑动页视图集合
*/
private List<View> mViews = new ArrayList<>();
/**
* 指示点集合
*/
private ImageView[] dots;
/**
* 小圆点图片集合
*/
private ImageView[] mIvPoints;
private ViewPager mViewPager;
private LinearLayout mPoints;
private ImageView mBt;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
initView();
setDatas();
}
/**
* 初始化页面控件
*/
private void initView() {
//设置全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
mViewPager = findViewById(R.id.splash_viewPager);
mPoints = findViewById(R.id.splash_points);
mBt = findViewById(R.id.bt);
mBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
}
});
}
/**
* 初始化页面数据
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void setDatas() {
//添加背景图片
addBackgroundImg();
mViewPager.setAdapter(new SplashAdapter(mViews, this));
mViewPager.addOnPageChangeListener(new PageChangeListener());
//设置点数据
setCurDot();
}
/**
* 设置点数据
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void setCurDot() {
//页面大于1,才显示点
if (PICS.length > 1) {
mIvPoints = new ImageView[PICS.length];
for (int i = 0; i < mIvPoints.length; i++) {
ImageView imageView = new ImageView(this);
//图片设置属性 宽高
imageView.setLayoutParams(new ViewGroup.LayoutParams(10, 10));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
//设置左右边距
layoutParams.leftMargin = (int) getResources().getDimension(R.dimen.app_home_points_item_margin);
layoutParams.rightMargin = (int) getResources().getDimension(R.dimen.app_home_points_item_margin);
//默认第一个选中
if (i == 0) {
// imageView.setBackgroundResource(R.mipmap.page_selected_indicator);
imageView.setBackground(getResources().getDrawable(R.drawable.shape_point_solid_selcted));
} else {
// imageView.setBackgroundResource(R.mipmap.page_normal_indicator);
imageView.setBackground(getResources().getDrawable(R.drawable.shape_point_solid_normal));
}
mIvPoints[i] = imageView;
mPoints.addView(imageView, layoutParams);
}
mPoints.setVisibility(View.VISIBLE);
} else {
mPoints.setVisibility(View.GONE);
}
}
/**
* 设置背景图
*/
private void addBackgroundImg() {
for (int i = 0; i < PICS.length; i++) {
View view = LayoutInflater.from(this).inflate(R.layout.activity_pic, null);
ImageView img = view.findViewById(R.id.img);
img.setBackgroundResource(PICS[i]);
//添加页面数据
mViews.add(view);
}
}
/**
* viewpager 页面监听
*/
private class PageChangeListener implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onPageSelected(int position) {
//最后一个页面显示按钮
if (position == PICS.length - 1) {
mBt.setVisibility(View.VISIBLE);
mPoints.setVisibility(View.GONE);
} else {
mBt.setVisibility(View.GONE);
mPoints.setVisibility(View.VISIBLE);
}
// 设置底部小点选中状态
setPointBg(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
/**
* 设置点跟随页面切换切换状态
*
* @param position
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void setPointBg(int position) {
for (int i = 0; i < mIvPoints.length; i++) {
if (i==position) {
//两种方式设置
// mIvPoints[i].setBackgroundResource(R.mipmap.page_selected_indicator);
mIvPoints[i].setBackground(getResources().getDrawable(R.drawable.shape_point_solid_selcted));
} else {
// mIvPoints[i].setBackgroundResource(R.mipmap.page_normal_indicator);
mIvPoints[i].setBackground(getResources().getDrawable(R.drawable.shape_point_solid_normal));
}
}
}
}
splash对应页面布局代码activity_splash.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/splash_viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/bt"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@mipmap/anniu"
android:textColor="@color/white"
android:layout_marginBottom="50dp"
android:textSize="18sp"
android:visibility="invisible"
/>
<LinearLayout
android:id="@+id/splash_points"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="30dp"
android:gravity="center"
android:orientation="horizontal"/>
</RelativeLayout>
viewpager用到的SplashAdapter
package com.kx.mysplash;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
/**
* @ 创建: kx
* @ 时间: 2018/9/17
* @ 描述:
*/
public class SplashAdapter extends PagerAdapter {
private final List<View> mData;
private final Context mContext;
public SplashAdapter(List<View> views, Context context) {
mData = views;
mContext = context;
}
/**
* 初始化item
* @param container 容器
* @param position 位置
* @return
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
//添加对应位置view到容器中
((ViewPager)container).addView(mData.get(position));
return mData.get(position);
}
/**
* 获取孩子数量
* @return
*/
@Override
public int getCount() {
return mData.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager)container).removeView(mData.get(position));
}
}
添加页面 背景用到的activity_pic.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
相应指示器选中和未选中 资源文件shape_point_solid_normal.xml 与shape_point_solid_selcted.xml
shape_point_solid_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<!-- 高度 -->
<size android:height="15dp" android:width="15dp"/>
<!-- 圆角弧度 -->
<corners android:radius="50dp"/>
<solid android:color="@color/color_f5f5f5"/>
</shape>
shape_point_solid_selcted.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<!-- 高度 -->
<size android:height="15dp" android:width="15dp"/>
<!-- 圆角弧度 -->
<corners android:radius="50dp"/>
<solid android:color="@color/color_009ffa"/>
</shape>
还有dimens.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="app_home_points_item_margin">4dp</dimen>
</resources>
四 博文对应Demo实例一个
本文对应实例Demo,提供给有需要的读者(有不少读者都会跟博主要相应博文的Demo学习分享用,所有博主时间上允许都会把Demo抽取出来)
五 尾言
本文仅供学习与分享使用,如有不当之处与bug,请读者不吝赐教,谢谢