Android Adapter 与 Listview

余生颓废 提交于 2020-02-10 01:58:15

一、Adapter,BaseAdapter

    BaseAdapter应用程序中经常用到的基础数据适配器,它的主要用途是将一组数据传到像ListView、Spinner、Gallery及GridView等UI显示组件,它是继承自接口类Adapter,Adapter有如下结构:

Public Methods
            abstract                                                            int getCount()
How many items are in the data set represented by this Adapter.
            abstract                                                            Object getItem(int position)
Get the data item associated with the specified position in the data set.
abstract long getItemId(int position)
Get the row id associated with the specified position in the list.
            abstract                                                            int getItemViewType(int position)
Get the type of View that will be created by getView(int, View, ViewGroup) for the specified item.
            abstract                                                            View getView(int position, View convertView, ViewGroup parent)
Get a View that displays the data at the specified position in the data set.
            abstract                                                            int getViewTypeCount()

Returns the number of types of Views that will be created by getView(int, View, ViewGroup).

            abstract                                                            boolean hasStableIds()
Indicates whether the item ids are stable across changes to the underlying data.
            abstract                                                            boolean isEmpty()
            abstract                                                            void registerDataSetObserver(DataSetObserver observer)
Register an observer that is called when changes happen to the data used by this adapter.
            abstract                                                            void unregisterDataSetObserver(DataSetObserver observer)
Unregister an observer that has previously been registered with this adapter via registerDataSetObserver(DataSetObserver).

  

 

BaseAdapter用的最多,BaseAdapter实现了ListAdapter和SpinnerAdapter两个接口,当然它也可以直接给ListView和Spinner等UI组件直接提供数据。使用BaseAdapter必须写一个类继承它,同时BaseAdapter是一个抽象类,继承它必须实现它的方法。BaseAdapter的灵活性就在于它要重写很多方法,其中最重要的即为getView()方法,当系统开始绘制ListView的时候,首先调用getCount()方法。得到它的返回值,即ListView的长度。然后系统调用getView()方法,根据这个长度逐一绘制ListView的每一行。也就是说,如果让getCount()返回1,那么只显示一行。而getItem()getItemId()则在需要处理和取得Adapter中的数据时调用。查阅关于getView方法的api手册如下:

 


 

public abstract View getView(int position, View convertView, ViewGroup parent) 

Get a View that displays the data at the specified position in the data set. You can either create a View manually or inflate it from an XML layout file. When the View is inflated, the parent View (GridView, ListView...) will apply default layout parameters unless you use inflate(int, android.view.ViewGroup, boolean) to specify a root view and to prevent attachment to the root.

Parameters

position

The position of the item within the adapter's data set of the item whose view we want.

convertView

The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using. If it is not possible to convert this view to display the correct data, this method can create a new view. Heterogeneous lists can specify their number of view types, so that this View is always of the right type (see getViewTypeCount() and getItemViewType(int)).

parent

The parent that this view will eventually be attached to

Returns

A View corresponding to the data at the specified position.


 

 二、使用自定义Adapter承载的ListView

  常用的Adapter:BaseAdapter,ArrayAdapter,SimpleAdapter和SimpleCursorAdapter,ArrayAdapter最为简单,只能展示一行字。SimpleAdapter有最好的扩充性,可以自定义出各种效果。 BaseAdapter自由度更高,SimpleAdpater 是BaseAdapter的子类之一。SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方面的把数据库的内容以列表的形式展示出来。这里两个Demo分别使用SimpleAdapter和BaseAdapter来实现两种功能自由度比较高的ListView。

1,SimpleAdapter Demo

构建一个显示图片和文字的ListView,捕获点击和长按的操作。

