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

第二篇:列表的实现

上一篇我们只是新建了项目,那么这一篇我们就先来实现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.bingpicanother

import 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值