Возможность сократить длительность печати UIDragInteraction
Я сейчас пользуюсь UIDragInteraction
а также UIDropInteraction
сделанный доступным в iOS 11, чтобы сделать простую функцию перетаскивания, где пользователь мог перетащить UIImageView на UIView.
Я понял, что одним неинтуитивным элементом этого является то, что UIDragInteraction
для работы требуется долгое нажатие не менее секунды. Мне было интересно, если есть способ сократить длительность печати? Документы на Apple, кажется, не подчеркивают это.
Спасибо!
Реализация вставлена ниже для справки:
class ViewController: UIViewController {
@IBOutlet var imageView: UIImageView!
@IBOutlet var dropArea: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let dragInteraction = UIDragInteraction(delegate: self)
imageView.addInteraction(dragInteraction)
dragInteraction.isEnabled = true
let dropInteraction = UIDropInteraction(delegate: self)
dropArea.addInteraction(dropInteraction)
}
}
extension ViewController: UIDragInteractionDelegate {
func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
guard let image = imageView.image
else { return [] }
let itemProvider = NSItemProvider(object: image)
return [UIDragItem(itemProvider: itemProvider)]
}
}
extension ViewController: UIDropInteractionDelegate {
func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
return UIDropProposal(operation: .copy)
}
func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
guard let itemProvider = session.items.first?.itemProvider,
itemProvider.canLoadObject(ofClass: UIImage.self)
else { return }
itemProvider.loadObject(ofClass: UIImage.self) { [weak self] loadedItem, error in
guard let image = loadedItem as? UIImage
else { return }
DispatchQueue.main.async {
self?.dropArea.image = image
}
}
}
}
3 ответа
Нет очевидного способа сделать это, но я просто столкнулся с той же проблемой и взглянул на распознаватели жестов представления, к которому присоединено dragInteraction. Это _UIDragLiftGestureRecognizer
который не является частью публичного API, но оказывается, что это просто подкласс UILongPressGestureRecognizer
,
Итак, после добавления UIDragInteraction
на ваш взгляд, и после добавления этого представления к иерархии представления (так как я использую пользовательский подкласс UIView, я просто добавил его в didMoveToSuperview()
), вы можете сделать что-то вроде этого:
if let longPressRecognizer = gestureRecognizers?.compactMap({ $0 as? UILongPressGestureRecognizer}).first {
longPressRecognizer.minimumPressDuration = 0.1 // your custom value
}
Я пытался сделать это из Xamarin.iOS внутри UIView
реализация IUIDragInteractionDelegate
интерфейс. В своем конструкторе я сделал SetupDragNDrop
метод, который позволяет перетаскивать вид без заданной по умолчанию задержки / задержки, чтобы поймать вид. Я оставляю код ниже на случай, если он пригодится кому-то еще:
#region Private Fields
private UIDragInteraction _UIDragInteraction;
#endregion
void Initialize()
{
SetupDragNDrop();
}
private void SetupDragNDrop()
{
UserInteractionEnabled = true;
_UIDragInteraction = new UIDragInteraction(this);
AddInteraction(_UIDragInteraction);
// On iPad, this defaults to true. On iPhone, this defaults to
// false. Since this app should work on the iPhone, enable the the
// drag interaction.
_UIDragInteraction.Enabled = true;
SetupDragDelay();
}
private void SetupDragDelay()
{
UILongPressGestureRecognizer longPressGesture = new UILongPressGestureRecognizer();
GestureRecognizers?.ToList().ForEach(gesture =>
{
var x = gesture as UILongPressGestureRecognizer;
if (x != null)
{
longPressGesture = x;
}
});
longPressGesture.MinimumPressDuration = 0.0;
}
Вы можете использовать этот код, чтобы не влиять на другие жесты:
let gestureRecognizers = self.view.gestureRecognizers?.compactMap({ $0 as? UILongPressGestureRecognizer })
let liftGesture = gestureRecognizers?.filter({ String(describing: type(of: $0)) == "_UIDragLiftGestureRecognizer" }).first
liftGesture?.minimumPressDuration = minimumPressDuration//use custom value
Также это может помочь кому-то настроить SwiftUI.
onDrag
:
extension View {
public func customizeOnDrag(minimumPressDuration: TimeInterval) -> some View {
overlay(CustomizeOnDrag(minimumPressDuration: minimumPressDuration).frame(width: 0, height: 0))
}
}
private struct CustomizeOnDrag: UIViewControllerRepresentable {
private let minimumPressDuration: TimeInterval
init(minimumPressDuration: TimeInterval) {
self.minimumPressDuration = minimumPressDuration
}
func makeUIViewController(context: Context) -> UIViewControllerType {
return UIViewController()
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
DispatchQueue.main.async {
let gestureRecognizers = uiViewController.parent?.view.gestureRecognizers?.compactMap({ $0 as? UILongPressGestureRecognizer })
let liftGesture = gestureRecognizers?.filter({ String(describing: type(of: $0)) == "_UIDragLiftGestureRecognizer" }).first
liftGesture?.minimumPressDuration = minimumPressDuration
}
}
}