ListItem的XML实现,data.xml

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout 
        android:id="@+id/RelativeLayout01" 
        android:layout_width="fill_parent" 
        xmlns:android="http://schemas.android.com/apk/res/android" 
        android:layout_height="wrap_content" 
        android:paddingBottom="4dip" 
        android:paddingLeft="12dip"
        android:paddingRight="12dip">
        <ImageView 
            android:paddingTop="12dip"
            android:layout_alignParentRight="true"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:id="@+id/ItemImage"
        /> 
        <TextView 
            android:text="TextView01" 
            android:layout_height="wrap_content" 
            android:textSize="20dip" 
            android:layout_width="fill_parent" 
            android:id="@+id/ItemTitle"
        />
        <TextView 
            android:text="TextView02" 
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent" 
            android:layout_below="@+id/ItemTitle" 
            android:id="@+id/ItemText"
        />
    </RelativeLayout>

/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    android:id="@+id/LinearLayout01" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    xmlns:android="http://schemas.android.com/apk/res/android">

    <ListView
        android:id="@+id/ListView01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >
    </ListView>
</LinearLayout>

 

MainActivity.java

捕获点击和长按的操作,并且在menu里面加入点击导航到另外一个Baseadapter demo里面

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //绑定Layout里面的ListView  
        ListView list = (ListView) findViewById(R.id.ListView01);  
        
      //生成动态数组,加入数据  
        ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String, Object>>();  
        for(int i=0;i<20;i++)  
        {  
            HashMap<String, Object> map = new HashMap<String, Object>();  
            map.put("ItemImage", R.drawable.ic_launcher);//图像资源的ID  
            map.put("ItemTitle", "Title"+i);  
            map.put("ItemText", "the info of this Item!");  
            listItem.add(map);  
        }  
        
      //生成适配器的Item和动态数组对应的元素  
        SimpleAdapter listItemAdapter = new SimpleAdapter(this,listItem,//数据源   
            R.layout.data,//ListItem的XML实现  
            //动态数组与ImageItem对应的子项          
            new String[] {"ItemImage","ItemTitle", "ItemText"},   
            //ImageItem的XML文件里面的一个ImageView,两个TextView ID  
            new int[] {R.id.ItemImage,R.id.ItemTitle,R.id.ItemText}  
        );
        
      //添加并且显示  
        list.setAdapter(listItemAdapter);  
        
      //添加点击  
        list.setOnItemClickListener(new  AdapterView.OnItemClickListener() {  

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
                // TODO Auto-generated method stub
                setTitle("点击第"+arg2+"个项目");  
                
            }  
        });  
        
      //添加长按点击  
        list.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {  

            @Override
            public void onCreateContextMenu(ContextMenu arg0, View arg1,
                    ContextMenuInfo arg2) {
                // TODO Auto-generated method stub
                arg0.setHeaderTitle("长按菜单-ContextMenu");     
                arg0.add(0, 0, 0, "弹出长按菜单0");  
                arg0.add(0, 1, 0, "弹出长按菜单1");  
                
            }  
        }); 
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        MenuItem menuItem= menu.getItem(0);
        menuItem.setTitle("自定义ListView");
        menuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
            
            public boolean onMenuItemClick(MenuItem item) {
                // TODO Auto-generated method stub
                Intent intent=new Intent();     

                intent.setClass(MainActivity.this, SecondActivity.class);
                MainActivity.this.startActivity(intent);
                return false;
            }
        });
        return true;
    }
    
    //长按菜单响应函数  
    @Override  
    public boolean onContextItemSelected(MenuItem item) {  
        setTitle("点击了长按菜单里面的第"+item.getItemId()+"个项目");   
        return super.onContextItemSelected(item);  
    }  

}

 

2,BaseAdapter demo

 实现带Checkbox的ListView

