看过前几篇文章后相信大家对viewpager的使用有了比较深入的了解上篇博客链接 viewpager从入门到精通4 优化轮播viewpager ViewPagerScroller PageTransformer 这篇博客我们重点介绍viewpager在listview中使用。
先看自定义viewpager的代码
public class MyViewPager extends ViewPager {
private static final int START_SCROLL_ANIM = 0;//开启滚动处理
private static final int STOP_SCROLL_ANIM = 1;//关闭滚动处理
private static final int LOOP_MESSAGE = 2;//循环消息
MyHeaderPagerHandler handler;
private int changePagerSpeed = 2000;//切换页面速度
private int loopSpeed = 3000;//每个item切换间隔
private boolean ifStopAnim = false;
public MyViewPager(Context context) {
this(context, null);
}
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
handler = new MyHeaderPagerHandler(new WeakReference<>(this));
setViewPagerScrollSpeed();
}
//pager切换控制--------------------------------------------------------------------------------------------------------------------------
private void setViewPagerScrollSpeed() {
try {
Field field = ViewPager.class.getDeclaredField("mScroller");
field.setAccessible(true);
ViewPagerScroller viewPagerScroller = new ViewPagerScroller(getContext(), new AccelerateDecelerateInterpolator());
field.set(this, viewPagerScroller);
viewPagerScroller.setDuration(changePagerSpeed);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
//滑动控制--------------------------------------------------------------------------------------------------------------------------
public void startScroll() {
ifStopAnim = false;
Message message = new Message();
message.what = START_SCROLL_ANIM;
handler.sendMessage(message);
}
public void startScroll(long delay) {
ifStopAnim = false;
Message message = new Message();
message.what = START_SCROLL_ANIM;
handler.sendMessageDelayed(message, delay);
}
public void stopScroll() {
ifStopAnim = true;
handler.removeCallbacksAndMessages(null);
}
private void loopMessage() {
Message message = new Message();
message.what = LOOP_MESSAGE;
handler.sendMessageDelayed(message, loopSpeed);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
getParent().requestDisallowInterceptTouchEvent(true);//这句话的作用 告诉父view,我的单击事件我自行处理,不要阻碍我。
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
stopScroll();
break;
case MotionEvent.ACTION_UP:
startScroll(6000);
break;
}
return super.onTouchEvent(ev);
}
private static class MyHeaderPagerHandler extends Handler {
private WeakReference<MyViewPager> myPager;
MyHeaderPagerHandler(WeakReference<MyViewPager> myPager) {
this.myPager = myPager;
}
@Override
public void handleMessage(Message msg) {
if (myPager.get() == null) return;
if (myPager.get().ifStopAnim) return;
super.handleMessage(msg);
switch (msg.what) {
case START_SCROLL_ANIM:
myPager.get().loopMessage();
break;
case STOP_SCROLL_ANIM:
break;
case LOOP_MESSAGE:
myPager.get().setCurrentItem(myPager.get().getCurrentItem() + 1, true);
myPager.get().loopMessage();
break;
}
}
}
}
复写dispatchTouchEvent的目的是为了告诉父布局viewpager的处理交给viewpager自己处理,onTouchEvent处理是为了防止自由滑动跟用户的滑动冲突。
然后写一个headerview作为viewpager的包裹容器。
public class MyHeaderView extends RelativeLayout {
private MyViewPager vp_header;
private List<View> headerViews;
public MyHeaderView(Context context) {
this(context, null);
}
public MyHeaderView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyHeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater.from(context).inflate(R.layout.header_view, this);
vp_header = findViewById(R.id.vp_header);
headerViews = new ArrayList<>();
}
public void initView() {
int drawables[] = {R.drawable.d_01, R.drawable.d_02, R.drawable.d_03, R.drawable.d_04, R.drawable.d_05};
for (int i = 0; i < 5; i++) {
RelativeLayout rlHeaderItem = (RelativeLayout) LayoutInflater.from(getContext()).inflate(R.layout.header_pager_view, null);
ImageView ivItem = rlHeaderItem.findViewById(R.id.iv_header_item);
ivItem.setBackgroundDrawable(getContext().getResources().getDrawable(drawables[i]));
headerViews.add(rlHeaderItem);
}
HeaderPagerAdapter adapter = new HeaderPagerAdapter(headerViews);
vp_header.setAdapter(adapter);
vp_header.setCurrentItem(headerViews.size() * 500);
vp_header.startScroll();
vp_header.addOnPageChangeListener(new MyPagerChangedListener());
}
class MyPagerChangedListener implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
}
这里有几点需要注意的因为这个headerview没用到OnPageChangeListener 但是必须指出的是onPageScrolled调用positionOffset有时可能为负数所以要略过负数的处理,OnPageChangeListener 先于onPageSelected调用什么意思呢就是当viewpager滑到第二页的时候onPageScrolled先调用后再调用onPageSelected,大家可以打log查查,还有一点是当viewpager划出界面的时候如果是自动滑动的viewpager,onPageSelected会一直调用onPageScrolled将不再调用,当迅速滑动回到viewpager的时候onPageSelected可能会连续调用两次后才会调用onPageScrolled处理,这些大家可以打log查看我在这里就不多说了。
最后是MainActivity的调用
public class MainActivity extends AppCompatActivity {
private ListView lv_main;
private MyHeaderView headerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<String> datas = new ArrayList<>();
for (int i = 0; i < 100; i++) {
datas.add("dada" + i);
}
lv_main = findViewById(R.id.lv_main);
headerView=new MyHeaderView(this);
lv_main.addHeaderView(headerView);
lv_main.setAdapter(new MyAdapter(datas));
headerView.initView();
}
private class MyAdapter extends BaseAdapter {
private List<String> datas;
private LayoutInflater inflater;
public MyAdapter(List<String> datas) {
this.datas = datas;
inflater = LayoutInflater.from(MainActivity.this);
}
@Override
public int getCount() {
return datas.size();
}
@Override
public Object getItem(int position) {
return datas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.item_main, null);
ImageView ivItem = convertView.findViewById(R.id.iv_item);
ivItem.setImageDrawable(getResources().getDrawable(R.drawable.d_0));
return convertView;
}
}
}
设置完adapter添加完header就完成了。
GitHub传送门