1、給表格 UITableView 添加單元格移動功能
(1)給表格添加長按功能状答,長按后表格進(jìn)入編輯狀態(tài)
(2)在編輯狀態(tài)下冷守,可以看到單元格后面出現(xiàn)拖動按鈕
(3)鼠標(biāo)按住拖動按鈕,可以拖動單元格到任意位置
(4)拖動完畢后惊科,還會觸發(fā) TabelView 對應(yīng)的代理事件
2教沾、效果圖
image.png
import UIKit
class ViewController: UIViewController,UITableViewDelegate,
UITableViewDataSource,UIGestureRecognizerDelegate {
var tableView:UITableView?
var ctrlnames:[String] = ["UILabel 標(biāo)簽","UIButton 按鈕","UIDatePiker 日期選擇器",
"UITableView 表格視圖"]
override func viewDidLoad() {
super.viewDidLoad()
//創(chuàng)建表視圖
self.tableView = UITableView(frame: self.view.frame,
style:.plain)
self.tableView!.delegate = self
self.tableView!.dataSource = self
//創(chuàng)建一個重用的單元格
self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "SwiftCell")
self.view.addSubview(self.tableView!)
//綁定對長按的響應(yīng)
let longPress = UILongPressGestureRecognizer(target:self,
action:#selector(tableviewCellLongPressed(gestureRecognizer:)))
//代理
longPress.delegate = self
longPress.minimumPressDuration = 1.0
//將長按手勢添加到需要實(shí)現(xiàn)長按操作的視圖里
self.tableView!.addGestureRecognizer(longPress)
}
//在本例中,只有一個分區(qū)
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
//返回表格行數(shù)(也就是返回控件數(shù))
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.ctrlnames.count
}
//創(chuàng)建各單元顯示內(nèi)容(創(chuàng)建參數(shù)indexPath指定的單元)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
//為了提供表格顯示性能译断,已創(chuàng)建完成的單元需重復(fù)使用
let identify:String = "SwiftCell"
//同一形式的單元格重復(fù)使用,在聲明時已注冊
let cell = tableView.dequeueReusableCell(withIdentifier: identify, for: indexPath)
as UITableViewCell
cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
cell.textLabel?.text = self.ctrlnames[indexPath.row]
return cell
}
//長按表格
@objc func tableviewCellLongPressed(gestureRecognizer:UILongPressGestureRecognizer)
{
if (gestureRecognizer.state == UIGestureRecognizer.State.ended)
{
print("UIGestureRecognizerStateEnded")
//在正常狀態(tài)和編輯狀態(tài)之間切換
if(self.tableView!.isEditing == false){
self.tableView!.setEditing(true, animated:true)
}
else{
self.tableView!.setEditing(false, animated:true)
}
}
}
//在編輯狀態(tài)或悲,可以拖動設(shè)置cell位置
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
//移動cell事件
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath,
to destinationIndexPath: IndexPath) {
if sourceIndexPath != destinationIndexPath{
//獲取移動行對應(yīng)的值
let itemValue:String = ctrlnames[sourceIndexPath.row]
//刪除移動的值
ctrlnames.remove(at: sourceIndexPath.row)
//如果移動區(qū)域大于現(xiàn)有行數(shù)孙咪,直接在最后添加移動的值
if destinationIndexPath.row > ctrlnames.count{
ctrlnames.append(itemValue)
}else{
//沒有超過最大行數(shù),則在目標(biāo)位置添加剛才刪除的值
ctrlnames.insert(itemValue, at:destinationIndexPath.row)
}
}
}
}
2巡语、讓單元格只能在自己的分區(qū)中拖動
1翎蹈,問題描述
如果我們的 tableView 有多個 section,那么使用上面代碼會發(fā)現(xiàn)男公,單元格 cell 可以自由地在各個分區(qū)間拖動荤堪。比如我們可以把第1個 section 里的 cell 移動到第2個 section 中,反之亦然枢赔。
2澄阳,解決辦法
如果想要限制單元格只能在其所屬的 section 內(nèi)部拖動,可以增加如下代理方法進(jìn)行判斷踏拜。該方法在拖動某行到一個目標(biāo)上方時會被觸發(fā)碎赢,我們可以在方法內(nèi)部判斷是否允許移動,或者進(jìn)行修正速梗。
import UIKit
class ViewController: UIViewController,UITableViewDelegate,
UITableViewDataSource,UIGestureRecognizerDelegate {
var tableView:UITableView?
var ctrlnames:[[String]] = [["UILabel 標(biāo)簽","UIButton 按鈕","UIDatePiker 日期選擇器",
"UITableView 表格視圖"],["UIImageView 圖片","UITableVIew 列表","UIDatePiker 日期選擇器",
"UITableView 表格視圖"]]
override func viewDidLoad() {
super.viewDidLoad()
//創(chuàng)建表視圖
self.tableView = UITableView(frame: self.view.frame,
style:.grouped)
self.tableView!.delegate = self
self.tableView!.dataSource = self
//創(chuàng)建一個重用的單元格
self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "SwiftCell")
self.view.addSubview(self.tableView!)
//綁定對長按的響應(yīng)
let longPress = UILongPressGestureRecognizer(target:self,
action:#selector(tableviewCellLongPressed(gestureRecognizer:)))
//代理
longPress.delegate = self
longPress.minimumPressDuration = 1.0
//將長按手勢添加到需要實(shí)現(xiàn)長按操作的視圖里
self.tableView!.addGestureRecognizer(longPress)
}
//在本例中肮塞,只有一個分區(qū)
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
//返回表格行數(shù)(也就是返回控件數(shù))
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.ctrlnames[section].count
}
//創(chuàng)建各單元顯示內(nèi)容(創(chuàng)建參數(shù)indexPath指定的單元)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
//為了提供表格顯示性能襟齿,已創(chuàng)建完成的單元需重復(fù)使用
let identify:String = "SwiftCell"
//同一形式的單元格重復(fù)使用,在聲明時已注冊
let cell = tableView.dequeueReusableCell(withIdentifier: identify, for: indexPath)
as UITableViewCell
cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
cell.textLabel?.text = self.ctrlnames[indexPath.section][indexPath.row]
return cell
}
//長按表格
@objc func tableviewCellLongPressed(gestureRecognizer:UILongPressGestureRecognizer)
{
if (gestureRecognizer.state == UIGestureRecognizer.State.ended)
{
print("UIGestureRecognizerStateEnded")
//在正常狀態(tài)和編輯狀態(tài)之間切換
if(self.tableView!.isEditing == false){
self.tableView!.setEditing(true, animated:true)
}
else{
self.tableView!.setEditing(false, animated:true)
}
}
}
//在編輯狀態(tài)枕赵,可以拖動設(shè)置cell位置
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
//移動cell事件
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath,
to destinationIndexPath: IndexPath) {
if sourceIndexPath != destinationIndexPath{
let values: [String] = self.ctrlnames[sourceIndexPath.section]
//獲取移動行對應(yīng)的值
let itemValue:String = values[sourceIndexPath.row] as String
print(itemValue)
//刪除移動的值
ctrlnames[sourceIndexPath.section].remove(at: sourceIndexPath.row)
//如果移動區(qū)域大于現(xiàn)有行數(shù)猜欺,直接在最后添加移動的值
if destinationIndexPath.row > ctrlnames.count{
ctrlnames[destinationIndexPath.section].append(itemValue)
}else{
//沒有超過最大行數(shù),則在目標(biāo)位置添加剛才刪除的值
ctrlnames[destinationIndexPath.section].insert(itemValue, at:destinationIndexPath.row)
}
}
}
//拖拽某行到一個目標(biāo)上方時觸發(fā)該方法拷窜,詢問是否移動或者修正
func tableView(_ tableView: UITableView,
targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath,
toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath {
//如果目標(biāo)位置和拖動行不是同一個分區(qū)开皿,則拖動行返回自己原來的分區(qū)
if sourceIndexPath.section != proposedDestinationIndexPath.section {
var row = 0
//如果是往下面的分區(qū)拖動,則回到原分區(qū)末尾
//如果是往上面的分區(qū)拖動装黑,則會到原分區(qū)開頭位置
if sourceIndexPath.section < proposedDestinationIndexPath.section {
row = tableView.numberOfRows(inSection: sourceIndexPath.section)-1
}
return IndexPath(row: row, section: sourceIndexPath.section)
}
return proposedDestinationIndexPath
}
}