34

为了在我的 ios 应用程序中连接到 facebook,我使用Facebook SDK for iOS中的 FBLoginVIew 。

它显示了一个不错的 FB 登录按钮,但我想使用我自己的图像和文本作为登录按钮。问题是我在任何地方都看不到如何定制它。

我已经设法通过覆盖 FacebookSDKResources.bundle/FBLoginView/images 中的图像来更改登录按钮背景图像,但我找不到更改登录按钮文本和位置的位置,所以它保持“登录”...

解决方案,有人吗?

谢谢

4

17 回答 17

67

答案是浏览 FBLoginView 子视图,找到按钮和标签并自定义它们。

这是代码:

FBLoginView *loginview = 
[[FBLoginView alloc] initWithPermissions:[NSArray arrayWithObject:@"publish_actions"]];


loginview.frame = CGRectMake(4, 95, 271, 37);
for (id obj in loginview.subviews)
        {
            if ([obj isKindOfClass:[UIButton class]])
            {
                UIButton * loginButton =  obj;
                UIImage *loginImage = [UIImage imageNamed:@"YourImg.png"];
                [loginButton setBackgroundImage:loginImage forState:UIControlStateNormal];
                [loginButton setBackgroundImage:nil forState:UIControlStateSelected];
                [loginButton setBackgroundImage:nil forState:UIControlStateHighlighted];
                [loginButton sizeToFit];
            }
            if ([obj isKindOfClass:[UILabel class]])
            {
                UILabel * loginLabel =  obj;
                loginLabel.text = @"Log in to facebook";
                loginLabel.textAlignment = UITextAlignmentCenter;
                loginLabel.frame = CGRectMake(0, 0, 271, 37);
            }
        }

loginview.delegate = self;

[self.view addSubview:loginview];
于 2012-09-05T12:06:36.143 回答
9

我想将 FBLoginview 显示为 UIBarbutton,所以我做了一个简单的方法:

首先,我将 FBLoginView 添加为属性:

@property (nonatomic, strong) FBLoginView* loginView;

然后我在视图之外添加了登录视图:

    self.loginView = [[FBLoginView alloc] init];
    self.loginView.frame = CGRectMake(-500, -500, 0, 0);
    [self.view addSubview:self.loginView];
    self.loginView.delegate = self;

然后,我添加了一个标准系统 UIbarbuttonItem

    UIBarButtonItem* fbButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(fireFbLoginView)];
    [self.navigationItem setRightBarButtonItem:fbButton];

然后我将栏按钮设置为触发 FBLoginView 的点击动作;)

-(void)fireFbLoginView{
for(id object in self.loginView.subviews){
    if([[object class] isSubclassOfClass:[UIButton class]]){
        UIButton* button = (UIButton*)object;
        [button sendActionsForControlEvents:UIControlEventTouchUpInside];
    }
  }
}
于 2014-01-27T16:38:59.150 回答
8

在我写这篇文章的时候,Facebook 已经发布了他们的 iOS SDK 3.0 版。

ozba 的答案有点工作,但在我看来,它不应该被使用。

  • 首先,也是最重要的,一般规则是迭代 SDK 组件的子视图/超级视图是不好的做法,因为层次结构可能会在 SDK 版本之间发生变化,从而导致难以跟踪和修复的错误。
  • 其次,当按钮被点击时,一两秒钟,它又回到了原始文本。

我的解决方案非常简单。在 Facebook 下载的文件夹FacebookSDK中,您有一个名为Samples的文件夹。在那里,您必须查看SessionLoginSample。您可以看到他们有一个普通的Round Rect Button,通过拥有它的 ViewController ,它具有FBLoginViewDelegate,它可以根据 FBSession 状态更改文本。相信我,这真的很简单。

于 2013-09-25T09:56:55.007 回答
6

或者阅读 Facebook 的文档来构建你自己的按钮:

https://developers.facebook.com/docs/ios/login-tutorial/#login-apicalls

像这样:

- (void) buttonSelector
{
[FBSession openActiveSessionWithReadPermissions:@[@"basic_info"]
                                       allowLoginUI:YES
                                  completionHandler:
     ^(FBSession *session, FBSessionState state, NSError *error) {

         if (FBSession.activeSession.state == FBSessionStateOpen) {

             //To get the use
             [[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection,NSDictionary<FBGraphUser> *user, NSError *error) {
                 NSString *token = [[[FBSession activeSession] accessTokenData] accessToken];


             }];

         }
     }];

}
于 2014-04-08T23:56:57.180 回答
3

