Skip to content

Commit a742403

Browse files
authored
feat(ios/android): be able to drag and drop without explicit editing mode (#13472)
* feat(ios): be able to drag and drop without explicit editing mode * fix: fix format * fix(cli): fix swiftlint warning * fix(ios): fix item provider config and proxy setup * fix(ios): fix linting * feat(android): don’t require editing mode to drag and drop cells * fix: fix selection issue * Update ListView.yml * Update ListView.yml * fix: fix setter * fix(ios): fix setter call
1 parent d60baec commit a742403

File tree

12 files changed

+70
-10
lines changed

12 files changed

+70
-10
lines changed

android/modules/ui/src/java/ti/modules/titanium/ui/TableViewProxy.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ private void processProperty(String name, Object value)
948948
if (name.equals(TiC.PROPERTY_DATA) || name.equals(TiC.PROPERTY_SECTIONS)) {
949949
setData((Object[]) value);
950950

951-
} else if (name.equals(TiC.PROPERTY_EDITING)) {
951+
} else if (name.equals(TiC.PROPERTY_EDITING) || name.equals(TiC.PROPERTY_REQUIRES_EDITING_TO_MOVE)) {
952952
final TiViewProxy parent = getParent();
953953

954954
if (parent != null) {

android/modules/ui/src/java/ti/modules/titanium/ui/widget/listview/ItemTouchHandler.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,11 @@ public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull Recycle
242242
*/
243243
private boolean isEditing()
244244
{
245-
return this.recyclerViewProxy.getProperties().optBoolean(TiC.PROPERTY_EDITING, false);
245+
boolean isEditing = this.recyclerViewProxy.getProperties().optBoolean(TiC.PROPERTY_EDITING, false);
246+
boolean requiresEditingToMove =
247+
this.recyclerViewProxy.getProperties().optBoolean(TiC.PROPERTY_REQUIRES_EDITING_TO_MOVE, true);
248+
249+
return isEditing || !requiresEditingToMove;
246250
}
247251

248252
/**

android/modules/ui/src/java/ti/modules/titanium/ui/widget/listview/ListViewHolder.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,12 @@ public void bind(final ListItemProxy proxy, final boolean selected)
119119
final int minHeight = TiConvert.toTiDimension(rawMinHeight, TiDimension.TYPE_HEIGHT).getAsPixels(itemView);
120120
this.content.setMinimumHeight(minHeight);
121121

122+
boolean canEdit = listViewProperties.optBoolean(TiC.PROPERTY_EDITING, false)
123+
|| !listViewProperties.optBoolean(TiC.PROPERTY_REQUIRES_EDITING_TO_MOVE, true);
124+
122125
// Handle selection checkmark.
123126
if (listViewProperties.optBoolean(TiC.PROPERTY_SHOW_SELECTION_CHECK, false)
124-
&& listViewProperties.optBoolean(TiC.PROPERTY_EDITING, false)
127+
&& canEdit
125128
&& listViewProperties.optBoolean(TiC.PROPERTY_ALLOWS_SELECTION_DURING_EDITING, false)
126129
&& listViewProperties.optBoolean(TiC.PROPERTY_ALLOWS_MULTIPLE_SELECTION_DURING_EDITING, false)
127130
&& !proxy.isPlaceholder()) {

android/modules/ui/src/java/ti/modules/titanium/ui/widget/listview/ListViewProxy.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
TiC.PROPERTY_HEADER_TITLE,
4949
TiC.PROPERTY_HEADER_VIEW,
5050
TiC.PROPERTY_REFRESH_CONTROL,
51+
TiC.PROPERTY_REQUIRES_EDITING_TO_MOVE,
5152
TiC.PROPERTY_SEARCH_TEXT,
5253
TiC.PROPERTY_SEARCH_VIEW,
5354
TiC.PROPERTY_SEPARATOR_COLOR,
@@ -524,7 +525,8 @@ private void processProperty(String name, Object value)
524525
// Set list sections.
525526
setSections((Object[]) value);
526527

527-
} else if (name.equals(TiC.PROPERTY_EDITING) || name.equals(TiC.PROPERTY_VISIBLE)) {
528+
} else if (name.equals(TiC.PROPERTY_EDITING) || name.equals(TiC.PROPERTY_REQUIRES_EDITING_TO_MOVE)
529+
|| name.equals(TiC.PROPERTY_VISIBLE)) {
528530
final TiViewProxy parent = getParent();
529531

530532
if (parent != null) {

android/modules/ui/src/java/ti/modules/titanium/ui/widget/listview/TiListView.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -264,14 +264,15 @@ public boolean inSelectionHotspot(@NonNull MotionEvent e)
264264

265265
final KrollDict properties = proxy.getProperties();
266266
final boolean editing = properties.optBoolean(TiC.PROPERTY_EDITING, false);
267+
final boolean requiresEditingToMove = properties.optBoolean(TiC.PROPERTY_REQUIRES_EDITING_TO_MOVE, true);
267268
final boolean allowsSelection = properties.optBoolean(TiC.PROPERTY_ALLOWS_SELECTION_DURING_EDITING, false);
268269
final boolean allowsMultipleSelection
269270
= properties.optBoolean(TiC.PROPERTY_ALLOWS_MULTIPLE_SELECTION_DURING_EDITING, false);
270271

271272
if (properties.optBoolean(TiC.PROPERTY_FIXED_SIZE, false)) {
272273
this.recyclerView.setHasFixedSize(true);
273274
}
274-
if (editing && allowsSelection) {
275+
if ((editing || !requiresEditingToMove) && allowsSelection) {
275276
if (allowsMultipleSelection) {
276277
this.tracker = trackerBuilder.withSelectionPredicate(SelectionPredicates.createSelectAnything())
277278
.build();
@@ -767,13 +768,15 @@ public void run()
767768

768769
if (firstUpdate && tracker != null) {
769770
final boolean editing = properties.optBoolean(TiC.PROPERTY_EDITING, false);
771+
final boolean requiresEditingToMove =
772+
properties.optBoolean(TiC.PROPERTY_REQUIRES_EDITING_TO_MOVE, true);
770773

771774
for (final ListItemProxy item : items) {
772775

773776
// Re-select previously selected items.
774777
// This can occur when the theme is changed.
775778
if (item.isSelected()) {
776-
if (!editing) {
779+
if (!editing || requiresEditingToMove) {
777780
item.setSelected(false);
778781
continue;
779782
}

android/titanium/src/java/org/appcelerator/titanium/TiC.java

+1
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,7 @@ public class TiC
652652
public static final String PROPERTY_REPEAT_COUNT = "repeatCount";
653653
public static final String PROPERTY_REPEAT_MODE = "repeatMode";
654654
public static final String PROPERTY_REQUEST_HEADERS = "requestHeaders";
655+
public static final String PROPERTY_REQUIRES_EDITING_TO_MOVE = "requiresEditingToMove";
655656
public static final String PROPERTY_RETURN_KEY_TYPE = "returnKeyType";
656657
public static final String PROPERTY_REVERSE = "reverse";
657658
public static final String PROPERTY_RIGHT = "right";

apidoc/Titanium/UI/ListView.yml

+12
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ description: |
191191
192192
- [editing](Titanium.UI.ListView.editing) - Determines if the List View is in a state where items can
193193
be deleted or reordered.
194+
195+
- [requiresEditingToMove](Titanium.UI.ListView.requiresEditingToMove) - Determines if the ListView
196+
should be able to drag-and-drop without explicitely enabling editing support (like drag bars).
194197
195198
- [pruneSectionsOnEdit](Titanium.UI.ListView.pruneSectionsOnEdit) - When this property is set to true and the
196199
user action results in a section having no other items, the section is deleted from the List View. Please note
@@ -675,6 +678,15 @@ properties:
675678
since: {android: "9.3.0", iphone: "3.2.0", ipad: "3.2.0", macos: "9.2.0"}
676679
platforms: [android, iphone, ipad, macos]
677680

681+
- name: requiresEditingToMove
682+
summary: Determines if the list view should allow drag-and-drop even without going into the editing mode
683+
description: |
684+
For more information see the "Editing Support" section of <Titanium.UI.ListView>.
685+
type: Boolean
686+
default: true
687+
since: "11.1.0"
688+
platforms: [android, iphone, ipad, macos]
689+
678690
- name: fastScroll
679691
summary: Sets the fastScroll mode on Android ListViews.
680692
description: |

iphone/Classes/TiUIListView.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#import "TiUIListViewProxy.h"
1010
#import <TitaniumKit/TiUIView.h>
1111

12-
@interface TiUIListView : TiUIView <UITableViewDelegate, UITableViewDataSource, UITableViewDataSourcePrefetching, UIScrollViewDelegate, UIGestureRecognizerDelegate, UISearchBarDelegate, UISearchResultsUpdating, UISearchControllerDelegate, TiScrolling, TiProxyObserver, TiUIListViewDelegateView>
12+
@interface TiUIListView : TiUIView <UITableViewDelegate, UITableViewDataSource, UITableViewDataSourcePrefetching, UIScrollViewDelegate, UIGestureRecognizerDelegate, UISearchBarDelegate, UISearchResultsUpdating, UISearchControllerDelegate, TiScrolling, TiProxyObserver, TiUIListViewDelegateView, UITableViewDragDelegate, UITableViewDropDelegate>
1313

1414
#pragma mark - Private APIs
1515

iphone/Classes/TiUIListView.m

+35
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifdef USE_TI_UIREFRESHCONTROL
1818
#import "TiUIRefreshControlProxy.h"
1919
#endif
20+
#import <MobileCoreServices/MobileCoreServices.h>
2021
#import <TitaniumKit/ImageLoader.h>
2122

2223
@interface TiUIListView ()
@@ -203,12 +204,19 @@ - (UITableView *)tableView
203204
{
204205
if (_tableView == nil) {
205206
UITableViewStyle style = [TiUtils intValue:[self.proxy valueForKey:@"style"] def:UITableViewStylePlain];
207+
BOOL requiresEditingToMove = [TiUtils boolValue:[self.proxy valueForKey:@"requiresEditingToMove"] def:YES];
206208

207209
_tableView = [[UITableView alloc] initWithFrame:self.bounds style:style];
208210
_tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
209211
_tableView.delegate = self;
210212
_tableView.dataSource = self;
211213

214+
if (!requiresEditingToMove) {
215+
_tableView.dragDelegate = self;
216+
_tableView.dropDelegate = self;
217+
_tableView.dragInteractionEnabled = YES;
218+
}
219+
212220
// Fixes incorrect heights in iOS 11 as we calculate them internally already
213221
_tableView.estimatedRowHeight = 0;
214222
_tableView.estimatedSectionFooterHeight = 0;
@@ -2553,6 +2561,33 @@ + (UITableViewRowAnimation)animationStyleForProperties:(NSDictionary *)propertie
25532561
return animate ? UITableViewRowAnimationFade : UITableViewRowAnimationNone;
25542562
}
25552563

2564+
- (nonnull NSArray<UIDragItem *> *)tableView:(nonnull UITableView *)tableView itemsForBeginningDragSession:(nonnull id<UIDragSession>)session atIndexPath:(nonnull NSIndexPath *)indexPath
2565+
{
2566+
NSItemProvider *itemProvider = [NSItemProvider new];
2567+
NSString *identifier = [NSString stringWithFormat:@"%lu_%lu", indexPath.section, indexPath.row];
2568+
2569+
[itemProvider registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypePlainText
2570+
visibility:NSItemProviderRepresentationVisibilityAll
2571+
loadHandler:^NSProgress *_Nullable(void (^_Nonnull completionHandler)(NSData *_Nullable, NSError *_Nullable)) {
2572+
return nil;
2573+
}];
2574+
2575+
UIDragItem *dragItem = [[UIDragItem alloc] initWithItemProvider:itemProvider];
2576+
dragItem.localObject = identifier;
2577+
2578+
return @[ dragItem ];
2579+
}
2580+
2581+
- (void)tableView:(UITableView *)tableView performDropWithCoordinator:(id<UITableViewDropCoordinator>)coordinator
2582+
{
2583+
// NO-OP right now
2584+
}
2585+
2586+
- (BOOL)tableView:(UITableView *)tableView canHandleDropSession:(id<UIDropSession>)session
2587+
{
2588+
return [session canLoadObjectsOfClass:[NSString class]];
2589+
}
2590+
25562591
@end
25572592

25582593
static TiViewProxy *FindViewProxyWithBindIdContainingPoint(UIView *view, CGPoint point)

iphone/Classes/TiUIListViewProxy.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ - (NSArray *)keySequence
207207
static dispatch_once_t onceToken;
208208
static NSArray *keySequence = nil;
209209
dispatch_once(&onceToken, ^{
210-
keySequence = [[NSArray alloc] initWithObjects:@"style", @"showSearchBarInNavBar", @"templates", @"defaultItemTemplate", @"sections", @"backgroundColor", nil];
210+
keySequence = [[NSArray alloc] initWithObjects:@"style", @"requiresEditingToMove", @"showSearchBarInNavBar", @"templates", @"defaultItemTemplate", @"sections", @"backgroundColor", nil];
211211
});
212212
return keySequence;
213213
}

lint-staged.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module.exports = {
1919
'npx clang-format -style=file -i'
2020
],
2121
'iphone/Classes/**/*.swift': [
22-
'swiftlint autocorrect'
22+
'swiftlint --fix'
2323
],
2424
'iphone/TitaniumKit/TitaniumKit/Sources/API/TopTiModule.m': [
2525
'npm run ios-sanity-check --'

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"format:android": "echo Formatting Android code is not supported.",
4343
"format:ios": "npm-run-all --parallel format:objc format:swift",
4444
"format:objc": "npm run lint:objc -- --fix",
45-
"format:swift": "npm run lint:swift -- autocorrect",
45+
"format:swift": "npm run lint:swift",
4646
"format:js": "npm run lint:js -- --fix",
4747
"ios": "node ./build/scons cleanbuild ios",
4848
"ios-sanity-check": "node ./build/scons check-ios-toplevel",

0 commit comments

Comments
 (0)