ListItem的XML实现,m_data.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" >
                <ImageView    
                android:id="@+id/img"   
                android:layout_width="wrap_content"   
                android:layout_height="wrap_content"   
                android:layout_gravity="center_vertical"/>    
                <TextView    
                android:id="@+id/title"   
                android:textSize="18dip"   
                android:layout_weight="1"
                android:textStyle="bold"
                android:gravity="center_horizontal|center_vertical"   
                android:layout_width="wrap_content"   
                android:layout_height="wrap_content"/>    
                <CheckBox    
                android:id="@+id/cb"   
                android:layout_width="wrap_content"   
                android:layout_height="wrap_content"   
                android:focusable="false"   
                android:focusableInTouchMode="false"   
                android:clickable="false"   
                android:checkMark="?android:attr/listChoiceIndicatorMultiple"/>    
</LinearLayout>

/layout/second_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <ListView    
    android:id="@+id/lv"   
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"/> 
</LinearLayout>

 MyListViewAdapter.java

自定义Adapter MyListViewAdapter

public class MyListViewAdapter extends BaseAdapter{
    private LayoutInflater mInflater;
    private List<Map<String, Object>> mData;
    public static Map<Integer, Boolean> isSelected;   //记录checkbox状态的
    String  [] string ={"Title"};
    int  [] img ={R.drawable.ic_launcher};
    public MyListViewAdapter(Context context ){
        mInflater = LayoutInflater.from(context);   
        init();
    }
    private void init() {
        // TODO Auto-generated method stub
        mData=new ArrayList<Map<String, Object>>();    
        for(int i=0;i<100;i++){
            Map<String,Object> map=new HashMap<String, Object>();
            map.put("img",img[0]);
            map.put("title",string[0] );
            mData.add(map);
        }
        
        //这儿定义isSelected这个map是记录每个listitem的状态,初始状态全部为false。
        isSelected = new HashMap<Integer, Boolean>();    
        for(int i=0;i<mData.size();i++){
            isSelected.put(i, false);
        }
    }
    
    public int getCount(){
        return mData.size();
    }
    public Object getItem(int position){
        return null;
    }
    public long getItemId(int position){
        return 0;
    }
    public View getView(int position,View convertView,ViewGroup parent) {
        ViewHolder holder = null;//
        if(convertView==null){
            holder=new ViewHolder();
            convertView = mInflater.inflate(R.layout.m_data, null);    
            holder.img = (ImageView) convertView.findViewById(R.id.img); 
            holder.title = (TextView) convertView.findViewById(R.id.title);    
            holder.cBox = (CheckBox) convertView.findViewById(R.id.cb);    
            convertView.setTag(holder);    
        }else {
            holder = (ViewHolder) convertView.getTag();    
        }
        holder.img.setBackgroundResource((Integer) mData.get(position).get( "img"));    
        holder.title.setText(mData.get(position).get("title").toString());    
        holder.cBox.setChecked(isSelected.get(position));    
    return convertView; 
    }
}

临时存储器ViewHoder类

public final class ViewHolder {
    public ImageView img;
    public TextView  title;
    public CheckBox  cBox;
}

从MainActivity跳转到的第二个Activity:SecondActivity.java

public class SecondActivity extends Activity {
    
    private  ListView  listview;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_activity);
        
        listview =(ListView)findViewById(R.id.lv);
        MyListViewAdapter  myListViewAdapter=new MyListViewAdapter(this);
        listview.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        listview.setItemsCanFocus(false);
        listview.setAdapter((ListAdapter) myListViewAdapter);
        
        listview.setOnItemClickListener(clickListener);
        listview.getCheckedItemPositions();
    }
    private OnItemClickListener clickListener=new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,long id){
            ViewHolder vHollder = (ViewHolder) view.getTag(); 
            //在每次获取点击的item时将对于的checkbox状态改变,同时修改map的值。
            vHollder.cBox.toggle();    
            MyListViewAdapter.isSelected.put(position, vHollder.cBox.isChecked());
        }
    }; 
    
}

效果图:


demo的java包均没有包含,需要根据提示自行导入。

刚接触android编程,发现java和C#如此相近,eclipse也用起来很顺手。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!