Custom Delete button On Editing in UITableView Cell - iphone

I have gone through this question that shows the following code:
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{
return #"Sagar";
}
What if I want a custom image instead of the default red button?

Implement this method in custom cell
- (void)willTransitionToState:(UITableViewCellStateMask)state{
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask) {
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"]) {
UIImageView *deleteBtn = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 64, 33)];
[deleteBtn setImage:[UIImage imageNamed:#"delete.png"]];
[[subview.subviews objectAtIndex:0] addSubview:deleteBtn];
[deleteBtn release];
}
}
}
}

This is a late reply but I hope someone may find this helpful. So the accepted answer seems sort of complicated for me, and #user1684899's answer only works if you just want to change the look of the delete button. I want to completely change the appearance of the delete button (i.e. its frame, position, etc.), so my solution is to add my own delete button to my custom cell and keep it initially hidden, and only show it when the cell is in edit mode. What's more important, I want to hide iOS's original delete button and support backward compatibility, and here's my trick:
- (void)willTransitionToState:(UITableViewCellStateMask)state
{
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask)
{
if (!IS_IOS_7){
for (UIView *subview in self.subviews)
{
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"])
{
// hide original button
[[subview.subviews objectAtIndex:0] setHidden:YES];
// show my custom button
[self.deleteButton setHidden:NO];
}
}
} else {
for (UIView *subview in self.subviews) {
for (UIView *subview2 in subview.subviews) {
if ([NSStringFromClass([subview2 class]) rangeOfString:#"Delete"].location != NSNotFound) {
// hide original button
[subview2 setHidden:YES];
// show my custom button
[self.deleteButton setHidden:NO];
}
}
}
}
} else {
// hide my custom button otherwise
[self.deleteButton setHidden:YES];
}
}
And don't forget to add:
[cell.deleteButton addTarget:self action:#selector(deleteEntryAtIndexPath:) forControlEvents:UIControlEventTouchUpInside];
in cellForRowAtIndexPath, so that you can add any thing you want when your delete button is clicked. Here is my result:

The systemwide standard for the intended list-dive-in action, as you said in the comment on luvieere's answer, would be to use the detail-disclosure (blue circled arrow) cell accessory, not the swipe gesture.
That said, if you still want to use the swipe action for this, there's no way to provide your own button without manually intercepting and completely reimplementing the swipe gesture, like what Tweetie does.

luvieere is right -- if you want that same "delete" metaphor, you want to keep it at the red button that Apple provides. Why change it? Its globally recognizable as the standard for delete buttons.
Although, if you want something like Tweetie, where you completely change the behavior of swiping, you could use something like ABTableViewCell where you just draw in your own view. Make a custom table view, override -touchesBegan:withEvent:, and check for touches. Calculate the delta of the two touches (in touchesMoved:withEvent:) and move your own view around.

Related

UISearchDisplayController hide drop shadow

If you look closely to the bottom of the UISearchBar in a UISearchDisplayController, you'll notice it has a subtile drop shadow. This shadow doesn't fit in the design of the app I'm currently working on, so I'm trying to remove/hide it. Unfortunately I have not yet succeeded.
During my research into this drop shadow, I found that it's not part of the UISearchBar. When I remove the UISearchDisplayController's UISearchBar from its superview in - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller, the shadow remains visible.
The shadow turned out to be part of the UISearchDisplayController's searchResultsTableView: when I hide the searchResultsTableView, the shadow disappears. However, I have not been able to trace down the view that has the shadow on its layer. I tried recursively iterating through all visible views (starting at [[UIApplication sharedApplication] window]) and then hiding the drop shadow of each view and setting its clipsToBounds property to YES, which also did not yield the desired result.
Any ideas?
I finally found a solution. Since setting clipsToBounds to YES and hiding the drop shadow of each view in the hierarchy didn't work, it's obvious that the shadow is an image. After iterating through all subviews of the searchResultsTableView and printing their class property, I found an instance of _UISearchBarShadowView, which obviously is the culprit. So what I'm doing now is finding the _UISearchBarShadowView and setting its alpha to 0.0f.
- (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
{
[self _findAndHideSearchBarShadowInView:tableView];
}
- (void)_findAndHideSearchBarShadowInView:(UIView *)view
{
NSString *usc = #"_";
NSString *sb = #"UISearchBar";
NSString *sv = #"ShadowView";
NSString *s = [[usc stringByAppendingString:sb] stringByAppendingString:sv];
for (UIView *v in view.subviews)
{
if ([v isKindOfClass:NSClassFromString(s)]) {
v.alpha = 0.0f;
}
[self _findAndHideSearchBarShadowInView:v];
}
}
The accepted answer uses a private API, which could get your app rejected. Instead, I'd just locate and hide any subviews that are also custom subclasses of UIImageView, like so:
- (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
{
for (UIView *view in tableView.subviews) {
if ([view.class isSubclassOfClass:[UIImageView class]]) {
view.alpha = 0.f;
}
}
}

Can I tint (black) a UIKeyboard? If so, how?

Is there a way to get a black keyboard? The default one is bluish. And the Alert style one is semi-transparent black. I was wondering if it was possible to have the keyboard black, e.g. non transparent. Or do I have to pull up a black view behind the keyboard to reduce the transparency effect?
The short answer is, NO. The only two keyboards you can display are the normal and alert style keyboards.
There are ways to hack around, get the ui keyboard and change it's composition. I wouldn't recommend doing this as it will 1) likely make have your app rejected from the app store and 2) likely break the next time an iOS revision comes around.
Seems like putting a black or white view behind the keyboard should work for application. In this case I would recommend looking here for a way to animate that black view up below the keyboard.
As Ben states above you can just use one of these two values:
[textView setKeyboardAppearance:UIKeyboardAppearanceAlert];
[textView setKeyboardAppearance:UIKeyboardAppearanceDefault];
Here is code to remove the UIKeyboard background by hiding it. Feel free to modify it to tint the UIKeyboard:
-(NSArray*)subviewsOfView:(UIView*)view withType:(NSString*)type{
NSString *prefix = [NSString stringWithFormat:#"<%#",type];
NSMutableArray *subviewArray = [NSMutableArray array];
for (UIView *subview in view.subviews) {
NSArray *tempArray = [self subviewsOfView:subview withType:type];
for (UIView *view in tempArray) {
[subviewArray addObject:view];
}
}
if ([[view description]hasPrefix:prefix]) {
[subviewArray addObject:view];
}
return [NSArray arrayWithArray:subviewArray];
}
-(void)removeKeyboardBackground{
for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows]) {
for (UIView *keyboard in [keyboardWindow subviews]) {
for (UIView *view in [self subviewsOfView:keyboard withType:#"UIKBBackgroundView"]) {
view.hidden=YES;
}
}
}
}
Just call [self removeKeyboardBackground] after you received a NSNotification for UIKeyboardDidShowNotification. Do whatever you want with the background view by replacing view.hidden=YES; with whatever you would like.

iPhone: How to remove all objects from a UIScrollView

Basically I want to remove all objects from a UIScrollView and I haven't yet found a solution to it because a simple "removeAllObjects" command doesn't work. Does anyone have an idea how to do it?
Even easier:
[[scrollView subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
The easiest way:
for(UIView *subview in [scrollView subviews]) {
[subview removeFromSuperview];
}
Two solutions would be, without removing the scrollbars:
Add a tag to all of your subviews, remove them by using those tags.
Implementation:
Place this above your class
#define XPScrollViewSubviewStartTag 100
When you add the objects
for(NSInteger = 0;i<[viewArray count];i++){
UIView* view = [viewArray objectAtIndex:i];
view.tag = XPScrollViewSubviewStartTag + i;
[scrollView addSubview:view];
}
When you later want to delete the views use
for(UIView* view in [scrollView subviews]){
if(view.tag >= XPScrollViewSubviewStartTag)
[view removeFromSuperview];
}
Create a custom UIView class
When you want to remove the views
for(id view in [scrollView subviews]){
if(![view isKindOfClass:[CustomView class]])
continue;
//not necessary, but just to make things understandable
CustomView* customView = (CustomView*)view;
[customView removeFromSuperview];
}
Oritm's solution is nice, but if you don't want to bother using tags, you can manually remove which views you want to remove from the scrollview. This will assume that you know which view to remove. For example, my scrollview only has UILabels so when I run the following:
// This will remove the scrollview but the scrollbars will remain
for (UIView *subview in [self.detailsExpander.scrollView subviews]) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UILabel"])
[subview removeFromSuperview];
}
This will only remove all the labels but keep the scrollbars (which are image views). Note: this won't work if you want to keep specific image views while at the same time you want to keep the scrollbars.

Weird view, in UITableViewCell at editing mode, while reorder cells

I am in editing mode.
The dark grey is an imageView, that it seems being pushed by the reorder icons, and you can see the UIview in the background (light grey).
I do not like this to happen.
What do you think?
Are you wanting to hide the reorder button and its views? If so, you can override the didTransitionToState method in your custom UITableView like so:
- (void)didTransitionToState:(UITableViewCellStateMask)state
{
//modified from comments here:
//http://www.erasetotheleft.com/post/overriding-the-drag-reorder-control-in-uitableviewcell/
if(state == UITableViewCellStateEditingMask)
{
for (UIControl *control in self.subviews)
{
// Find the Reorder Control
if ([control isMemberOfClass:NSClassFromString(#"UITableViewCellReorderControl")] && [control.subviews count] > 0)
{
// Create Pointer to Reorder Controls Image View
UIImageView *imageView = [control.subviews objectAtIndex:0];
// Set Image Views Hidden Property to NO
imageView.hidden = YES;
}
}
}
}

Access every button in a UIView on the iPhone

What I want to do is ideally loop through all buttons in a UIView (I have a lot, over 40 buttons), and depending on the tag, change the image that the button is displaying. Does anyone know how I can do this?
Thanks!!!!
I would say use the subviews property, as devilaether said, but do an additional check to make sure the subview is a UIButton before you do anything else with it:
for(UIView *view in [rootView subviews]) {
if([view isKindOfClass:[UIButton class]]) {
if([view tag] == 0) {
// First image
} /* ... */
else {
NSLog(#"didn't recognize tag");
}
} else {
NSLog(#"view is not a button");
}
}
You could also make your life easier if you stored an NSArray somewhere with the UIButtons you wanted to iterate over; this would take out the isKindOfClass: check. See the NSObject protocol for more info.
Use the subview property of the UIView containing the buttons. For each UIView element in that NSArray, inspect the tag property. If the tag matches what your logic needs, change the image displayed in that UIView instance - which in this case is one of the buttons.
for(i=0; i<numberOfTags; i++){
UIButton *tempBtn = [yourView viewWithTag:i];
[tempBtn setImage:yourImage];
}