ViewPager一般来说都是用于完成图片的翻页,画面的翻页之类的效果。
布局文件:外层是一个相对布局
<androidx.viewpager.widget.ViewPager
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="@+id/vp_main"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_alignBottom="@+id/vp_main"
android:background="#44000000"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="标题信息"
android:textColor="#ffffff"
android:gravity="center"
android:id="@+id/tv_main"/>
<LinearLayout
android:id="@+id/ll_point"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
对应的java:
public class MyViewPager extends AppCompatActivity {
private ViewPager vp_main;
private TextView tv_main;
private LinearLayout ll_point;
private MyPagerAdapter myPagerAdapter;
private MyImage myImage;
private List<ImageView> imageViews;
//得到上一个位置
private int prePosition=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_view_pager);
vp_main=(ViewPager)findViewById(R.id.vp_main);
tv_main=(TextView)findViewById(R.id.tv_main);
ll_point=(LinearLayout)findViewById(R.id.ll_point);
imageViews=new ArrayList<ImageView>();
myImage=new MyImage();
for(int i=0;i<myImage.getImage.length;i++){
ImageView imageView=new ImageView(this);
imageView.setBackgroundResource(myImage.getImage[i]);
imageViews.add(imageView);
//下面点操作,包括添加点,设置颜色,设置间距。还有就是通过viewpager改变颜色
ImageView point_main=new ImageButton(this);
point_main.setBackgroundResource(R.drawable.point_background);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(25, 25);
if(i==0){
point_main.setEnabled(true);
}else {
point_main.setEnabled(false);
layoutParams.leftMargin=60;
}
point_main.setLayoutParams(layoutParams);
ll_point.addView(point_main);
//----------------------------------------------//
}
//初始化适配器
myPagerAdapter=new MyPagerAdapter(this,imageViews);
//设置适配器
vp_main.setAdapter(myPagerAdapter);
//设置监听
vp_main.addOnPageChangeListener(new MyClickListener());
}
}
然后就是适配器:
在继承适配器时,它不会强制让你实现四个主要方法。但是还是得实现四个方法。所以这四个方法可以将鼠标移动到
PagerAdapter(也就是继承类)。然后ctrl+q。有四个方法写在那里
public class MyPagerAdapter extends PagerAdapter {
private Context context;
private List<ImageView> data;
public MyPagerAdapter(Context context, List<ImageView> data) {
this.context = context;
this.data = data;
}
/**
* @return 得到图片的总数
*/
@Override
public int getCount() {
return data.size();
}
/***
*比较View和Oject是否同一实例
* @param view 页面
* @param object 这个方法instantiateItem返回的结果
* @return
*/
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view==object;
}
/**
*释放资源,因为Viewpage最多加载3个页面。开始是加载两个。果然不释放资源切换之后会报错闪退。
* @param container Viewpager
* @param position 要释放的位置
* @param object 要释放的页面
*/
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}
/**
*相当于getView方法
* @param container Viewpager自身
* @param position 当前实例化位置
* @return
*/
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
ImageView imageView=data.get(position);
container.addView(imageView);
return imageView;
}
}
设置viewpage监听
public class MyClickListener implements ViewPager.OnPageChangeListener {
/**
*当页面滑动的时候回调这个方法
* @param position 当前页面的位置
* @param positionOffset 滑动页面的百分比
* @param positionOffsetPixels 在屏幕上滑动的像素
*/
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
/**
*当某个页面呗选中了回调
* @param position 被选中页面的位置
*/
@Override
public void onPageSelected(int position) {
ll_point.getChildAt(prePosition).setEnabled(false);
ll_point.getChildAt(position).setEnabled(true);
prePosition=position;
}
/**
* 当页面滑动状态变化的时候回调这个方法
* 静止-》滑动 滑动-》静止 静止-》拖拽
* @param state
*/
@Override
public void onPageScrollStateChanged(int state) {
}
}
如果设置可以无限拖动。
则该适配器得代码改一下:
public Object instantiateItem(@NonNull ViewGroup container, int position) {
//求余得到位置
int realPosition=position%data.size();
ImageView imageView=data.get(realPosition);
container.addView(imageView);
return imageView;
}
public int getCount() {
//return data.size();
return Integer.MAX_VALUE;
}
还有就是修改一下监听的代码:
public void onPageSelected(int position) {
int realPosition=position%imageViews.size();
ll_point.getChildAt(prePosition).setEnabled(false);
ll_point.getChildAt(realPosition).setEnabled(true);
prePosition=realPosition;
}
设置自动滑动页面:
原理利用handler:
handler代码:
private Handler handler=new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if(msg.what==GET_TIME) {
//得到viewpager当前页面值+1
int currentItem = vp_main.getCurrentItem() + 1;
//设置当前页面值
vp_main.setCurrentItem(currentItem);
//循环发延时消息
handler.sendEmptyMessageDelayed(GET_TIME, 5000);
}
}
};
还有就是在主方法里面加入一条开启发延时消息
handler.sendEmptyMessageDelayed(GET_TIME, 5000);
设置viewpager的滑动监听,包括点击,滑动,离开,还有取消。
在适配去的instantiateItem方法里面添加
imageView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN://手指按下
break;
case MotionEvent.ACTION_MOVE://移动
break;
case MotionEvent.ACTION_UP://手指离开
break;
case MotionEvent.ACTION_CANCEL://页面拖后时,会触发对上一个页面操作的取消,因为上个页面触发了按下,但是按下和离开时绑定一起的连贯的动作
break;
}
return true;
}
});
练习:
添加点击时不会自动滑动:
imageView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN://手指按下
Log.e("TAG", "手指点击");
handler.removeCallbacksAndMessages(null);
break;
case MotionEvent.ACTION_MOVE://移动
Log.e("TAG", "手指移动");
break;
case MotionEvent.ACTION_UP://手指离开
Log.e("TAG", "手指离开");
break;
case MotionEvent.ACTION_CANCEL://页面拖后时,会触发对上一个页面操作的取消,因为上个页面触发了按下,但是按下和离开时绑定一起的连贯的动作
Log.e("TAG", "页面取消");
break;
}
return true;
}
});
原理是:当我们点下去的时候。触发点击,拖到一半回来,触发取消。所以不会触发离开的动作。
并在viewpager监听中修改函数:
/**
* 当页面滑动状态变化的时候回调这个方法
* 静止-》滑动 滑动-》静止 静止-》拖拽
* @param state
*/
private boolean isDragging;
@Override
public void onPageScrollStateChanged(int state) {
if(state==ViewPager.SCROLL_STATE_IDLE){//静止的时候
Log.e("TAG", "SCROLL_STATE_IDLE");
isDragging=true;
handler.removeCallbacksAndMessages(null);
handler.sendEmptyMessageDelayed(GET_TIME, 5000);
}else if(state==ViewPager.SCROLL_STATE_DRAGGING&&isDragging){//拉的时候
isDragging=false;
Log.e("TAG", "SCROLL_STATE_DRAGGING");
handler.removeCallbacksAndMessages(null);
}else if(state==ViewPager.SCROLL_STATE_SETTLING){//用户手放开的时候 Log.e("TAG", "SCROLL_STATE_SETTLING");
}
}
上面代码private boolean isDragging;这个我作用还不是太清楚。好像有没有作用都一样。以后搞明白了再来。
设置点击事件:
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, ""+position%data.size(), Toast.LENGTH_SHORT).show();
}
});
为了完成点击监听,记得把触摸监听返回设置位false,这样就不会被触摸监听消费了。才可以完成触发点击监听
为切换ViewPager设置动画
这里做的是一个缩放的动画
vp_main.setPageTransformer(true, new ScaleTransformer());
第一个参数不知道是什么,没研究过,第二个参数是自定义动画类
public class ScaleTransformer implements ViewPager.PageTransformer {
private static float MIN_CONTENT=0.75f;
@Override
public void transformPage(@NonNull View page, float position) {
if(position<-1){
page.setScaleX(MIN_CONTENT);
page.setScaleY(MIN_CONTENT);
}else if(position<=1){
//左边页面
if(position<0){
//a->b:(0,-1)
float v = MIN_CONTENT + (1 - MIN_CONTENT) * (1 + position);
page.setScaleX(v);
page.setScaleY(v);
}else {//右边页面
//a->b:(1,0)
float v = MIN_CONTENT + (1 - MIN_CONTENT) * (1 - position);
page.setScaleX(v);
page.setScaleY(v);
}
}else {
page.setScaleX(MIN_CONTENT);
page.setScaleY(MIN_CONTENT);
}
}
}