ios 在 UIToolbar 上创建左箭头按钮(如 UINavigationBar 的“后退”样式)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/227078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:20:45  来源:igfitidea点击:

Creating a left-arrow button (like UINavigationBar's "back" style) on a UIToolbar

iosiphonecocoa-touchuinavigationbaruitoolbar

提问by Marco

I'd love to create a "back" left-arrow-bezel button in a UIToolbar.

我很想在UIToolbar.

As far as I can tell, the only way to get one of these is to leave UINavigationControllerat default settings and it uses one for the left bar item. But there's no way I can find to create one as a UIBarButtonItem, so I can't make one in a standard UIToolbar, even though they're very similar to UINavigationBars.

据我所知,获得其中之一的唯一方法是保留UINavigationController默认设置,并将其用于左侧栏项目。但是我无法找到将一个创建为 a 的方法UIBarButtonItem,因此我无法在标准中创建一个UIToolbar,即使它们与UINavigationBars非常相似。

I could manually create it with button images, but I can't find the source images anywhere. They have alpha-channel edges, so screenshotting and cutting won't get very versatile results.

我可以用按钮图像手动创建它,但我无法在任何地方找到源图像。它们具有 alpha 通道边缘,因此截图和剪切不会获得非常通用的结果。

Any ideas beyond screenshotting for every size and color scheme I intend to use?

除了对我打算使用的每种尺寸和配色方案进行截图之外,还有什么想法吗?

Update:PLEASE STOP dodging the question and suggesting that I shouldn't be asking this and should be using UINavigationBar. My app is Instapaper Pro. It shows only a bottom toolbar (to save space and maximize readable content area), and I wish to put a left-arrow-shaped Back button in the bottom.

更新:请停止回避这个问题并暗示我不应该问这个而应该使用UINavigationBar. 我的应用程序是 Instapaper Pro。它只显示底部工具栏(以节省空间并最大化可读内容区域),我希望在底部放置一个左箭头形状的后退按钮。

Telling me that I shouldn't need to do this is not an answerand certainly doesn't deserve a bounty.

告诉我我不需要这样做不是一个答案,当然也不值得赏金。

采纳答案by PyjamaSam

I used the following psd that I derived from http://www.teehanlax.com/blog/?p=447

我使用了以下来自http://www.teehanlax.com/blog/?p=447 的psd

http://www.chrisandtennille.com/pictures/backbutton.psd

http://www.chrisandtennille.com/pictures/backbutton.psd

I then just created a custom UIView that I use in the customView property of the toolbar item.

然后我刚刚创建了一个自定义 UIView,我在工具栏项的 customView 属性中使用它。

Works well for me.

对我来说效果很好。



Edit:As pointed out by PrairieHippo, maralbjofound that using the following, simple code did the trick (requires custom image in bundle) should be combined with this answer. So here is additional code:

编辑:正如PrairieHippo所指出的maralbjo发现使用以下简单的代码可以解决问题(需要捆绑中的自定义图像)应与此答案结合使用。所以这里是额外的代码:

// Creates a back button instead of default behaviour (displaying title of previous screen)
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back_arrow.png"]
                                                               style:UIBarButtonItemStyleBordered
                                                              target:self
                                                              action:@selector(backAction)];

tipsDetailViewController.navigationItem.leftBarButtonItem = backButton;
[backButton release];

回答by Cameron Lowell Palmer

The Unicode Method

Unicode 方法

I think it is much easier to just use a unicode character to get the job done. You can look through arrows by googling either Unicode Trianglesor Unicode Arrows. Starting with iOS6 Apple changed the character to be an emoji character with a border. To disable the border I add the 0xFE0E Unicode Variation Selector.

我认为仅使用 unicode 字符来完成工作要容易得多。您可以通过谷歌搜索Unicode TrianglesUnicode Arrows来查看箭头。从 iOS6 开始,Apple 将字符更改为带边框的 emoji 字符。为了禁用边框,我添加了 0xFE0E Unicode Variation Selector

NSString *backArrowString = @"\U000025C0\U0000FE0E"; //BLACK LEFT-POINTING TRIANGLE PLUS VARIATION SELECTOR

UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:backArrowString style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.leftButtonItem = backBarButtonItem;

The code block is just for the demo. It would work in any button that accepts an NSString.

代码块仅用于演示。它适用于任何接受 NSString 的按钮。

For a full list of characters search Google for Unicode character and what you want. Here is the entry for Black Left-Pointing Triangle.

要获得完整的字符列表,请在 Google 上搜索 Unicode 字符和您想要的字符。这是Black Left-Pointing Triangle的条目。

Result

结果

The result

结果

回答by AndrewS

WARNING:There are reports that this will not work on iOS 6. This might only work on older versions of the OS. Evidently at least one dev has had their app rejected for using this trick (see the comments). Use at your own risk. Using an image (see answer above) might be a safer solution.

警告:有报告称这不适用于 iOS 6。这可能仅适用于旧版本的操作系统。显然至少有一个开发人员因为使用这个技巧而拒绝了他们的应用程序(见评论)。使用风险自负。使用图像(见上面的答案)可能是一个更安全的解决方案。

This can be done without adding in your own image files using sekr1t button type 101 to get the correct shape. For me the trick was figuring out that I could use initWithCustomViewto create the BarButtonItem. I personally needed this for a dynamic navbar rather than a toolbar, but I tested it with a toolbar and the code is nearly the same:

这可以在不使用 sekr1t 按钮类型 101 添加您自己的图像文件的情况下完成,以获得正确的形状。对我来说,诀窍是弄清楚我可以initWithCustomView用来创建BarButtonItem. 我个人需要这个用于动态导航栏而不是toolbar,但我使用工具栏对其进行了测试,代码几乎相同:

// create button
UIButton* backButton = [UIButton buttonWithType:101]; // left-pointing shape!
[backButton addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:@"Back" forState:UIControlStateNormal];

// create button item -- possible because UIButton subclasses UIView!
UIBarButtonItem* backItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

// add to toolbar, or to a navbar (you should only have one of these!)
[toolbar setItems:[NSArray arrayWithObject:backItem]];
navItem.leftBarButtonItem = backItem;

If you're doing this on a toolbar you'll have to tweak how you set the items, but that depends on the rest of your code and I leave that as an exercise for the reader. :P This sample worked for me (compiled & run).

如果您在工具栏上执行此操作,则必须调整设置项目的方式,但这取决于您的代码的其余部分,我将其作为练习留给读者。:P 这个示例对我有用(编译并运行)。

Blah blah, read the HIG, don't use undocumented features, and all that. There's only six supported button types and this isn't one of them.

废话废话,阅读 HIG,不要使用未记录的功能,等等。只有六种受支持的按钮类型,这不是其中之一。

回答by Alexey

enter image description here

在此处输入图片说明

First of all you have to find an image of the back button. I used a nice app called Extractorthat extracts all the graphics from iPhone. In iOS7I managed to retrieve the image called UINavigationBarBackIndicatorDefaultand it was in black colour, since I needed a red tint I change the colour to red using Gimp.

首先,您必须找到后退按钮的图像。我使用了一个名为Extractor的不错的应用程序,它可以从 iPhone 中提取所有图形。在iOS7 中,我设法检索了调用的图像UINavigationBarBackIndicatorDefault,它是黑色的,因为我需要红色调,所以我使用 Gimp 将颜色更改为红色。

EDIT:

编辑:

As was mentioned by btatein his comment, there is no need to change the color with the image editor. The following code should do the trick:

正如btate在他的评论中提到的,不需要使用图像编辑器更改颜色。以下代码应该可以解决问题:

