如何在ViewPager中设置多View?解决数组越界异常问题
修复ViewPager每页显示3个Item的PagerAdapter问题
看了你的代码,问题出在索引计算逻辑完全混乱——你一开始把页面位置position乘以2,这和每页3个Item的需求完全不匹配,后面的越界判断(比如position==getRealCount()时取position-1、position-2)也逻辑错误,直接导致了IndexOutOfBoundException。
我帮你重新梳理了逻辑,核心思路是:
- 每个页面的起始索引是
页面位置 * 每页数量(也就是position * 3) - 依次处理当前页面的3个Item,每个Item的索引是
startIndex、startIndex+1、startIndex+2 - 对每个索引,判断是否小于数据总长度,符合条件就填充数据并显示,否则隐藏该Item
以下是修正后的完整代码:
public class SummaryViewPagerAdapter extends PagerAdapter { private List<SummaryModel> mSummaryModelList; private Context context; private LayoutInflater inflater; public SummaryViewPagerAdapter(Context context, List<SummaryModel> summaryModels ) { this.mSummaryModelList = summaryModels; this.context = context; this.inflater = LayoutInflater.from(context); // 提前初始化LayoutInflater,避免重复获取 } @Override public int getCount() { // 计算总页数:向上取整,比如5条数据就是2页 return (mSummaryModelList.size() + 3 - 1) / 3; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } private void populateTextView(TextView statusTxt, TextView statusCount, String status, String color, RelativeLayout layout, String count) { statusTxt.setText(status); statusCount.setText(count); layout.setBackgroundColor(Color.parseColor(color)); // 填充数据后直接设置可见,不用重复写 statusTxt.setVisibility(View.VISIBLE); statusCount.setVisibility(View.VISIBLE); layout.setVisibility(View.VISIBLE); } @Override public Object instantiateItem(ViewGroup container, int position) { View itemView = inflater.inflate(R.layout.summary_viewholder, container, false); // 计算当前页面的起始索引 int startIndex = position * 3; int realCount = getRealCount(); // 处理第一个Item TextView statusTxt1 = itemView.findViewById(R.id.txt_1); TextView countTxt1 = itemView.findViewById(R.id.count_1); RelativeLayout rl1 = itemView.findViewById(R.id.rl_1); if (startIndex < realCount) { SummaryModel model = mSummaryModelList.get(startIndex); populateTextView(statusTxt1, countTxt1, model.getName(), model.getColorCode(), rl1, String.valueOf(model.getCount())); } else { statusTxt1.setVisibility(View.INVISIBLE); countTxt1.setVisibility(View.INVISIBLE); rl1.setVisibility(View.INVISIBLE); } // 处理第二个Item TextView statusTxt2 = itemView.findViewById(R.id.txt_2); TextView countTxt2 = itemView.findViewById(R.id.count_2); RelativeLayout rl2 = itemView.findViewById(R.id.rl_2); int secondIndex = startIndex + 1; if (secondIndex < realCount) { SummaryModel model = mSummaryModelList.get(secondIndex); populateTextView(statusTxt2, countTxt2, model.getName(), model.getColorCode(), rl2, String.valueOf(model.getCount())); } else { statusTxt2.setVisibility(View.INVISIBLE); countTxt2.setVisibility(View.INVISIBLE); rl2.setVisibility(View.INVISIBLE); } // 处理第三个Item TextView statusTxt3 = itemView.findViewById(R.id.txt_3); TextView countTxt3 = itemView.findViewById(R.id.count_3); RelativeLayout rl3 = itemView.findViewById(R.id.rl_3); int thirdIndex = startIndex + 2; if (thirdIndex < realCount) { SummaryModel model = mSummaryModelList.get(thirdIndex); populateTextView(statusTxt3, countTxt3, model.getName(), model.getColorCode(), rl3, String.valueOf(model.getCount())); } else { statusTxt3.setVisibility(View.INVISIBLE); countTxt3.setVisibility(View.INVISIBLE); rl3.setVisibility(View.INVISIBLE); } container.addView(itemView); return itemView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); // 这里改成View更通用,避免强转LinearLayout报错 } private int getRealCount() { return mSummaryModelList.size(); } }
关键改进点:
- 提前初始化
LayoutInflater,避免在instantiateItem中重复获取系统服务,优化性能 - 用
startIndex = position * 3计算页面起始索引,逻辑清晰,不会越界 - 每个Item的索引单独计算(
startIndex、startIndex+1、startIndex+2),判断是否小于数据总数,逻辑简单直接 - 修复了
destroyItem中的强转问题,改成View更通用 - 简化了
populateTextView方法,填充数据后直接设置可见,减少重复代码
这样修改后,当数据长度为5时:
- 第0页(第一页)的索引是0、1、2,显示3个Item
- 第1页(第二页)的索引是3、4、5,其中5超出数据长度(总数5,索引最大是4),所以第三个Item隐藏,显示前2个,完全符合你的需求。
内容的提问来源于stack exchange,提问作者M.Yogeshwaran
相关产品推荐
相关产品推荐