更改 Facebook 资源包中的文本 en.lproj Localizable.strings ...我想它可以工作

于 2012-09-05T12:22:19.700 回答
3

我正在创建一个自定义 FB 按钮类,以防我需要为其他项目回收它,它仍然是第一个版本,但可以根据记录的状态更改按钮图像并轻松管理其大小。

有些方法是为了以防万一。

请注意,您还可以通过将其类设置为 FBCustomLoginView 及其委托来放置 NIB 文件中的按钮视图,但是您设置的任何大小都将始终重置为 FBLoginView 的默认大小,因此您必须始终在代码中设置特定大小。(我不知道如何从 NSCoder 获取框架的大小以避免这种情况)

代码是原样的,您可以编辑它并对其中的任何错误负责,我会在找到任何错误时编辑这个答案。我希望它对某人有用。

如果您从 NIB 添加它,您只需使用所需的文本和图像对其进行调整,其余的就像 FBLoginView 一样工作:

    _facebookLoginButton.label.text = nil;
    [_facebookLoginButton setLoggedImage:  [UIImage imageNamed: @"ic_link_fb_on.png"] notLoggedImage:  [UIImage imageNamed: @"ic_link_fb_off.png"]];
    [_facebookLoginButton wrapButtonToSizeWidth: IS_IPAD ? 38 : 30 height: IS_IPAD ? 38 : 30 ];

FBCustomLoginView.h

#import <Foundation/Foundation.h>
#import <FacebookSDK/FacebookSDK.h>

@interface FBCustomLoginView : FBLoginView <FBLoginViewDelegate>

/** The button actual button */
@property (nonatomic, strong) UIButton* button;

/** The button label */
@property (nonatomic, strong) UILabel* label;

/** To a single button without label, set the same frame for the login button view and the actual button */
- (void)setWrappedButtonFrame:(CGRect)frame;

/** Wraps button to specified size, maintaining frame origin */
- (void)wrapButtonToSizeWidth: (CGFloat) width height: (CGFloat) height;

/** Sets a default background image for all states */
- (void) setBackgroundImage: (UIImage*) image selectedImage: (UIImage*) selectedImage highlightedImage: (UIImage*) highlightedImage disabledImage: (UIImage*) disabledImage;

/** Sets a default background image */
- (void) setBackgroundImage: (UIImage*) image;

/** Resizes the background image to specified size */
- (void) setBackgroundImageSizeWidth: (CGFloat) width height: (CGFloat) height;

/** Place images to manage and differentiate between logged in and out states */
- (void) setLoggedImage: (UIImage*) loggedImage notLoggedImage: (UIImage*) notLoggedImage;

@end

FBCustomLoginView.m

#import "FBCustomLoginView.h"

@interface FBCustomLoginView() {
    id<FBLoginViewDelegate> _delegate;
    UIImage* _loggedImage;
    UIImage* _notLoggedImage;
}

@end

@implementation FBCustomLoginView

@synthesize button = _button;
@synthesize label = _label;

