Android ListView 多种布局–进阶一 中提及了这么一个需求,本博文就这个需求的实现做进一步探讨。
前面是单列,后面是双列的情况,使用ListView实现,一般的解决思路是处理getView和getCount方法,如下实现:
- 首先实现Adapter,处理getView和getCount方法
public class DoubleAdapter extends BaseAdapter implements OnClickListener{ private List<String> mDataList = new ArrayList<String>(); private Context mContext; private final static int PRESIZE = 5; public DoubleAdapter(Context context,List<String> datas){ this.mContext = context; this.mDataList = datas; } @Override public int getCount() { return PRESIZE + (mDataList.size()- PRESIZE) % 2 == 0 ? (mDataList.size()- PRESIZE) / 2 : (mDataList.size()- PRESIZE) / 2 + 1; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return position; } @SuppressLint("InflateParams") @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHodler hodler = null; if(convertView == null){ hodler = new ViewHodler(); LayoutInflater inflater = LayoutInflater.from(mContext); convertView = inflater.inflate(R.layout.item, null); hodler.textView1 = (TextView) convertView.findViewById(R.id.text1); hodler.textView2 = (TextView) convertView.findViewById(R.id.text2); hodler.layout1 = (LinearLayout) convertView.findViewById(R.id.item_layout1); hodler.layout2 = (LinearLayout) convertView.findViewById(R.id.item_layout2); convertView.setTag(hodler); }else{ hodler = (ViewHodler) convertView.getTag(); } if (position >= PRESIZE ) { String item1 = ""; String item2 = ""; if(position * 2 + 1< mDataList.size()){ item1 = mDataList.get(position * 2 - PRESIZE); item2 = mDataList.get(position * 2 + 1 - PRESIZE); }else if(position * 2 + 1== mDataList.size()){ item1 = mDataList.get(position * 2 - PRESIZE); item2 = ""; } if(item1 != null){ hodler.textView1.setText(item1); hodler.layout1.setOnClickListener(this); hodler.layout1.setTag(item1); } if(item2 != null){ hodler.textView2.setText(item2); hodler.layout2.setOnClickListener(this); hodler.layout2.setTag(item2); } }else { String item = mDataList.get(position); hodler.textView1.setText(item); hodler.layout1.setOnClickListener(this); hodler.layout1.setTag(item); hodler.textView2.setText(""); hodler.layout2.setOnClickListener(this); hodler.layout2.setTag(""); } return convertView; } class ViewHodler { TextView textView1; TextView textView2; LinearLayout layout1; LinearLayout layout2; } @Override public void onClick(View v) { Toast.makeText(mContext, v.getTag().toString(), Toast.LENGTH_SHORT).show(); }}
- 接着是Activity将数据绑定View
public class DoubleListViewActivity extends Activity { private List<String> datas; private ListView listView; private DoubleAdapter adapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); getData(); initView(); } private void initView(){ listView = (ListView) findViewById(R.id.listView); adapter = new DoubleAdapter(this, datas); listView.setAdapter(adapter); } private void getData(){ datas = new ArrayList<String>(); for(int i = 0;i < 60;i++){ datas.add("NO:"+i); } }}
我们来看看关键的实现点:
@Overridepublic int getCount() { return PRESIZE + (mDataList.size()- PRESIZE) % 2 == 0 ? (mDataList.size()- PRESIZE) / 2 : (mDataList.size()- PRESIZE) / 2 + 1;}@SuppressLint("InflateParams")@Overridepublic View getView(int position, View convertView, ViewGroup parent) { ViewHodler hodler = null; if(position * 2 + 1< mDataList.size()){ item1 = mDataList.get(position * 2 - PRESIZE); item2 = mDataList.get(position * 2 + 1 - PRESIZE); }else if(position * 2 + 1== mDataList.size()){ item1 = mDataList.get(position * 2 - PRESIZE); item2 = ""; }}
小结一下上面的实现思路: 主要是重新计算getCount,不满足偶数的补充一个, 重新绑定数据,每行绑定两个数据,然后一个Holder初始化对应的itemView,再更新到view上去。
上面的实现思路只能说很一般,比较麻烦的是计算getCount和getView的处理,有木有更好的方式处理一行两列的ListView思路呢?
当然有的,其实很简单,就是从数据端入手,而不是像上面那样从绑定到View处着手,那么从数据端该如何着手呢,其实就是将原有的数据封装一下,每两个bean封装成一个bean,接下来绑定过程和普通的Adapter一样,这样说是不是问题就迎刃而解了,简单看一下实现吧
- 首先将数据封装一下
public static final class BrandRecommedProduct { private ProductBean productLeft; private ProductBean productRight; public BrandRecommedProduct() { } public BrandRecommedProduct(ProductBean productLeft, ProductBean productRight) { this.productLeft = productLeft; this.productRight = productRight; } public ProductBean getProductLeft() { return productLeft; } public void setProductLeft(ProductBean productLeft) { this.productLeft = productLeft; } public ProductBean getProductRight() { return productRight; } public void setProductRight(ProductBean productRight) { this.productRight = productRight; }}
- 接着初始化List数据(将奇数数据去掉最后一个保持始终偶数个数据)
private void updateRecommendProducts(List<ProductBean> recommendProducts) { int size = 0; if (recommendProducts != null && (size = recommendProducts.size()) > 0) { mDataList.add(BrandDetailAdapter.RECOMMEND_PRODUCT_TITLE); mRecommendProductSize = size % 2 == 0 ? size : size -1; for (int i = 0; i < size; i++) { if (size % 2 == 0) { BrandRecommedProduct product = new BrandRecommedProduct(); product.setProductLeft(recommendProducts.get(i)); i++; product.setProductRight(recommendProducts.get(i)); mDataList.add(product); }else { if (i == size -1 ) { break; } BrandRecommedProduct product = new BrandRecommedProduct(); product.setProductLeft(recommendProducts.get(i)); i++; product.setProductRight(recommendProducts.get(i)); mDataList.add(product); } } if(mBrandDetailBean.getCat() != null){ mDataList.add(mBrandDetailBean.getCat()); } mAdapter.notifyDataChanged(mDataList); }}
这样就可以在初始化数据的时候就包装了两个对等的数据,这样在通过Adapter绑定View的时候就和普通ListView处理相同了。这么做对于简单的View体现不出来很大的优势,如果是复杂的ListView布局就很能体现优势了.
版权声明:本文为博主原创文章,未经博主允许不得转载。