imageView.tint = [UIColor redColor];
imageView.image = [[UIImage imageNamed:@"UINavigationBarBackIndicatorDefault"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

Then I created a view that contains an imageView with that arrow, a label with the custom text and on top of the view I have a button with an action. Then I added a simple animation (fading and translation).

然后我创建了一个视图,其中包含一个带有该箭头的 imageView,一个带有自定义文本的标签,在视图顶部我有一个带有操作的按钮。然后我添加了一个简单的动画(淡入淡出和平移)。

The following code simulates the behaviour of the back button including animation.

以下代码模拟后退按钮的行为,包括动画。

-(void)viewWillAppear:(BOOL)animated{
        UIImageView *imageView=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UINavigationBarBackIndicatorDefault"]];
        [imageView setTintColor:[UIColor redColor]];
        UILabel *label=[[UILabel alloc] init];
        [label setTextColor:[UIColor redColor]];
        [label setText:@"Blog"];
        [label sizeToFit];

        int space=6;
        label.frame=CGRectMake(imageView.frame.origin.x+imageView.frame.size.width+space, label.frame.origin.y, label.frame.size.width, label.frame.size.height);
        UIView *view=[[UIView alloc] initWithFrame:CGRectMake(0, 0, label.frame.size.width+imageView.frame.size.width+space, imageView.frame.size.height)];

        view.bounds=CGRectMake(view.bounds.origin.x+8, view.bounds.origin.y-1, view.bounds.size.width, view.bounds.size.height);
        [view addSubview:imageView];
        [view addSubview:label];

        UIButton *button=[[UIButton alloc] initWithFrame:view.frame];
        [button addTarget:self action:@selector(handleBack:) forControlEvents:UIControlEventTouchUpInside];
        [view addSubview:button];

        [UIView animateWithDuration:0.33 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
            label.alpha = 0.0;
            CGRect orig=label.frame;
            label.frame=CGRectMake(label.frame.origin.x+25, label.frame.origin.y, label.frame.size.width, label.frame.size.height);
            label.alpha = 1.0;
            label.frame=orig;
        } completion:nil];

        UIBarButtonItem *backButton =[[UIBarButtonItem alloc] initWithCustomView:view];
}

- (void) handleBack:(id)sender{
}

EDIT:

编辑:

Instead of adding the button, in my opinion the better approach is to use a gesture recognizer.

在我看来,最好的方法是使用手势识别器,而不是添加按钮。

UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleBack:)];
[view addGestureRecognizer:tap];
[view setUserInteractionEnabled:YES];

回答by Adam Rosenfield

I'm not sure if this would work, but you could try creating a UINavigationControllerwith the default settings to create the button, find the button in the navigation controller's subview hierarchy, call removeFromSuperviewon it, destroy the navigation controller, and then add the button as a subview of your toolbar. You may also need to retainand the button before calling removeFromSuperview(and then releaseit after adding it as subview of your toolbar) to avoid it being deallocated during the process.

我不确定这是否可行,但您可以尝试UINavigationController使用默认设置创建按钮来创建按钮,在导航控制器的子视图层次结构中找到按钮,调用removeFromSuperview它,销毁导航控制器,然后将按钮添加为工具栏的子视图。您可能还需要retain在调用之前和按钮removeFromSuperview(然后release在将其添加为工具栏的子视图之后),以避免在此过程中释放它。

回答by Bj?rn Egil

