缓存式的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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值