大家好,又见面了,我是你们的朋友全栈君。
先看一下效果
两边显示上一个和下一个item部分布局,可以自动滚动
实现:
布局
主要属性:android:clipChildren=”false” //允许子布局超出父布局显示
xml代码:
Adapter
没什么特别的只要 getCount()返回一个很大的值如:return Integer.MAX_VALUE;
适配器代码:
package com.guzhc.module_demo;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;
/**
* @author : GuZhC
* @date : 2019/6/1 9:46
* @description : 顶部banner viewPager 适配器
*/
public class ShortViewoViewPagerAdapter extends PagerAdapter {
private final Context context;
private final ListmData;
private PagerClick pagerClick;
public ShortViewoViewPagerAdapter(ListmData, Context context) {
this.mData = mData;
this.context = context;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public void destroyItem(ViewGroup container, int position,
Object object) {
//Warning:不要在这里调用removeView
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
position %= mData.size();
final String data = mData.get(position);
View view = View.inflate(container.getContext(),R.layout.demo_item_short_video_viewpager, null);
ImageView img = view.findViewById(R.id.demo_img_short_video_item);
TextView tvContent = view.findViewById(R.id.demo_tv_short_video_item);
tvContent.setText(data);
Glide.with(context)
.load(“https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559367407524&di=2a7d6a1a12707287e908d61922a637c2&imgtype=0&src=http%3A%2F%2Fpic72.nipic.com%2Ffile%2F20150715%2F9448607_192612583000_2.jpg”)
.into(img);
//对ViewPager页号求模取出View列表中要显示的项
if (position < 0) {
position = mData.size() + position;
}
//如果View已经在之前添加到了一个父组件,则必须先remove,否则会抛出IllegalStateException。
ViewParent vp = view.getParent();
if (vp != null) {
ViewGroup parent = (ViewGroup) vp;
parent.removeView(view);
}
container.addView(view);
return view;
}
}
调用
注意:两边的item滑动没有效果吗,需要将容器的触摸事件反馈给ViewPager
//设置banner
shortViewoViewPagerAdapter = new ShortViewoViewPagerAdapter(mData, getContext());
View bannerView = LayoutInflater.from(getContext()).inflate(R.layout.demo_layout_short_video_banner, null);
viewPagerBanner = bannerView.findViewById(R.id.demo_vp_short_video_top);
LinearLayout mViewPagerContainer = bannerView.findViewById(R.id.demo_ll_short_video_vp_root);
viewPagerBanner.setAdapter(shortViewoViewPagerAdapter);
viewPagerBanner.addOnPageChangeListener(this);
//将容器的触摸事件反馈给ViewPager
mViewPagerContainer.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return viewPagerBanner.dispatchTouchEvent(event);
}
});
无限循环:方式很多,这里用的Handler实现
设置viewPager.addOnPageChangeListener(this)实现接口重写方法:实现滑动时候暂停自动滑动,停止的时候开启
重写方法代码:
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
handler.sendMessage(Message.obtain(handler, ImageHandler.MSG_PAGE_CHANGED, position, 0));
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
switch (state) {
//滑动中
case ViewPager.SCROLL_STATE_DRAGGING:
handler.sendEmptyMessage(ImageHandler.MSG_KEEP_SILENT);
break;
//未滑动
case ViewPager.SCROLL_STATE_IDLE:
handler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);
break;
default:
break;
}
}
Handler代码:
public class ImageHandler extends Handler {
/**
* 请求更新显示的View。
*/
protected static final int MSG_UPDATE_IMAGE = 1;
/**
* 请求暂停轮播。
*/
protected static final int MSG_KEEP_SILENT = 2;
/**
* 请求恢复轮播。
*/
protected static final int MSG_BREAK_SILENT = 3;
/**
* 记录最新的页号,当用户手动滑动时需要记录新页号,否则会使轮播的页面出错。
* 例如当前如果在第一页,本来准备播放的是第二页,而这时候用户滑动到了末页,
* 则应该播放的是第一页,如果继续按照原来的第二页播放,则逻辑上有问题。
*/
protected static final int MSG_PAGE_CHANGED = 4;
//轮播间隔时间
protected static final long MSG_DELAY = 5000;
//使用弱引用避免Handler泄露.
private WeakReferenceweakReference;
private int currentItem = 0;
protected ImageHandler(WeakReferencewk){
weakReference = wk;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
ShortVedioFragmet shortVedioFragmet = weakReference.get();
if (shortVedioFragmet==null){
//Activity已经回收,无需再处理UI了
return ;
}
//检查消息队列并移除未发送的消息,这主要是避免在复杂环境下消息出现重复等问题。
if (shortVedioFragmet.handler.hasMessages(MSG_UPDATE_IMAGE)){
shortVedioFragmet.handler.removeMessages(MSG_UPDATE_IMAGE);
}
switch (msg.what) {
case MSG_UPDATE_IMAGE:
currentItem++;
shortVedioFragmet.viewPagerBanner.setCurrentItem(currentItem);
//准备下次播放
shortVedioFragmet.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
case MSG_KEEP_SILENT:
//只要不发送消息就暂停了
break;
case MSG_BREAK_SILENT:
shortVedioFragmet.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
case MSG_PAGE_CHANGED:
//记录当前的页号,避免播放的时候页面显示不正确。
currentItem = msg.arg1;
break;
default:
break;
}
}
}
如果是viewpager嵌套Fragment的界面中使用可以通过setUserVisibleHint(boolean isVisibleToUser)方法这样开启和暂停:
setUserVisibleHint()方法会在fragment显示和隐藏的时候被调用
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser) {
//相当于OnResume(),可以做相关逻辑
//开始轮播效果
handler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);
}else {
//相当于OnPause()
//暂停轮播效果
handler.sendEmptyMessage(ImageHandler.MSG_KEEP_SILENT);
}
}
在Activity使用 可以在onResum() 和onPause()开启可暂停。
至此完成。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/129964.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...