一個iOS開發(fā)者的android修行之路二:UITableView和ListView的對比探究

盡管現(xiàn)在主流的移動設(shè)備的屏幕尺寸都越來越大,特別是iPhone X的出現(xiàn),以后的趨勢都是全屏手機(jī),但是一屏的顯示的內(nèi)容還是有限的,當(dāng)我們需要有大量數(shù)據(jù)需要展示時就可以使用這兩個控件。這兩個控件的相同點(diǎn)都是允許用戶上下滑動,以便展示屏幕區(qū)域外的內(nèi)容。很多主流的應(yīng)用,比如微信、QQ的消息列表,微信朋友圈,微博等等應(yīng)用的很多界面都是使用這兩個控件實(shí)現(xiàn)的。

一、UITableView的基本使用

  1. iOS添加一個UITableView有兩種方式。一是:純代碼初始化一個UITableView;二是在storyboard中直接拖入一個UITableView并且設(shè)置約束添加,同時設(shè)置tableView的dataSource和delegate為ViewController。這兩種方式并沒有優(yōu)劣之分,使用第二種方式是蘋果推薦的快速開發(fā)的方式。我的事例代碼選擇的第二種方法。
    在storyboard添加UITableView的四步曲
  2. 自定義UITableViewCell,勾選同時勾選xib,我這里命名為TestTableViewCell,里面添加兩個控件ImageView和Label,同時設(shè)置應(yīng)用。同時設(shè)置xib中的重用identifier為:TestTableViewCell。
  3. 注冊重用的cell,在ViewControllerviewDidLoad方法中注冊自定義cell。
let nib = UINib(nibName: "TestTableViewCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "TestTableViewCell")
  1. 配置tableView顯示的數(shù)據(jù)源,實(shí)際項(xiàng)目中為網(wǎng)絡(luò)請求的數(shù)據(jù),demo中為模擬了100條假數(shù)據(jù)。
  2. 實(shí)現(xiàn)tableView的數(shù)據(jù)源和代理方法。
    其中這兩個數(shù)據(jù)源方法必須實(shí)現(xiàn):func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Intfunc tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell,否則會app會閃退。其中第一個方法用來指明cell的個數(shù),第二個方法用來設(shè)置cell的數(shù)據(jù),demo中的設(shè)置UIImageView和UILabel。
    cell點(diǎn)擊事件的響應(yīng),則需要實(shí)現(xiàn)代理方法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: "關(guān)于")
      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布局,充滿父容器,其實(shí)iOS中的storyboard和xib文件也是xml語言編寫(也就是說和android的xml文件類似),只不過蘋果公司開發(fā)Xcode可以圖形化界面進(jìn)行設(shè)置約束,而Android Studio盡管也可以通過拖控件進(jìn)行布局,但是一般都不使用。
<?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. 設(shè)置ListView子項(xiàng)布局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數(shù)據(jù),同iOS類似,demo添加了100條假數(shù)據(jù)。
  2. onCreate方法中創(chuàng)建一個TestAdapter對象adapter,并且設(shè)置為listView的適配器。為ListViewitem子項(xiàng)添加點(diǎn)擊事件。
    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,"關(guān)于");
            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的對比

相同點(diǎn):

  1. 都有重用機(jī)制,來提高滑動性能;
  2. 見文章開頭所寫;

不同點(diǎn):

  1. UITableView繼承自UIScrollView是一個滑動的View,而ListView則不是集成ScrollView。(或許這兩點(diǎn)并沒有沒有可比性,畢竟是兩個不同框架提供的庫)
  2. UITableView有兩種樣式,group和plain。而ListView只有一種類似于iOS的plain模式,
    group樣式

    plain樣式

最后,文中使用的控件對比:
iOS圖片顯示控件UIImageView與Android的ImageView控件對應(yīng),文本顯示控件iOS是UILabel,對應(yīng)Android的TextView。
GitHub demo地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容