【Android前端】Bing每日图片列表应用制作记录——2.列表的实现

来源:互联网 发布:360手机数据恢复 编辑:程序博客网 时间:2024/05/22 13:26

第二篇:列表的实现

上一篇我们只是新建了项目,那么这一篇我们就先来实现app的主体——列表。
说到列表大家可能一下子就会想到ListView,虽然现在ListView已经被功能更为强大的RecycleView逐步替代了,但是对于初学者来说掌握ListView的用法比学习曲线陡峭的RecycleView更为容易,所以这次也先使用ListView。

从这一部分开始我会把每次的代码更新到github:BingPicAnother上,有兴趣的也可以试着从第一个commit开始fork一下做自己的魔改。

第一部分:ListView

ListView是非常常用的控件,它由内部的多个item构成,也就是说真正显示信息的其实是那些item。

下面我们来实际操作,建立一个简单的ListView:
首先是res/layout/activity_main.xml,这是我们app的主要activity的布局文件,我们在父容器中建立一个ListView:
<?xml version="1.0" encoding="utf-8"?><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"    tools:context="com.xugino.bingpicanother.MainActivity">    <ListView        android:id="@+id/list"        android:layout_width="match_parent"        android:layout_height="wrap_content">    </ListView></RelativeLayout>
大家可能注意到了我的父容器使用的是RelativeLayout,这是为了方便调整内部布局,当然使用LinearLayout也并没有什么问题。

然后下一步我们在activity里绑定上面那个布局并且找到我们定义的ListView:
package com.xugino.bingpicanotherimport android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.ListView;public class MainActivity extends AppCompatActivity {    ListView mListView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mListView=(ListView)this.findViewById(R.id.list);    }}

这样就已经可以运行了,当然运行之后你会发现界面里空空如也只有一个ActionBar,这个的原因其实很简单——ListView的里面还没有数据,而为ListView绑定数据的则是另外一个控件:Adapter。

第二部分:Adapter

Adapter按照字面翻译就是适配器,它的作用就是把你的数据按需放进ListView里面。
通常在使用时会直接继承BaseAdapter写一个新类,这是因为原生Adapter往往不能在每一个方面都满足我们的需求,尤其是getView()方法非常需要按需重写。
不过在实现Adapter之前,我们先要为内部的Item写一个布局:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent" android:layout_height="150dp"    android:background="#fffafafa">    <ImageView        android:id="@+id/item_pic"        android:layout_width="120dp"        android:layout_height="120dp"        android:layout_alignParentTop="true"        android:layout_alignParentStart="true"        android:layout_centerVertical="true"        android:layout_margin="15dp" />    <LinearLayout        android:id="@+id/item_doc"        android:orientation="vertical"        android:layout_width="205dp"        android:layout_height="120dp"        android:layout_marginTop="15dp"        android:layout_alignParentTop="true"        android:layout_toRightOf="@id/item_pic"        android:layout_alignEnd="@+id/download_btn">        <TextView            android:id="@+id/item_text"            android:layout_width="match_parent"            android:layout_height="90dp"            android:gravity="left|top"            android:textSize="18sp"            android:textColor="#000000"/>        <TextView            android:id="@+id/item_time"            android:layout_width="140dp"            android:layout_height="30dp"            android:gravity="left|bottom"            android:textSize="16sp"            android:textColor="#666666"/>    </LinearLayout>    <Button        android:id="@+id/download_btn"        android:layout_width="wrap_content"        android:layout_height="40dp"        android:text="这是按钮"        android:textColor="@color/colorAccent"        android:background="@color/colorPrimary"        android:textSize="16sp"        android:focusable="false"        android:layout_alignParentRight="true"        android:layout_alignBottom="@id/item_doc"        android:layout_marginRight="5dp" /></RelativeLayout>
(这里的所有数值当然可以根据需要改)

