`

缓存式的ViewPager&和其他手势控件冲突的解决办法

阅读更多
一般来说ViewPager如果有很多页的话,会加载它的上一页,当前页和下一页,当从n页以后再想回到第一页,就会再加载一次,这样第一页很多操作后的数据就会被重置,原因是在PagerAdapter的destroyItem经常会移除View,类似下面这样的代码:

@Override
        public void destroyItem(View container, int position, Object object)
        {
            // ((ViewPager) container).removeView(viewMap.get(position));//

        }


现在我不想移除它,需要让View保持原来的状态
那么就要采用一个Map用于保存View
HashMap<Integer, View> viewMap = new HashMap<Integer, View>();

然后在PagerAdapter的instantiateItem方法中如下用法:
@Override
        public Object instantiateItem(View container, int position)
        {
            View view = null;
            if (viewMap.containsKey(position))
            {
                view = viewMap.get(position);
            }
            else
            {
                view = getLayoutInflater().inflate(R.layout.item_for_gallery, null);
                viewMap.put(position, view);

                ((ViewPager) container).addView(view, 0);
}
}

这样就保证不会View不会被重置了。

伪代码如下:
package com.mobovip.bgr;

import java.util.ArrayList;
import java.util.HashMap;

import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.View;
import android.view.ViewGroup;

import com.mobovip.model.Prize;
import com.mobovip.util.Utils;

public class PrizeActivity extends BaseActivity
{

    private Context context;

    private HashMap<Integer, View> viewMap = new HashMap<Integer, View>();

    private com.mobovip.view.MyViewPager viewPager;

    private MyAdapter adapter;

    private ArrayList<Prize> prizes;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_prize);
        context = this;
        initViews();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        initValues();
    }

    @Override
    protected void onDestroy()
    {
        // TODO Auto-generated method stub
        super.onDestroy();
    }

    @Override
    protected void initViews()
    {
        // TODO Auto-generated method stub
        viewPager = (com.mobovip.view.MyViewPager) findViewById(R.id.viewPager);
        // viewPager.setOnPageChangeListener(new MyOnPageChangeListener());
    }

    @Override
    protected void initValues()
    {
        // TODO Auto-generated method stub

    }

    @Override
    protected void updateViews(Object obj)
    {
        // TODO Auto-generated method stub
        prizes = (ArrayList<Prize>) obj;
        if (prizes == null)
        {
            return;
        }

        if (adapter == null)
        {
            adapter = new MyAdapter();
            viewPager.setAdapter(adapter);
            viewPager.setCurrentItem(0);
        }
        else
        {
            adapter.notifyDataSetChanged();
        }

    }

    class MyAdapter extends PagerAdapter
    {

        @Override
        public void destroyItem(View container, int position, Object object)
        {
            // 无需removeView
            // ((ViewPager) container).removeView(viewMap.get(position));//
            // View view = (View)object;

        }

        @Override
        public void finishUpdate(View container)
        {
        }

        @Override
        public int getCount()
        {
            return prizes.size();
        }

        /**
         * 跳转到每个页面都要执行的方法
         */
        @Override
        public void setPrimaryItem(View container, int position, Object object)
        {
        }

        @Override
        public Object instantiateItem(View container, int position)
        {
            View view = null;
            if (viewMap.containsKey(position))
            {
                view = viewMap.get(position);
            }
            else
            {
                view = getLayoutInflater().inflate(R.layout.item_for_gallery, null);
                viewMap.put(position, view);
                final Prize prize = prizes.get(position);
                String format = "MM-dd-yyyy HH:mm:ss";
                int days = Utils.days(prize.getCreateTime(), getCurTime(format), format);
                prize.setExpires(prize.getExpires() - days);

                ((ViewPager) container).addView(view, 0);
                com.mobovip.view.WinView winView = (com.mobovip.view.WinView) view.findViewById(R.id.winView);
                winView.setPrize(prize);
                //处理其他逻辑
                ......
            }
            return view;
        }

        @Override
        public boolean isViewFromObject(View container, Object object)
        {
            return container == (object);
        }

        @Override
        public void restoreState(Parcelable arg0, ClassLoader arg1)
        {
        }

        @Override
        public Parcelable saveState()
        {
            return null;
        }

        @Override
        public void startUpdate(View container)
        {
        }

        @Override
        public void finishUpdate(ViewGroup container)
        {
            // TODO Auto-generated method stub
            super.finishUpdate(container);
        }

    }

}



上面有一个自定义控件WinView,是一个刮刮卡效果的类,上面有手势刮奖的效果,
现在问题是,由于ViewPager和WinView都具有手势操作的能力,所以这两个控件放在一起回发生冲突,为了防止这种冲突就需要重写一下ViewPager
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

public class MyViewPager extends ViewPager
{
    public MyViewPager(Context context)
    {
        super(context);
        // TODO Auto-generated constructor stub
    }

    public MyViewPager(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    @Override
    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y)
    {
        if (v != this && v instanceof WinView)
        {// 解决冲突
            return true;
        }
        return super.canScroll(v, checkV, dx, x, y);
    }

}


重写canScroll方法,将WinView排除在外即可。


如果不重写ViewPager,那么需要在WinView的
public boolean onTouchEvent(MotionEvent event)中写入如下语句,该方法专门用于剥夺父级控件的控制权

// 阻止父控件获得触摸操作,拦截触摸事件,防止与ViewPager等控件发生手势冲突
getParent().requestDisallowInterceptTouchEvent(true);


这样可以不用重写ViewPager了,推荐这样写(虽然我没试过!P)
分享到:
评论
2 楼 yangsiyu11 2016-06-24  
最后一句话最关键了 找了一下午
1 楼 lxh2002 2015-08-08  
感谢楼主分享,正好解决了我的问题。不过发现,
重写ViewPager的canScroll()完全正常,但在自定义View中requestDisallowInterceptTouchEvent()则无效,还没仔细研究是什么原因。

相关推荐

Global site tag (gtag.js) - Google Analytics