如何自定义FBLoginVIew?

时间:2012-09-05 11:54:07

标签: objective-c ios facebook facebook-login facebook-ios-sdk

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

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

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

解决方案,任何人?

谢谢

17 个答案:

答案 0 :(得分: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];

答案 1 :(得分:9)

我想成为一个UIBarbutton的FBLoginview节目,所以我做了一个简单的方法:

首先我将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];
    }
  }
}

答案 2 :(得分:8)

当我写这篇文章时,Facebook已经发布了适用于iOS的SDK 3.0版。

ozba的回答是有效的,但从我看来,不应该使用。

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

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

答案 3 :(得分: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];


             }];

         }
     }];

}

答案 4 :(得分:3)

更改Facebook资源包中的文本en.lproj Localizable.strings ...我认为它有效

答案 5 :(得分:3)

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

有些方法适用于实际情况。

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

代码是AS-IS,你可以编辑它并对其中的任何错误负责,我会编辑这个答案,因为我发现任何。我希望它对某人有用。

如果您从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

答案 6 :(得分:3)

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

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

享受!

答案 7 :(得分: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];
        }
    }
}

答案 8 :(得分:1)

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

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

我试过了,我觉得它很有用。

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

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

希望这有帮助。

答案 9 :(得分: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";

希望它可以帮到你!

答案 10 :(得分: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,因为该类可能会在将来自定义。

答案 11 :(得分:0)

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

答案 12 :(得分: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];

答案 13 :(得分: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

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

答案 14 :(得分:0)

自最新版本4.X Facebook SDK,

自定义登录变得更加轻松,使用FBSDKLoginManager

答案 15 :(得分:0)

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

您可以使用以下代码段通过任何自定义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

答案 16 :(得分: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)
相关问题