To make a UIButton with an arrow pretty close (I'm not a designer ;) to the iOS 7 system back arrow:

要使带有箭头的 UIButton 与 iOS 7 系统后退箭头非常接近(我不是设计师;):

Standard:

标准:

Standard system back arrow

标准系统后退箭头

Apple SD Gothic Neo

Apple SD Gothic Neo

Apple SD Gothic Neo < character

Apple SD Gothic Neo < 字符

In Xcode:

在Xcode中:

  • Focus on the title value field of the button (or any other view/control with text content)
  • Open Edit -> Special Characters
  • Select the Parentheses group and double click the '<' character
  • Change font to: Apple SD Gothic Neo, Regular with desired size (e.g. 20)
  • Change colour as you like
  • 专注于按钮的标题值字段(或任何其他带有文本内容的视图/控件)
  • 打开编辑 -> 特殊字符
  • 选择括号组并双击“<”字符
  • 将字体更改为:Apple SD Gothic Neo,具有所需大小的常规(例如 20)
  • 随心所欲改变颜色

Ref @staticVoidMan's answerto Back-like arrow on iOS 7

参考@staticVoidMan对 iOS 7 上类似后退箭头的回答

回答by machoota

back arrow

后退箭头

If you don't want to bother with image files, the arrow shape can be drawn in a UIView subclass with the following code:

如果您不想打扰图像文件,可以使用以下代码在 UIView 子类中绘制箭头形状:

- (void)drawRect:(CGRect)rect {
    float width = rect.size.width;
    float height = rect.size.height;
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextBeginPath(context);
    CGContextMoveToPoint(context, width * 5.0/6.0, height * 0.0/10.0);
    CGContextAddLineToPoint(context, width * 0.0/6.0, height * 5.0/10.0);
    CGContextAddLineToPoint(context, width * 5.0/6.0, height * 10.0/10.0);
    CGContextAddLineToPoint(context, width * 6.0/6.0, height * 9.0/10.0);
    CGContextAddLineToPoint(context, width * 2.0/6.0, height * 5.0/10.0);
    CGContextAddLineToPoint(context, width * 6.0/6.0, height * 1.0/10.0);
    CGContextClosePath(context);

    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
    CGContextFillPath(context);
}

where the arrow view is proportional to a width of 6.0 and a height of 10.0

其中箭头视图与 6.0 的宽度和 10.0 的高度成比例

回答by quantumpotato

    self.navigationItem.leftBarButtonItem = self.navigationItem.backBarButtonItem;

Works for me. I used this when I had more tabs then could fit on the tab bar, and a view controller pushed from the "More" overrode the leftBarButtonItem in its viewDidLoad.

为我工作。当我有更多选项卡然后可以放在选项卡栏上时,我使用了它,并且从“更多”推送的视图控制器覆盖了其 viewDidLoad 中的 leftBarButtonItem。

回答by Steve

Here's what I ended up doing after searching through all these solutions and others. It uses a stretchable png's extracted from the UIKit stock images. This way you can set the text to whatever you liek

这是我在搜索所有这些解决方案和其他解决方案后最终做的事情。它使用从 UIKit 库存图像中提取的可拉伸 png。通过这种方式,您可以将文本设置为您喜欢的任何内容

// Generate the background images
UIImage *stretchableBackButton = [[UIImage imageNamed:@"UINavigationBarDefaultBack.png"] stretchableImageWithLeftCapWidth:14 topCapHeight:0];
UIImage *stretchableBackButtonPressed = [[UIImage imageNamed:@"UINavigationBarDefaultBackPressed.png"] stretchableImageWithLeftCapWidth:13 topCapHeight:0];
// Setup the UIButton
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setBackgroundImage:stretchableBackButton forState:UIControlStateNormal];
[backButton setBackgroundImage:stretchableBackButtonPressed forState:UIControlStateSelected];
NSString *buttonTitle = NSLocalizedString(@"Back", @"Back");
[backButton setTitle:buttonTitle forState:UIControlStateNormal];
[backButton setTitle:buttonTitle forState:UIControlStateSelected];
backButton.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 2, 1); // Tweak the text position
NSInteger width = ([backButton.titleLabel.text sizeWithFont:backButton.titleLabel.font].width + backButton.titleEdgeInsets.right +backButton.titleEdgeInsets.left);
[backButton setFrame:CGRectMake(0, 0, width, 29)];
backButton.titleLabel.font = [UIFont boldSystemFontOfSize:13.0f];
[backButton addTarget:self action:@selector(yourSelector:) forControlEvents:UIControlEventTouchDown];
// Now add the button as a custom UIBarButtonItem
UIBarButtonItem *backButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:backButton] autorelease];
self.navigationItem.leftBarButtonItem = backButtonItem;

回答by Anton Gaenko

It's easy to do with Interface Builderin Xcode 5.x

Xcode 5.x 中使用Interface Builder很容易

Result

结果

  • use Toolbarand Bar Button Itemfrom Object library

    Components

  • in button's Attributes inspectoredit Imagesection with yourback button image

    Attributes inspector

  • 使用工具栏栏按钮项目对象库

    成分

  • 在按钮的属性检查器中编辑图片与部分后退按钮图像

    属性检查器

Done!

完毕!