ViewPager是Google的support.v4包中的支持控件,可以实现View之间的切换。
ViewPager的使用在目前的应用环境中非常频繁,甚至对其进行相关的自定义来实现一些特别的效果。ViewPager最简单的使用方法,就是与PagerAdapter的配合使用,所以我们必须了解PagerAdapter中的方法及其对应的功能。
public class ViewPagerAdapter extends PagerAdapter {
/**
* 获取View的总数
*
* @return View总数
*/
@Override
public int getCount() {
return 0;
}
/**
* 当ViewPager的内容有所变化时,进行调用。
*
* @param container ViewPager本身
*/
@Override
public void startUpdate(ViewGroup container) {
super.startUpdate(container);
}
/**
* 为给定的位置创建相应的View。创建View之后,需要在该方法中自行添加到container中。
*
* @param container ViewPager本身
* @param position 给定的位置
* @return 提交给ViewPager进行保存的实例对象
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
return super.instantiateItem(container, position);
}
/**
* 为给定的位置移除相应的View。
*
* @param container ViewPager本身
* @param position 给定的位置
* @param object 在instantiateItem中提交给ViewPager进行保存的实例对象
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
/**
* ViewPager调用该方法来通知PageAdapter当前ViewPager显示的主要项,提供给用户对主要项进行操作的方法。
*
* @param container ViewPager本身
* @param position 给定的位置
* @param object 在instantiateItem中提交给ViewPager进行保存的实例对象
*/
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
}
/**
* 当ViewPager的内容变化结束时,进行调用。当该方法被调用时,必须确定所有的操作已经结束。
*
* @param container ViewPager本身
*/
@Override
public void finishUpdate(ViewGroup container) {
super.finishUpdate(container);
}
/**
* 确认View与实例对象是否相互对应。ViewPager内部用于获取View对应的ItemInfo。
*
* @param view ViewPager显示的View内容
* @param object 在instantiateItem中提交给ViewPager进行保存的实例对象
* @return 是否相互对应
*/
@Override
public boolean isViewFromObject(View view, Object object) {
return false;
}
/**
* 保存与PagerAdapter关联的任何实例状态。
*
* @return PagerAdapter保存状态
*/
@Override
public Parcelable saveState() {
return super.saveState();
}
/**
* 恢复与PagerAdapter关联的任何实例状态。
*
* @param state PagerAdapter保存状态
* @param loader 用于实例化还原对象的类加载器
*/
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
super.restoreState(state, loader);
}
/**
* 当ViewPager试图确定某个项的位置是否已更改时调用。默认有两个可选项:POSITION_UNCHANGED和POSITION_NONE。
* POSITION_UNCHANGED:给定项的位置未变更
* POSITION_NONE:给定项不再用于PagerAdapter中
* 其他值:可以根据具体的情况进行调整
*
* @param object 在instantiateItem中提交给ViewPager进行保存的实例对象
* @return
*/
@Override
public int getItemPosition(Object object) {
return super.getItemPosition(object);
}
/**
* 新增方法,目前较多用于Design库中的TabLayout与ViewPager进行绑定时,提供显示的标题。
*
* @param position 给定的位置
* @return 显示的标题
*/
@Override
public CharSequence getPageTitle(int position) {
return super.getPageTitle(position);
}
/**
* 获取给定位置的View的显示宽度比例,该比例是相对于ViewPager。
*
* @param position 给定的位置
* @return View显示的宽度比例
*/
@Override
public float getPageWidth(int position) {
return super.getPageWidth(position);
}
}
当然,这么多的方法,其实我们经常使用到的只是其中的一部分而已,我们经常使用的是下面几个方法:
public class MyViewPager extends PagerAdapter {
private List list;
public MyViewPager(List list) {
this.list = list;
}
@Override//此方法返回的是当前窗体的页面数
public int getCount() {
if (list != null && list.size() > 0) {
return list.size();
} else
return 0;
}
@Override
//重点解释一下此方法Viewpager会将每一个item添加到item中,item是一个arrayList数组,
//itemInfo是每个View相关的信息,其中的Object就是instantiateItem返回的那个Object,这个对象可以
// 不是一个View,是为了让ViewPager检查是否和View是对应的
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
@Override
//此方法返回一个对象,表明pagerAdapter选择哪个对象放在ViewPager中
public Object instantiateItem(ViewGroup container, int position) {
return super.instantiateItem(container, position);
}
@Override
//从ViewPager中移除当前的View
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
@Override
//重写这个方法是由于不重写的话调用MyViewPager().notifyDataSetChanged()不会刷新数据
//重写之后返回POSITION_NONE也就是-2就可以刷新数据了
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
下面使用ViewPager来实现一个程序引导的demo,效果图如下:
(第一次进入APP会有导航页面,实在找不到图片,视觉感觉上差了很多,诸位莫怪)
(第二次进入App就不会再进入导航页面了)
一般来说,引导界面是出现第一次运行时出现的,之后不会再出现。所以需要记录是否是第一次使用程序,办法有很多,最容易想到的就是使用SharedPreferences来保存。步骤如下:
1、程序进入欢迎界面,SplashActivity,在这里读取SharedPreferences里面的变量,先设置为true。进入引导界面,然后设置为false。
2、之后每次进入欢迎界面读取SharedPreferences里面的变量,因为是false,所以不会运行引导界面了。
代码如下:
SplashActivity.java,欢迎界面。
package com.example.forget.viewpagerdemo;
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;
public class SplashActivity extends AppCompatActivity {
boolean isfirst = true;
private static final String IS_FIRST = "frist";sharedpreference的文件名称
public static final int GO_HOME = 0x123;进入主activty的标记
public static final int GO_GUIDE = 0x124;进入导航页的标记
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
对收到的标记进行判断执行相应的方法
case GO_HOME:
goHome();
break;
case GO_GUIDE:
goGuide();
break;
}
super.handleMessage(msg);
}
};
private void goGuide() {
Intent intent = new Intent(this, GuideActivity.class);
startActivity(intent);
finish();
}
private void goHome() {
Intent intent = new Intent(this, HomeActivty.class);
startActivity(intent);
finish();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
进入闪屏页的时候进行判断,标记是否为true,若为true的话进入导航页,第一次默认标记为true
private void init() {
SharedPreferences sp = getSharedPreferences(IS_FIRST, MODE_PRIVATE);
isfirst = sp.getBoolean("isFirstIn", true);
if (isfirst) {
如果标记为true,则发送消息进入导航页
handler.sendEmptyMessageDelayed(GO_GUIDE,3000);
}
else 如果标记为false,进入主activty
handler.sendEmptyMessageDelayed(GO_HOME,3000);
}
}
对应的导航页的适配器的代码:
package com.example.forget.viewpagerdemo;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v4.view.PagerAdapter;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.util.List;
/**
* Created by Forget on 2017/1/2.
*/
public class GuideAdapter extends PagerAdapter {
private Activity activity;
private List list;
private static final String IS_FIRST = "frist";
public GuideAdapter(Activity activity, List list) {
this.activity = activity;
this.list = list;
}
@Override返回的viewpager中的页数
public int getCount() {
if (list != null && list.size() > 0) {
return list.size();
} else return 0;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override 销毁当前activity
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(list.get(position));
}
@Override设置返回的视图
public Object instantiateItem(ViewGroup container, int position) {
container.addView(list.get(position));
如果是最后一页,设置事件,使其跳转到主activity界面
if (position == list.size() - 1) {
ImageView imageView= (ImageView) container.getChildAt(position);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
将标记变成false,之后每次进入会读取此标记,不会再次进入导航页
setGuide();
跳转页面
goHome();
}
});
}
return list.get(position);
}
private void goHome() {
Intent intent = new Intent(activity, HomeActivty.class);
activity.startActivity(intent);
activity.finish();
}
private void setGuide() {
SharedPreferences sp = activity.getSharedPreferences(IS_FIRST, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean("isFirstIn", false);
editor.commit();
}
}
导航页Activty的代码:
package com.example.forget.viewpagerdemo;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
public class GuideActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {
private ViewPager viewPager;
private GuideAdapter guideAdapter;
private List list;定义适配器中需要添加的视图
private ImageView[] dots;定义底部导航图的集合
private int curretnIndex;记录当前页面的标记
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guide);
viewPager = (ViewPager) findViewById(R.id.viewpager);
initView();
guideAdapter = new GuideAdapter(this, list);
viewPager.setAdapter(guideAdapter);
viewPager.addOnPageChangeListener(this);
initData();
}
初始化需要填充到viewpager中的数据
private void initView() {
list = new ArrayList<>();
int[] imageResour = new int[]{R.mipmap.first, R.mipmap.second, R.mipmap.third};
for (int i = 0; i < imageResour.length; i++) {
ImageView imageView = new ImageView(this);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setImageResource(imageResour[i]);
imageView.setClickable(true);
list.add(imageView);
}
}
初始化需要填充到底部导航圆点的视图
private void initData() {
获取装小圆点的容器
LinearLayout ll = (LinearLayout) findViewById(R.id.group);
dots = new ImageView[guideAdapter.getCount()];
根据索引取出容器中的小圆点,并设置选择器(选择器里面设置的是state_enabled的状态),
for (int i = 0; i < dots.length; i++) {
dots[i] = (ImageView) ll.getChildAt(i);
// dots[i].setImageResource(R.mipmap.default_holo);
dots[i].setEnabled(false);
}
curretnIndex = 0;
// dots[curretnIndex].setImageResource(R.mipmap.touched_holo);
将第一页设置成选中状态
dots[curretnIndex].setEnabled(true);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (position < 0 || position > guideAdapter.getCount() - 1 || curretnIndex == position) {
return;
}
// dots[position].setImageResource(R.mipmap.touched_holo);
// dots[curretnIndex].setImageResource(R.mipmap.default_holo);
将当期的页面设置成true,即:选中状态,将前一个页面设置成未选中状态
dots[position].setEnabled(true);
dots[curretnIndex].setEnabled(false);
修改临时变量的值
curretnIndex=position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
选择器如下:我们给imageview的state_enabled(是否可用的状态)设置选择器
(注意:这里再imageView中引用的话使用background进行引用,需要配合图片使用(或者给定大小),不然会导致小圆点变形)