在android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示。
列表的显示需要三个元素:
1.ListVeiw 用来展示列表的View。
2.适配器Adapter:用来把数据映射到ListView上的中介。
3.数据Data:具体的将被映射的字符串,图片,或者基本组件。
根据列表的适配器类型,列表分为三种,ArrayAdapter,SimpleAdapter和SimpleCursorAdapter。其中以ArrayAdapter最为简单,只能展示一行字。SimpleAdapter有最好的扩充性,可以自定义出各种效果。SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方面的把数据库的内容以列表的形式展示出来。
android中基本的适配器BaseAdapter是一个抽象类,而它非常懒,基本没有什么方法去可以直接使用的,所以我们在实际开发中如果需要实现各种各样的适配器样式,则需要自定义适合自己的适配器,也就是说需要继承BaseAdapter。而如果获取的json数据是千变万化的,可以使用android代码进行方便的调用相应的数据,就可以达到图文混排等好看的样式效果。
自定义Adapter中主要在getView中进行UI操作和数据处理。如以下代码中,根据数据类型不同,显示两种风格的item,在进行相关数据操作后加载到同一个Listview中,这就实现了简单的自定义Adapter。
public View getView(int position, View convertView, ViewGroup parent) { final CellData data = mDataList.get(position); ViewHolder viewHolderFirst = null; ViewHolder viewHolderSecond = null; int layoutType = this.getItemViewType(position); if (convertView == null) { switch (layoutType) { case LAYOUT_TYPE_FIRST: convertView = new CellFirst(context); viewHolderFirst = new ViewHolder(); viewHolderFirst .mCellFirst = (CellFirst) convertView; viewHolderFirst .mCellFirst .setCellFirstListener(mAdapterListener); convertView.setTag(viewHolderFirst ); break; case LAYOUT_TYPE_SECOND: convertView = new CellSecond(context); viewHolderSend = new ViewHolder(); viewHolderSend.mCellSecond = (CellSecond) convertView; viewHolderSend.CellSecond .setCellSecondListener(mAdapterListener); convertView.setTag(viewHolderSend); break; } } else { switch (layoutType) { case LAYOUT_TYPE_FIRST: viewHolderFirst = (ViewHolder) convertView.getTag(); break; case LAYOUT_TYPE_SECOND: viewHolderSend = (ViewHolder) convertView.getTag(); break; } } switch (layoutType) { case LAYOUT_TYPE_FIRST: String first= data.getFirst(); viewHolderFirst .mCellFirst.setData(first); LinearLayout linearLayout = (LinearLayout) viewHolderFirst .mCellFirst .findViewById(R.id.firstContent); break; case LAYOUT_TYPE_SEND_MSG: String second= data.getSecond(); viewHolderSecond .mCellSecond.setData(second); LinearLayout linearLayout = (LinearLayout) viewHolderSend .mCellSecond .findViewById(R.id.secondContent); break; } return convertView; }
常见问题1:安卓的listview,只要屏幕是静态显示(如在无任何操作),它会正确地显示出来。但是,当开始滚动,列表中的行项目的滚动将正确显示,但“根”布局的背景将变成全黑的,当滚动停止后台需要花费大量时间找回它原有颜色或者背景,导致页面出现混乱布局
解决方法:有两种可能的解决该问题,既工作但每个应中使用不同的情况。 使用“android:cacheColorHint”当你的ListView有一个纯色背景。
<item name="android:cacheColorHint">@color/transparent</item>
使用“android:scrollingCache”当你的ListView有一个(复杂)图像作为背景。
注意<item name="android:scrollingCache">false</item>
当你的ListView有一个纯色背景这两种方法都可以工作,所以不仅cacheColorHint会工作。但它不建议使用scrolingCache方法纯色背景的,因为它会关闭用于平滑动画和滚动ListView的优化方法。
请注意注: scrolingCache设置为false并不一定意味着ListView的动画和滚动会越来越慢。
常见问题2:安卓开发中可能出现如下Listview的嵌套Listview的需求,但会发现放入的小ListView会显示不完全,它的高度始终有问题。 解决方法:只要在设置ListView的Adapter后调用静态方法重新计算相关参数即可让ListView正确的显示在其父ListView的ListItem中。但是要注意的是,子ListView的每个Item必须是LinearLayout,不能是其他的,因为其他的Layout(如RelativeLayout)没有重写onMeasure(),所以会在onMeasure()时抛出异常。
在ScrollView中嵌套ListView(或者ScrollView)的另外一个问题就是,子ScrollView中无法滑动的(如果它没有显示完全的话),因为滑动事件会被父ScrollView吃掉,如果想要让子ScrollView也可以滑动,只能强行截取滑动事件。
虽然在ScrollView中显示ScrollView在技术上的难题可以攻破,但是这样的设计却是非常差的用户体验因为用户会不容易看到和操作子ScrollView中的内容。默认情况下Android是禁止在ScrollView中放入另外的ScrollView的,它的高度是无法计算的。故而能尽量避免使用就避免。