#pragma mark - View lifecycle, superclass override
- (id)init {
    if (self = [super init]) {
        [self getReferences];
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame {
    if(self = [super initWithFrame: frame]) {
        [self getReferences];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder: aDecoder]) {
        [self getReferences];
    }
    return self;
}


- (void) getReferences {

    for (id obj in self.subviews) {
        if ([obj isKindOfClass:[UIButton class]]) {
            self.button = obj;
        }

        if ([obj isKindOfClass:[UILabel class]]) {
            self.label =  obj;
        }
    }

}

- (void)setDelegate:(id<FBLoginViewDelegate>)delegate {
    _delegate = delegate;
    [super setDelegate: self];
}


#pragma mark - FBLoginViewDelegate

- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView {
    if (_loggedImage) {
        [self setBackgroundImage: _loggedImage];
    }
    [_delegate loginViewShowingLoggedInUser: loginView];
}

- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
                            user:(id<FBGraphUser>)user {
    [_delegate loginViewFetchedUserInfo: loginView user: user];
}

- (void)loginViewShowingLoggedOutUser:(FBLoginView *)loginView {

    if (_notLoggedImage) {
        [self setBackgroundImage: _notLoggedImage];
    }
    [_delegate loginViewShowingLoggedOutUser: loginView];
}

- (void)loginView:(FBLoginView *)loginView handleError:(NSError *)error {
    if ([_delegate respondsToSelector: @selector(loginView:handleError:)]) {
        [_delegate performSelector: @selector(loginView:handleError:) withObject: loginView withObject: error];
    }
}


#pragma mark - Custom methods

/** To a single button without label, set the same frame for the login button view and the actual button */
- (void)setWrappedButtonFrame:(CGRect)frame {
    [super setFrame: frame];

    if (_button) {
        [self setBackgroundImageSizeWidth: frame.size.width height: frame.size.height];
    }

}

/** Wraps button to specified size, maintaining frame origin */
- (void)wrapButtonToSizeWidth: (CGFloat) width height: (CGFloat) height {
    [super setFrame: CGRectMake(self.frame.origin.x, self.frame.origin.y, width, height)];
    if (_button) {
        [self setBackgroundImageSizeWidth: width height: height];
    }
}


- (void) setBackgroundImage: (UIImage*) image selectedImage: (UIImage*) selectedImage highlightedImage: (UIImage*) highlightedImage disabledImage: (UIImage*) disabledImage {

    [_button setBackgroundImage:image forState:UIControlStateNormal];
    [_button setBackgroundImage:selectedImage forState:UIControlStateSelected];
    [_button setBackgroundImage:highlightedImage forState:UIControlStateHighlighted];
    [_button setBackgroundImage:disabledImage forState:UIControlStateDisabled];
}

- (void) setBackgroundImage: (UIImage*) image {
    [self setBackgroundImage: image selectedImage:nil highlightedImage:nil disabledImage:nil];
}

- (void) setBackgroundImageSizeWidth: (CGFloat) width height: (CGFloat) height {
    _button.frame = CGRectMake(0, 0, width, height);
}

- (void) setLoggedImage: (UIImage*) loggedImage notLoggedImage: (UIImage*) notLoggedImage {
    _loggedImage = loggedImage;
    _notLoggedImage = notLoggedImage;

    [self setBackgroundImage: notLoggedImage];
}


@end
于 2013-03-26T02:37:14.087 回答
3

我想我找到了一种更简单的方法来自定义文本,例如 FBSDKLoginButton 的文本,而无需从头开始创建包含所有登录功能的完全自定义按钮。这很好,因为 FBSDKLoginButton 完成了所有工作——您只需更改文本。对不起,我只知道 Swift ......这是代码:

var fbButton = FBSDKLoginButton()
var titleText = NSAttributedString(string: "Your new button title")
fbButton.setAttributedTitle(titleText, forState: UIControlState.Normal)

享受!

于 2015-12-10T03:41:43.777 回答
2

您所有问题的答案,包括按登录后的标签非常简单:就像 OZBA 的答案一样,只需完全删除UILabel(添加[loginLabel removeFromSuperview];:)

这是完整的工作代码:

- (void)setFacebookConnectButton{
    self.loginView.readPermissions = @[@"public_profile", @"email", @"user_friends"];
    [self.loginView setDelegate:self];
    for (id obj in self.loginView.subviews)
    {
        if ([obj isKindOfClass:[UIButton class]])
        {
            UIButton * loginButton =  obj;
            UIImage *loginImage = [UIImage imageNamed:@"fb_connect"];
            [loginButton setBackgroundImage:loginImage forState:UIControlStateNormal];
            [loginButton setBackgroundImage:nil forState:UIControlStateSelected];
            [loginButton setBackgroundImage:nil forState:UIControlStateHighlighted];
            [loginButton setTitle:nil forState:UIControlStateSelected];
            [loginButton setTitle:nil forState:UIControlStateHighlighted];

            [loginButton sizeToFit];
        }
        if ([obj isKindOfClass:[UILabel class]])
        {
            UILabel * loginLabel =  obj;
            loginLabel.text = @"";
            loginLabel.textAlignment = NSTextAlignmentCenter;
            loginLabel.frame = CGRectMake(0, 0, 271, 37);
            [loginLabel removeFromSuperview];
        }
    }
}
于 2014-05-07T18:28:48.560 回答
1

请阅读 Facebook SDK 中的 README 文件。您必须在 info.plist 中添加 Row - FacebookBundleName 并将其命名为您的捆绑包。然后,使用此名称将包添加到您的项目并放入名为“lang.lproj”的文件夹中:例如:en.lproj - it.lproj - fr.lproj - es.lproj.... 进入这个文件夹,你必须添加 Localizable.strings 文件,然后您可以本地化很多短语,例如:

"FBLV:LogOutButton" = "Log Out";
"FBLV:LogInButton" = "Log In";
"FBLV:LoggedInAs" = "Logged in as: %@";
"FBLV:LoggedInUsingFacebook" = "Logged in using Facebook";
"FBLV:LogOutAction" = "Log Out";
"FBLV:CancelAction" = "Cancel";

希望对你有帮助!

于 2014-02-17T17:47:22.680 回答
1

我刚刚找到了按下登录按钮时按钮文本更新的答案。我遇到了同样的问题。

如何尝试将按钮标签的框架设置为 CGRectMake(0,0,0,0)。

我试过了,我认为它有效。

将此代码添加到 ozba 的答案中:

[loginLabel setFrame:CGRectMake(0, 0, 0, 0)];

希望这可以帮助。

于 2014-03-13T12:53:00.893 回答
0

我考虑了这个问题,我个人并不是很喜欢接受的答案......出于各种原因。每个人都可以自由选择任何他喜欢的解决方案,但我决定分享我自己的解决方案。

for (UIButton *view in loginView.subviews) {
    if ([view respondsToSelector:@selector(addTarget:action:forControlEvents:)]) {
        [view setBackgroundImage:nil forState:UIControlStateNormal];
        [view setBackgroundImage:nil forState:UIControlStateHighlighted];
    }
}

我使用respondsToSelector而不是isKindOfClass因为将来该类可能是自定义的。

于 2014-06-23T10:07:59.773 回答
0

将 FB 视图定位在屏幕外,或大小为 0x0。然后,设置按钮的操作以将消息 buttonPressed: 发送到 FB 视图。我认为这是最简单的方法。

于 2014-07-17T18:17:37.400 回答
0

在我的例子中,我在 Photoshop 中创建了一个好看的按钮,然后简单地将它放在 facebook 按钮的顶部。(我知道Apple不建议将视图放在按钮上但是迭代子视图对我来说并不好看)。很难理解为什么像 FB 这样的公司没有提供简单的方法来做到这一点。

UIImageView *fbImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"facebookButton.png"]];
CGRect newFrame = fBButtonFrame;
newFrame.origin.x = 0; newFrame.origin.y = 0;
[fbImageView setFrame:newFrame];
[fbImageView setUserInteractionEnabled:NO];

