这类问题如果细化到ViewPager和SwipeRefreshLayout方面,解决方法详见http://blog.csdn.net/u010386612/article/details/50548977
一般来说,HorizontalScrollView会选用一个Adapter,而且一般会用自定义的Adapter
我这里用的是我自己定义的HorizontalScrollAdapter
public abstract class BaseHorizontalAdapter
{
private HorizontalScrollMenu mHorizontalScrollMenu;
public abstract List<String> getMenuItems();
public abstract List<View> getContentViews();
public abstract void onPageChanged(int position,boolean visitStatus);
public void setHorizontalScrollMenu(HorizontalScrollMenu horizontalScrollMenu)
{
mHorizontalScrollMenu=horizontalScrollMenu;
}
public void notifyDataSetChanged()
{
mHorizontalScrollMenu.notifyDataSetChanged(this);
}
}
自定义的HorizontalScrollviewMenu,附上代码
public class HorizontalScrollMenu extends LinearLayout
{
private BaseHorizontalAdapter mAdapter;
private RadioGroup rg_items;
private List<RadioButton> rb_items = new ArrayList<RadioButton>();
private HorizontalViewPager vp_content;
private Context mContext;
private ColorStateList mColors;
private int mBackgroundResId;
private int mPaddingLeft = 20;
private int mPaddingTop = 20;
private int mPaddingRight = 20;
private int mPaddingBottom = 20;
private HorizontalScrollView hsv_menu;
private boolean[] mVisitStatus; // 菜单访问状态
private List<String> mItems; // 菜单名
private List<View> mPagers; // 内容页
private boolean mSwiped = true; // 是否可滑动
public HorizontalScrollMenu(Context context)
{
this(context, null);
// TODO Auto-generated constructor stub
}
public HorizontalScrollMenu(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
// TODO Auto-generated constructor stub
}
public HorizontalScrollMenu(Context context, AttributeSet attrs,
int defStyle)
{
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
mContext = context;
View v = LayoutInflater.from(context).inflate(
R.layout.view_horizontal_scroll_menu, this, true);
rg_items = (RadioGroup) v.findViewById(R.id.rg_items);
vp_content = (HorizontalViewPager) v.findViewById(R.id.vp_content);
mColors = getResources().getColorStateList(
R.drawable.selector_menu_item_text);
hsv_menu = (HorizontalScrollView) v.findViewById(R.id.hsv_menu);
mBackgroundResId = R.drawable.bg_rb_checked;
}
public void setAdapter(BaseHorizontalAdapter adapter)
{
if (null != adapter)
{
adapter.setHorizontalScrollMenu(this);
mAdapter = adapter;
initView(adapter);
}
}
/**
* 初始化视图
*
* @param adapter
*/
private void initView(BaseHorizontalAdapter adapter)
{
if (null == adapter)
{
return;
}
mItems = mAdapter.getMenuItems();
mVisitStatus = new boolean[mItems.size()];
initMenuItems(mItems);
mPagers = mAdapter.getContentViews();
initContentViews(mPagers);
}
/**
* 当数据集改变通知视图重绘
*
* @param adapter
*/
public void notifyDataSetChanged(BaseHorizontalAdapter adapter)
{
rg_items.removeAllViews();
rb_items.clear();
initView(adapter);
}
/**
* 初始化菜单项
*
* @param items
*/
@SuppressLint("InflateParams")
private void initMenuItems(List<String> items)
{
if (null != items && 0 != items.size())
{
rg_items.setOnCheckedChangeListener(mItemListener);
for (String str : items)
{
RadioButton rb_item = (RadioButton) LayoutInflater.from(
mContext).inflate(R.layout.view_horizontal_scroll_menu_item, null);
rb_item.setTextColor(mColors);
rb_item.setText(str);
rb_item.setTextSize(16);
rb_item.setGravity(Gravity.CENTER);
rb_item.setPadding(mPaddingLeft, mPaddingTop, mPaddingRight,
mPaddingBottom);
rg_items.addView(rb_item);
rb_items.add(rb_item);
}
rb_items.get(0).setChecked(true);
}
}
/**
* 初始化内容
*
* @param contentViews
*/
private void initContentViews(List<View> contentViews)
{
if (null == contentViews || 0 == contentViews.size())
{
return;
}
Log.i("list", ""+contentViews.size());
vp_content.setAdapter(new MyViewPagerAdapter(contentViews));
vp_content.setOnPageChangeListener(mPageListener);
}
/**
* 设置颜色变化列表
*
* @param colorListId
*/
public void setColorList(int colorListId)
{
mColors = getResources().getColorStateList(colorListId);
}
/**
* 设置菜单项状态背景
*
* @param resId
*/
public void setCheckedBackground(int resId)
{
mBackgroundResId = resId;
}
/**
* 菜单项切换监听器
*/
private OnCheckedChangeListener mItemListener = new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(RadioGroup group, int checkedId)
{
// TODO Auto-generated method stub
RadioButton btn = (RadioButton) group.findViewById(checkedId);
setMenuItemsNullBackground();
btn.setBackgroundResource(mBackgroundResId);
btn.setPadding(mPaddingLeft, mPaddingTop, mPaddingRight,
mPaddingBottom);
int position = 0;
for (int i = 0; i < rb_items.size(); i++)
{
if (rb_items.get(i) == btn)
{
position = i;
}
}
vp_content.setCurrentItem(position, mSwiped);
moveItemToCenter(btn);
if (mVisitStatus.length >= position + 1) {
mAdapter.onPageChanged(position, mVisitStatus[position]);
mVisitStatus[position] = true;
}
}
};
/**
* 内容页切换监听器
*/
private OnPageChangeListener mPageListener = new OnPageChangeListener()
{
@Override
public void onPageSelected(int arg0)
{
// TODO Auto-generated method stub
rb_items.get(arg0).setChecked(true);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
// TODO Auto-generated method stub
}
@Override
public void onPageScrollStateChanged(int state)
{
}
};
/**
* 将菜单项尽量移至中央位置
*
* @param rb
*/
private void moveItemToCenter(RadioButton rb)
{
DisplayMetrics dm = getResources().getDisplayMetrics();
int screenWidth = dm.widthPixels;
int[] locations = new int[2];
rb.getLocationInWindow(locations);
int rbWidth = rb.getWidth();
hsv_menu.smoothScrollBy((locations[0] + rbWidth / 2 - screenWidth / 2),
0);
}
/**
* 设置所有菜单项的背景为空
*/
private void setMenuItemsNullBackground()
{
if (null != rg_items)
for (int i = 0; i < rg_items.getChildCount(); i++)
{
View v = rg_items.getChildAt(i);
v.setBackgroundResource(android.R.color.transparent);
}
}
public void setMenuItemPaddingLeft(int paddingLeft)
{
mPaddingLeft = paddingLeft;
}
public void setMenuItemPaddingTop(int paddingTop)
{
mPaddingTop = paddingTop;
}
public void setMenuItemPaddingRight(int paddingRight)
{
mPaddingRight = paddingRight;
}
public void setMenuItemPaddingBottom(int paddingBottom)
{
mPaddingBottom = paddingBottom;
}
/**
* 视图页的适配器
*
* @author Administrator
*
*/
static class MyViewPagerAdapter extends PagerAdapter
{
private List<View> mViews;
public MyViewPagerAdapter(List<View> views)
{
// TODO Auto-generated constructor stub
mViews = views;
}
@Override
public int getCount()
{
// TODO Auto-generated method stub
return mViews.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1)
{
// TODO Auto-generated method stub
return arg0 == arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object)
{
// TODO Auto-generated method stub
container.removeView(mViews.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position)
{
// TODO Auto-generated method stub
container.addView(mViews.get(position));
return mViews.get(position);
}
}
public void setSwiped(boolean swiped)
{
mSwiped = swiped;
vp_content.setSwiped(swiped);
}
}
显然,onPagedChanged方法用于在HorizontalScrollMenu界面切换的时候调用。一般来讲,为了美观,会在切换(也就是onPageChanged)的时候设置SwipeRefreshLayout的小圆圈开始加载。但是事实上会报空指针,而且会发现空指针居然报在HorizontalMenu中调用Adapter处。
事实上问题所在就是滑动冲突。如果想要开始加载,常用的办法都是新开一个线程然后设置开始加载
//开始刷新动画
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
onRefreshListener.onRefresh();
}
});
解决方法:在onPageChanged中使用handler发消息,然后在接收消息之后开始刷新动画。如果在onPageChanged中刷新动画,会因为滑动冲突报空指针
(注:事实上,在界面初始化的时候,也会调用一次onPageChanged)