您的位置:首页 > 其它

Views和Adapters

2015-06-16 16:38 281 查看

关键点

ListView、Spinner、Adapters

在展现多条数据的时候,我们用List负责数据的显示,用Adapter来管理基本的数据

实例一

在用户界面实现一系列的数据项

Android提供了很多pre_built layout.例如simple_list_item_1。

1)activity_main.xml界面如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>


2)创建Adapter来管理需要显示的数据:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //创建ArrayAdapter来管理数据,使用simple_list_item_1作为子布局,一个数组做为需要使用的数据
        ArrayAdapter<String> aAdpt = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
                new String[]{"Froyo", "Gingerbread", "Honeycomb", "Ice cream Sandwich", "Jelly Bean", " KitKat"});
        //最后将adapter添加到listview中
        ListView lv = (ListView) findViewById(R.id.list);
        lv.setAdapter(aAdpt);
3)运行结果如下所示:



实例二

上述的例子是实现ListView,例二是实现Spinner,实现下拉列表。这两个是实际应用中最广泛的。

1)布局文件中,ListView换成Spinner

<Spinner
       android:id="@+id/spinner"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       />
2)在strings.xml中定义要显示的字符数组days

<string-array name="days">
        <item>Monday</item>
        <item>Tuesday</item>
        <item>Wednesday</item>
    </string-array>
3)在主类中添加adapter,并在adapter添加到spinner中

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Spinner spinner=(Spinner)findViewById(R.id.spinner);
        ArrayAdapter<CharSequence> aAdpt = ArrayAdapter.createFromResource(this, R.array.days,
                android.R.layout.simple_spinner_item);
        aAdpt.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(aAdpt);
    }
4)运行结果如下所示:



实例三

ListView事件处理,当数据以ListView的方式呈现的时候,我们可能需要点击ListView中的每个item得到更详细的信息

本实例实现的是点击每条item,弹出提示框,该例是建立在实例一的基础上,为ListView添加监听器,并实现处理监听事件

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> aView, View view, int position, long id) {
               // We handle item click event
                TextView tv = (TextView) view;
                String text = (String) tv.getText();
                Toast.makeText(MainActivity.this, "You clicked on " + text, Toast.LENGTH_LONG).show();
            }
        });


运行结果,点击对应的项目,弹出对话框



实例四

定制Adapter和View Holder Pattern

当标准的Adapter不能满足我们需求的时候,就需要定制Adapter,在已有BaseAdapter或其他Adapter的基础上补充功能,以符合需要。

本例是实现一个ListView,每条子项目有两行信息

1)首先我们新建一个继承BaseAdapter的CustomAdapter类

我们需要重写getCount()、getItem(int arg0)、getItemId(int arg0)、getView()这四个方法

public class CustomAdapter extends BaseAdapter {
    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return null;
    }
}


2)在实现这些方法之前,我们先定义我们得数据模型。我们假设,我们的类名为Item,它包含两个属性,name和desc,现在我们需要定义一个子layout来显示这些数据

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/descr"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
3)在我们的adapter中,我们需要构造方法来传递我们得数据。

然后我们实现除getView()之外的方法

private Context ctx;
    List<Item> itemList;
    public CustomAdapter(Context ctx, List<Item> itemList) {
        this.ctx = ctx;
        this.itemList = itemList;
    }
    @Override
    public int getCount() {
        return itemList==null?0:itemList.size();
    }

    @Override
    public Object getItem(int position) {
        return itemList==null?0:itemList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return itemList==null?0:itemList.get(position).hashCode();
    }


接下来是getView()方法,它是所有方法中实现起来最复杂的,同时他是定制adapter的核心功能。

public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        if (v == null) {
            LayoutInflater lInf = (LayoutInflater)
                    ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = lInf.inflate(R.layout.item_layout, null);
        }
        TextView nameView = (TextView) v.findViewById(R.id.name);
        TextView descrView = (TextView) v.findViewById(R.id.desc);
        nameView.setText(itemList.get(position).name);
        descrView.setText(itemList.get(position).desc);
        return v;
    }


4)主类中使用CustomAdapter

List<Item> list=new ArrayList<Item>();
        list.add(new Item("name1","desc1"));
        list.add(new Item("name2","desc2"));
        list.add(new Item("name3","desc3"));
        list.add(new Item("name4","desc4"));

        CustomAdapter adapter=new CustomAdapter(this,list);

        //最后将adapter添加到listview中
        ListView lv = (ListView) findViewById(R.id.list);
        lv.setAdapter(adapter);


5)运行结果如下所示



在上例中,getView方法是一个很长耗时的操作,当用户滚动界面时它会影响整个ListView的性能。应用View Holder Pattern,可以减少调用getView方法

上面的讲法好像没什么作用,我们分析实例三中没有ViewHolder情况,看一下getView()方法

1)当它第一次加载时,convertView是null。我们需要inflate list item layout并通过findViewById来查找TextView

2)第二次加载时,convertView不为空,但是我们仍然需要findViewById查找TextView

3)第三次仍然要频繁findViewById查找TextView,当有很多item和view在ListView中时,性能就会下降,这时候就用到了ViewHolder

public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        TextHolder th = null;
        if (v == null) {
            LayoutInflater lInf = (LayoutInflater)
                    ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = lInf.inflate(R.layout.item_layout, null);
            TextView nameView = (TextView) v.findViewById(R.id.name);
            TextView descrView = (TextView) v.findViewById(R.id.desc);
            th = new TextHolder();
            th.nameView = nameView;
            th.descView = descrView;
            v.setTag(th);
        }
        else
            th = (TextHolder) v.getTag();
        th.nameView.setText(itemList.get(position).name);
        th.descView.setText(itemList.get(position).desc);
        return v;
    }
    static class TextHolder {
        TextView nameView;
        TextView descView;
    }
加入ViewHolder使得在第一次调用getView方法的时候,将ViewHolder做为convertView的一个标志,或者是一个临时存储convertView的地方,载第二次访问的时候,通过getTag直接获得view不需要通过findViewById的方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: