Adapter Adapter的翻译成中文是适配器和设计模式中介绍的适配器其实是一个意思,它的作用就是将数据库等形式存在的数据适配到像ListView等组件上。 Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带。
常见的Adapter类型 ArrayAdapter :只能展示一行文字。 BaseAdapter:是一个抽象类,继承它需要实现较多的方法,所以也就具有较高的灵活性; SimpleAdapter:有最好的扩充性,可以自定义出各种效果。 SimpleCursorAdapter:可以适用于简单的纯文字型ListView,它需要Cursor的字段和UI的id对应起来。如需要实现更复杂的UI也可以重写其他方法。可以认为是SimpleAdapter对数据库的简单结合,可以方便地把数据库的内容以列表的形式展示出来。
ArrayAdapter 列表的显示需要三个元素: a.ListVeiw 用来展示列表的View。 b.适配器 用来把数据映射到ListView上的中介。 c.数据 具体的将被映射的字符串,图片,或者基本组件。
public class ArrayAdapterActivity extends ListActivity { public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); String [] strs = {"1" ,"2" ,"3" ,"4" ,"5" }; ArrayAdapter <String > adapter = new ArrayAdapter <String >(this , android.R .layout.simple_expandable_list_item_1,strs); setListAdapter(adapter); } } }
SimpleAdapter simpleAdapter的扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)等等。
SimpleAdapter adapter = new SimpleAdapter(this , getData () , R . layout.simple, new String[] { "title" , "img" }, new int [] { R . id.title, R . id.img });
SimpleAdapter adapter = new SimpleAdapter( 上下文, List <Map <String , Object >>类型数据, 每个Item布局文件, new String [] { “title”}, new int [] { R.id.title,} );
SimpleCursorAdapter ListAdapter adapter = new SimpleCursorAdapter ( this , android.R.layout.simple_list_item_1, cur, new String [] {People.NAME}, new int [] {android.R.id.text1} );
BaseAdapter public View getView(int position , View convertView , ViewGroup parent ) { ViewHolder holder = null; if (convertView == null) { holder=new ViewHolder() ; convertView = mInflater.inflate(R . layout.vlist2, null); holder.img = (ImageView)convertView.findViewById(R.id .img ) ; holder.title = (TextView)convertView.findViewById(R.id .title ) ; holder.info = (TextView)convertView.findViewById(R.id .info ) ; holder.viewBtn = (Button)convertView.findViewById(R.id .view_btn ) ; convertView.setTag(holder ) ; }else { holder = (ViewHolder)convertView.getTag() ; } holder.img.setBackgroundResource((Integer) mData.get(position).get("img" )); holder.title.setText((String) mData.get(position).get("title" )); holder.info.setText((String) mData.get(position).get("info" )); return convertView; }
系统首先调用getCount()函数,根据他的返回值得到listView的长度.然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。
getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的vlist2.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响 应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个 ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了。
<Button android:id ="@+id/view_btn" android:focusable ="false" />
ListView ListView常见的XML属性
ListView常用的内置列表项布局
如果一个窗口仅需要显示一个列表,则可以直接让Activity继承ListActivity来实现
public class MainActivity extends ListActivity { protected void onCreate(Bundle savedInstanceState ) { super.onCreate(savedInstanceState ) ; String ctype[] = {“项目1 ”,“项目2 ”,“项目3 ”,“项目4 ”}; ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(this, android.R . layout.simple_list_item_1, ctype); this.setListAdapter(adapter ) ; } protected void onListItemClick(ListView l , View v , int position , long id ) { Toast . makeText(MainActivity.this ,l .getItemAtPosition (position ) .to String() ,0 ).show() ; super.onListItemClick(l , v , position , id ) ; } }
ListView中item与控件抢夺焦点的解决方法
将ListView中的Item布局中的子控件focusable属性设置为false
在getView方法中设置button.setFocusable(false)
设置item的根布局的属性android: descendantFocusability="blocksDescendant"
我们可以发现,其实这三种方法都是为了让Button等控件不能获取焦点,从而使得item可以响应点击事件。
第三种方法使用起来相对方便,因为它是将item布局中的其他所有控件都设置为不能获取焦点。
android:descendantFocusability属性共有三个取值,分别为
beforeDescendants:viewgroup会优先其子类控件而获取到焦点 afterDescendants:viewgroup 只有当其子类控件不需要获取焦点时才获取焦点blocksDescendants:viewgroup 会覆盖子类控件而直接获得焦点
ListView滚动事件 ListView的滚动有三种状态 第一是静止状态,SCROLL_STATE_IDLE 第二是手指滚动状态,SCROLL_STATE_TOUCH_SCROLL 第三是手指不动了,但是屏幕还在滚动状态。SCROLL_STATE_FLING
getListView().setOnScrollListener(new OnScrollListener() { listViewScrollState; public void onScrollStateChanged (AbsListView view, int scrollState ) { listViewScrollState = scrollState; switch (scrollState){ case OnScrollListener.SCROLL_STATE_IDLE: break ; case OnScrollListener.SCROLL_STATE_FLING: break ; case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: break ; } }
firstVisibleItem the index of the first visible cell (ignore if visibleItemCount == 0 ) visibleItemCount the number of visible cells totalItemCount the number of items in the list adaptor public void onScroll(AbsListView view , int firstVisibleItem ,int visibleItemCount , int totalItemCount ) { }
判断滚动到底部和顶部的方法 lv.setOnScrollListener(new OnScrollListener() { public void onScrollStateChanged(AbsListView view , int scrollState ) { switch (scrollState) { case OnScrollListener.SCROLL_STATE_IDLE: if (lv.getLastVisiblePosition() == (lv.getCount() - 1 )) { } if (lv.getFirstVisiblePosition() == 0 ){ } break; } } public void onScroll(AbsListView view , int firstVisibleItem ,int visibleItemCount , int totalItemCount ) { } );
getListView() .setOnScrollListener(new OnScrollListener() { public void onScrollStateChanged(AbsListView view , int scrollState ) { } public void onScroll(AbsListView view , int firstVisibleItem , int visibleItemCount , int totalItemCount ) { if (firstVisibleItem==0 ){ Log . e("log" , "滑到顶部" ); } if (visibleItemCount + firstVisibleItem == totalItemCount){ Log . e("log" , "滑到底部" ); } } });