這類問題如果細化到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)