对于实现一个列表视图,使用苹果官方的方式真是恶心的不行,要实现多个代理,还要复写多个名字一样,参数名不同还很长的函数,真真的是写不下去的。。。
然后,依据android的adapter,弄了个swift版的Adapter类,方便的实现这一切,先看使用方法
简单使用
实现一个简单的UICollectionView列表视图:
class MyMolde{
//数据model
}
class MyViewCell: UICollectionViewCell {
//创建Cell布局
}
//创建一个 adapter 类,传入泛型 model 和 cell
class MyAdapter: BaseQuickAdapter<MyMolde,MyViewCell> {
//cell大小
override func cellSize(data:MyMolde, indexPath:IndexPath) ->CGSize{
CGSize(width:ScreenWidth, height:PT_100)
}
override func bindView(data:MyMolde, indexPath:IndexPath, cell:MyViewCell) {
//将model的数据显示到cell上面
}
}
复制代码
然后绑定:
let mCollectionView = UICollectionView(frame: .zero ,collectionViewLayout: UICollectionViewFlowLayout())
let mAdapter = MyAdapter()
//绑定collectionView 和 adapter
mCollectionView.setAdapter(mAdapter)
复制代码
完事收工!!!
进阶使用
mAdapter.setOnItemSelected { (indexPath, model) in
//处理点击事件
}
mAdapter.setOnItemLongPress { (indexPath, model) in
//处理长按事件
//移除数据
mAdapter.removeItem(indexPath)
}
//设置数据
let data = [MyMolde(),MyMolde(),MyMolde()]
mAdapter.setNewData(data)
//添加数据
mAdapter.appendData(MyMolde())
//获取adapter的数据
let dataArray = mAdapter.getData()
复制代码
使用多个cell布局
同样非常的简单
//数据model 实现 CellType 协议,根据cellType属性区分要使用的cell类型,cellType即注册cell时使用的标识
class MyMolde:CellType{
static let TYPE_1 = "1"
static let TYPE_2 = "2"
//根据不同的布局设置不同的type
var cellType: String = TYPE_1
}
class MyViewCell: UICollectionViewCell {
//创建Cell布局
}
class MyViewCell2: UICollectionViewCell {
//创建Cell布局
}
//创建一个 adapter 类
class MyAdapter: BaseAdapter<MyMolde> {
override init() {
super.init()
//注册cell
registerCell(MyViewCell.self, MyMolde.TYPE_1)
registerCell(MyViewCell2.self, MyMolde.TYPE_2)
}
//cell大小
override func cellSize(data: MyMolde, indexPath: IndexPath) -> CGSize {
//根据data.cellType 设置不同的size
if data.cellType == MyMolde.TYPE_1 {
return CGSize(width: ScreenWidth, height: PT_100)
}else if data.cellType == MyMolde.TYPE_2{
return CGSize(width: ScreenWidth, height: PT_200)
}
return .zero
}
override func bindView(data: MyMolde, indexPath: IndexPath, collectionCell: UICollectionViewCell) {
//将model的数据显示到cell上面
//根据data.cellType 转换成不同的 cell
if data.cellType == MyMolde.TYPE_1 {
let cell = collectionCell as! MyViewCell
}else if data.cellType == MyMolde.TYPE_2{
let cell = collectionCell as! MyViewCell2
}
}
}
复制代码
目前就弄了这点功能,如果有使用到其他功能,后期再加。
初学者,代码比较简陋随意O(∩_∩)O,欢迎指正!
BaseAdapter源码:
//
// BaseAdapter.swift
// bookista
//
// Created by DU on 2021/4/25.
//
import Foundation
let DefaultCellId = "BaseCell" //默认的cellId
class BaseAdapter<T> :NSObject,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout, UITableViewDelegate,UITableViewDataSource{
private var mData = [T]()//数据列表
private var mCell = [String:AnyClass?]() //需要注册的cell
private var onItemSelected:((IndexPath,T)->Void)? //点击事件
private var onItemLongPress:((IndexPath,T)-> Void)? //长按事件
private var mCollectionView:UICollectionView?
private var mTableView:UITableView?
/**
绑定 UICollectionView
*/
func bindTo(_ collectionView: UICollectionView){
if mTableView != nil || mCollectionView != nil {
fatalError("已经绑定过 UITableView 或 UICollectionView")
}
mCollectionView = collectionView
mCollectionView?.delegate = self
mCollectionView?.dataSource = self
mCell.forEach { (cell) in
mCollectionView?.register(cell.value, forCellWithReuseIdentifier: cell.key)
}
}
/**
绑定 UITableView
*/
func bindTo(_ tableView: UITableView){
if mTableView != nil || mCollectionView != nil{
fatalError("已经绑定过 UITableView 或 UICollectionView")
}
mTableView = tableView
mTableView?.delegate = self
mTableView?.dataSource = self
mCell.forEach { (cell) in
mTableView?.register(cell.value, forCellReuseIdentifier: cell.key)
}
}
/**
获取数据
*/
func getData() -> [T]{
return mData
}
/**
设置新的数据
*/
func setNewData(_ data:[T]){
mData.removeAll()
mData.append(contentsOf: data)
mCollectionView?.reloadData()
mTableView?.reloadData()
}
/**
添加数据
*/
func appendData(_ data:T){
mData.append(data)
mCollectionView?.reloadData()
mTableView?.reloadData()
}
/**
注册cell - 用于不用样式的cell注册
reuseIdentifier = model.cellType
*/
func registerCell(_ cell:AnyClass?,_ reuseIdentifier: String){
mCell.updateValue(cell, forKey: reuseIdentifier)
}
/**
注册cell - 只有一种样式
*/
func registerCell(_ cell:AnyClass?){
self.registerCell(cell, DefaultCellId)
}
/**
item 点击
*/
func setOnItemSelected(_ onItemSelected:((IndexPath,T)->Void)?){
self.onItemSelected = onItemSelected
}
/**
设置长按点击事件
*/
func setOnItemLongPress(_ todo: ((IndexPath,T)-> Void)?){
self.onItemLongPress = todo
let recognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressGesture(_:)))
self.mCollectionView?.addGestureRecognizer(recognizer)
self.mTableView?.addGestureRecognizer(recognizer)
}
//长按动作
@objc func longPressGesture(_ tap: UILongPressGestureRecognizer) {
if tap.state == .began {
if mTableView != nil {
guard let path = mTableView!.indexPathForRow(at: tap.location(in: mTableView!)) else {
return
}
self.onItemLongPress?(path,mData[path.row])
}else if mCollectionView != nil {
guard let path = mCollectionView!.indexPathForItem(at: tap.location(in: mCollectionView!)) else {
return
}
self.onItemLongPress?(path,mData[path.item])
}
}
}
/**
移除cell
*/
func removeItem(_ indexPath:IndexPath){
if mCollectionView != nil {
mData.remove(at: indexPath.item)
mCollectionView?.deleteItemsAtIndexPaths([indexPath], animationStyle: .automatic)
}else if mTableView != nil {
mData.remove(at: indexPath.row)
mTableView?.deleteItemsAtIndexPaths([indexPath], animationStyle: .automatic)
}
}
//MARK: UITableView =========================================================
/**
设置view显示内容 - UITableViewCell
*/
func bindView(data:T, indexPath: IndexPath, tableCell:UITableViewCell){
}
/**
table cell height
*/
func cellHeight(data:T, indexPath: IndexPath) -> CGFloat{
return 100
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
mData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cellId = DefaultCellId
if T.self is CellType {
cellId = (mData[indexPath.row] as! CellType).cellType
}
// let cellId = mData[indexPath.row].cellType
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
self.bindView(data: mData[indexPath.row], indexPath: indexPath, tableCell: cell)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.onItemSelected?(indexPath,mData[indexPath.row])
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return cellHeight(data: mData[indexPath.row], indexPath: indexPath)
}
//MARK: UICollectionView =========================================================
/**
设置view显示内容 - UICollectionViewCell
*/
func bindView(data:T, indexPath: IndexPath, collectionCell:UICollectionViewCell){
}
/**
cell size
*/
func cellSize(data:T, indexPath: IndexPath) -> CGSize{
return .zero
}
/**
行间距
*/
func lineSpace() -> CGFloat{
0
}
/**
左右间距
*/
func interitemSpace() -> CGFloat{
0
}
/**
section 边距
*/
func sectionInset() -> UIEdgeInsets {
.zero
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
mData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var cellId = DefaultCellId
if T.self is CellType {
cellId = (mData[indexPath.item] as! CellType).cellType
}
// let cellId = mData[indexPath.item].cellType
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
self.bindView(data: mData[indexPath.item], indexPath: indexPath, collectionCell: cell)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.onItemSelected?(indexPath,mData[indexPath.item])
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return cellSize(data:mData[indexPath.item],indexPath: indexPath)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return lineSpace()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return interitemSpace()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return sectionInset()
}
}
//MARK: BaseQuickAdapter =================================
/**
快速创建一个单样式的adapter
*/
class BaseQuickAdapter<Model,ViewCell:UIView>: BaseAdapter<Model> {
override init() {
super.init()
registerCell(ViewCell.self)
}
func bindView(data: Model, indexPath: IndexPath, cell: ViewCell){
}
override func bindView(data: Model, indexPath: IndexPath, tableCell: UITableViewCell) {
self.bindView(data: data, indexPath: indexPath, cell: tableCell as! ViewCell)
}
override func bindView(data: Model, indexPath: IndexPath, collectionCell: UICollectionViewCell) {
self.bindView(data: data, indexPath: indexPath, cell: collectionCell as! ViewCell)
}
}
//MARK: ===============================================
extension UICollectionView {
func setAdapter<T>(_ adapter:BaseAdapter<T>){
adapter.bindTo(self)
}
}
extension UITableView {
func setAdapter<T>(_ adapter:BaseAdapter<T>){
adapter.bindTo(self)
}
}
/**
实现不同布局的cell,使model类实现此协议
*/
protocol CellType{
/**
注册cell时的 ReuseIdentifier
*/
var cellType:String{get set}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END