FBLoginView *loginView = [[FBLoginView alloc] init];
[loginView setFrame:fBButtonFrame];
[loginView addSubview:fbImageView];
[self.view addSubview:loginView];
于 2014-09-13T14:14:52.963 回答
0

如果您参考https://github.com/facebook/facebook-ios-sdk/blob/master/src/UI/FBLoginView.m,第 299 行,您会看到文本是由 FBLoginView 中的实例方法提供的。因此,您可以通过从 FBLoginView 派生您自己的类并提供您自己的 logInText 实现来更改此文本:

@interface CustomFBLoginView : FBLoginView

@end

@implementation CustomFBLoginView

-(NSString*) logInText {
    return @"Some custom text";
}

@end

这有点冒险,因为它确实取决于内部实现细节。

于 2014-10-11T10:43:18.060 回答
0

自最新版本 4.X Facebook SDK 以来,

自定义登录变得更容易,使用FBSDKLoginManager

于 2015-05-30T08:39:11.553 回答
0

根据最新的 Facebook 登录 iOS 版本 2.3。

您可以使用以下代码片段通过任何自定义 UIButton 登录。

- (void)loginWithFacebook:(id) sender {
   FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
   [login logInWithReadPermissions:@[@"public_profile",@"email"] handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
    if (error) {
        // Process error
    } else if (result.isCancelled) {
        // Handle cancellations
    } else {
        // Login Successful here

        // Check for any particular permissions you asked
        if ([result.grantedPermissions containsObject:@"email"]) {
            // Do work
        }
     }
  }];
}

这是链接:https ://developers.facebook.com/docs/facebook-login/ios/v2.3#login-apicalls

于 2015-07-06T10:54:36.817 回答
0

最简单的解决方案

let FB_LoginButton = FBSDKLoginButton()

let imgV = UIImageView(frame: FB_LoginButton.frame)
img.image = UIImage(named: "Your Image Name")

let textV = UILabel(frame: CGRect(x: 0, y: 0, width: FB_LoginButton.frame.size.width, height: 20)) // Set Frames as you need
textV.text = "Your Text"
textV.font = textV.font.fontWithSize(20)

// Swift 3
textV.font = textV.font.withSize(20)

imgV.addSubview(textV)
FB_LoginButton.addSubview(imgV)
于 2017-09-20T07:00:53.080 回答