viewpager从入门到精通5 listview中headerview添加viewpager

看过前几篇文章后相信大家对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传送门

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值