一个iOS开发者的android修行之路二:UITableView和ListView的对比探究

尽管现在主流的移动设备的屏幕尺寸都越来越大,特别是iPhone X的出现,以后的趋势都是全屏手机,但是一屏的显示的内容还是有限的,当我们需要有大量数据需要展示时就可以使用这两个控件。这两个控件的相同点都是允许用户上下滑动,以便展示屏幕区域外的内容。很多主流的应用,比如微信、QQ的消息列表,微信朋友圈,微博等等应用的很多界面都是使用这两个控件实现的。

一、UITableView的基本使用

  1. iOS添加一个UITableView有两种方式。一是:纯代码初始化一个UITableView;二是在storyboard中直接拖入一个UITableView并且设置约束添加,同时设置tableView的dataSource和delegate为ViewController。这两种方式并没有优劣之分,使用第二种方式是苹果推荐的快速开发的方式。我的事例代码选择的第二种方法。
    在storyboard添加UITableView的四步曲
  2. 自定义UITableViewCell,勾选同时勾选xib,我这里命名为TestTableViewCell,里面添加两个控件ImageView和Label,同时设置应用。同时设置xib中的重用identifier为:TestTableViewCell
  3. 注册重用的cell,在ViewControllerviewDidLoad方法中注册自定义cell。
let nib = UINib(nibName: "TestTableViewCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "TestTableViewCell")
  1. 配置tableView显示的数据源,实际项目中为网络请求的数据,demo中为模拟了100条假数据。
  2. 实现tableView的数据源和代理方法。
    其中这两个数据源方法必须实现:func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Intfunc tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell,否则会app会闪退。其中第一个方法用来指明cell的个数,第二个方法用来设置cell的数据,demo中的设置UIImageView和UILabel。
    cell点击事件的响应,则需要实现代理方法func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    下面是整个ViewController代码:
//
//  ViewController.swift
//  iOSTableViewDemo
//
//  Created by romance on 2017/11/28.
//  Copyright © 2017年 firstleap. All rights reserved.
//

import UIKit

final class ViewController: UIViewController {
  
  @IBOutlet weak var tableView: UITableView!
  final fileprivate var dataList = [TestModel]()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    let nib = UINib(nibName: "TestTableViewCell", bundle: nil)
    tableView.register(nib, forCellReuseIdentifier: "TestTableViewCell")
    setupData()
  }
  
  private func setupData() {
    for _ in 0...100 {
      let model1 = TestModel(imageName: "set_icon_about", title: "关于")
      dataList.append(model1)
      let model2 = TestModel(imageName: "set_icon_change", title: "头像")
      dataList.append(model2)
      let model3 = TestModel(imageName: "set_icon_clean", title: "清楚")
      dataList.append(model3)
      let model4 = TestModel(imageName: "set_icon_edit", title: "修改")
      dataList.append(model4)
    }
  }
  
}

extension ViewController: UITableViewDataSource, UITableViewDelegate {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataList.count
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCell", for: indexPath) as! TestTableViewCell
    let model = dataList[indexPath.row]
    cell.icon?.image = UIImage(named: model.imageName);
    cell.title?.text = model.title
    return cell
  }
  
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
    
    let model = dataList[indexPath.row]
    let showtitle = model.title
    let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
    label.text = showtitle
    label.textAlignment = .center
    label.backgroundColor = .lightGray
    label.center = view.center
    label.alpha = 0
    self.view.addSubview(label)
    
    UIView.animate(withDuration: 0.25, animations: {
      label.alpha = 1
    }) { (b) in
      DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2, execute: {
        UIView.animate(withDuration: 0.25, animations: {
          label.alpha = 0
        }, completion: { (b) in
          label.removeFromSuperview()
        })
      })
    }
  }
}

二、ListView的基本使用

  1. activity_main.xml中添加ListView布局,充满父容器,其实iOS中的storyboard和xib文件也是xml语言编写(也就是说和android的xml文件类似),只不过苹果公司开发Xcode可以图形化界面进行设置约束,而Android Studio尽管也可以通过拖控件进行布局,但是一般都不使用。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

</LinearLayout>
  1. 设置ListView子项布局test_item.xml。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/test_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/set_icon_about"/>

    <TextView
        android:id="@+id/test_tile"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:text="hehe"
        android:textSize="21sp"
        android:layout_marginLeft="8dp"/>

</LinearLayout>
  1. 自定义ListView的适配器TestAdapter
public class TestAdapter extends ArrayAdapter {

    private int resourceID;

    public TestAdapter(@NonNull Context context, int resource, List<TestModel> objects) {
        super(context, resource,objects);
        resourceID = resource;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        TestModel testModel = (TestModel)getItem(position);
        View view;
        ViewHolder viewHolder;
        if (convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(resourceID, parent, false);
            viewHolder = new ViewHolder(view);
            view.setTag(viewHolder);
        } else {
            view = convertView;
            viewHolder = (ViewHolder)view.getTag();
        }
        viewHolder.imageView.setImageResource(testModel.getImageID());
        viewHolder.textView.setText(testModel.getTitle());
        return view;
    }

    class ViewHolder {
        ImageView imageView;
        TextView textView;
        ViewHolder(View view ) {
            imageView = (ImageView)view.findViewById(R.id.test_image);
            textView = (TextView)view.findViewById(R.id.test_tile);
        }
    }

}

  1. 添加Adapter数据,同iOS类似,demo添加了100条假数据。
  2. onCreate方法中创建一个TestAdapter对象adapter,并且设置为listView的适配器。为ListViewitem子项添加点击事件。
    MainActivity的代码如下:
public class MainActivity extends AppCompatActivity {
    private List<TestModel> dataList = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initsData();
        TestAdapter adapter = new TestAdapter(MainActivity.this,R.layout.test_item,dataList);
        ListView listView = (ListView)findViewById(R.id.list_view);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                TestModel model = dataList.get(i);
                Toast.makeText(MainActivity.this,model.getTitle(),Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void initsData() {
        for (int i = 0; i < 100; i ++) {
            TestModel testModel = new TestModel(R.drawable.set_icon_about,"关于");
            dataList.add(testModel);
            TestModel testModel2 = new TestModel(R.drawable.set_icon_change,"头像");
            dataList.add(testModel2);
            TestModel testModel3 = new TestModel(R.drawable.set_icon_clean,"清楚");
            dataList.add(testModel3);
            TestModel testModel4 = new TestModel(R.drawable.set_icon_edit,"修改");
            dataList.add(testModel4);
        }
    }
}

三、UITableView和ListView的对比

相同点:

  1. 都有重用机制,来提高滑动性能;
  2. 见文章开头所写;

不同点:

  1. UITableView继承自UIScrollView是一个滑动的View,而ListView则不是集成ScrollView。(或许这两点并没有没有可比性,毕竟是两个不同框架提供的库)
  2. UITableView有两种样式,group和plain。而ListView只有一种类似于iOS的plain模式,
    group样式

    plain样式

最后,文中使用的控件对比:
iOS图片显示控件UIImageView与Android的ImageView控件对应,文本显示控件iOS是UILabel,对应Android的TextView。
GitHub demo地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269