然后还有一步:定义一个用于存储数据的类,以这里为例,我们建立一个叫DataResource的类,并在其中实现数据的初始化:
package com.xugino.bingpicanother;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class DataResource {    private List<Map<String,Object>> list;    private Map<String,Object> map;    public DataResource(){        list=new ArrayList<>();    }    public List<Map<String,Object>> getData()    {        for(int i=1;i<=5;i++){            map=new HashMap<>();            map.put("pic",R.mipmap.test);            map.put("text","这里应该是内容");            map.put("time","这里应该有时间");            list.add(map);        }        return list;    }}

最后再来实现Adapter,我们新建一个MyAdapter.java。既然要继承自BaseAdapter,那么以下几个方法是一定要重写的:构造函数,getCount(),getId(),getItem()和getView():
package com.xugino.bingpicanother;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.ImageView;import android.widget.TextView;import java.util.List;import java.util.Map;public class MyAdapter extends BaseAdapter{    Context mContext;    private LayoutInflater mInflater;    private List<Map<String,Object>> mapList;    private DataResource data;    public MyAdapter(Context mContext, List<Map<String,Object>> mapList,DataResource data){        this.mContext=mContext;        mInflater=LayoutInflater.from(mContext);        this.mapList=mapList;        this.data=data;    }    @Override    public int getCount() {        return mapList.size();    }    @Override    public Object getItem(int i) {        return mapList.get(i);    }    @Override    public long getItemId(int i) {        return i;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        ViewHolder viewHolder;        if(convertView==null){            viewHolder = new ViewHolder();            convertView=mInflater.inflate(R.layout.list_item,null);            viewHolder.pic=convertView.findViewById(R.id.item_pic);            viewHolder.text=convertView.findViewById(R.id.item_text);            viewHolder.time=convertView.findViewById(R.id.item_time);            viewHolder.btn=convertView.findViewById(R.id.download_btn);            convertView.setTag(viewHolder);        }else{            viewHolder=(ViewHolder)convertView.getTag();        }        viewHolder.pic.setImageResource((int)data.getData().get(position).get("pic"));        viewHolder.text.setText((CharSequence) data.getData().get(position).get("text"));        viewHolder.time.setText((CharSequence) data.getData().get(position).get("time"));        viewHolder.btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {            }        });        return convertView;    }    private class ViewHolder{        ImageView pic;        TextView text;        TextView time;        Button btn;    }}

大家应该注意到了有一个需要注意的东西:ViewHolder。ViewHolder的作用是为ListView提供缓存,当你拖动ListView时新的View就会从缓存中提取出来放到List的可见区域里,利用这种方式我们就不用在显示一个新Item时再重新创建对象了。
此外细心的人还会发现构造函数里多了一个List,这里先卖个关子,我们都后面再讲。

当然不要忘了更新MainActivity,包括View的初始化和数据的初始化:
package com.xugino.bingpicanother;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.ListView;import java.util.ArrayList;import java.util.List;import java.util.Map;public class MainActivity extends AppCompatActivity {    ListView mListView;    List<Map<String,Object>> mList;    DataResource data;    MyAdapter mAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initData();    }    private void initView(){        mList=new ArrayList<>();        data=new DataResource();        mAdapter=new MyAdapter(MainActivity.this,mList,data);        mListView=(ListView)this.findViewById(R.id.list);        mListView.setAdapter(mAdapter);    }    private void initData(){        mList.addAll(data.getData());        mAdapter.notifyDataSetChanged();    }}
mAdapter.notifyDataSetChanged()是通知适配器数据有更新,如果不加这一句那么多次更新就会报错(当然现在只涉及一次更新并不会弹错,这并不意味着这句就可以不加)

然后就可以运行来看结果了:

ImageView的图片当然是用来演示的图片,大家随便找一张就好。

后续:API

之前说过了我们的预期效果是从网络加载数据,那么DataResource里面的方法也要相应更新,下一次我们会讲重头戏之一:HttpUrlConnection
阅读全文
0 0
原创粉丝点击