Facebook SDK v4 LoginButton 忽略 XML 自定义
Facebook SDK v4 LoginButton ignores XML customizations
我正在使用的新 Facebook SDK for Android (v4.0) that was released recently caused strange behavior for a customized LoginButton。下面是相同的 XML 在不同 SDK 版本中的渲染效果对比。
问题似乎是 SDK 4.x 中的 FB 图标无法正确拉伸以适应自定义大小的按钮,而在 4.0.1 中 android:layout_height
属性 完全被忽略。
我的问题是如何让按钮像在 SDK 3.x 中一样出现在 SDK 4.x 中? XML 和Java 解决方案是完全可以接受的。
XML 用于 SDK 3.x:
<com.facebook.widget.LoginButton
android:background="@color/com_facebook_blue"
android:id="@+id/login_btn_facebook"
android:layout_width="225dp"
android:layout_height="50dp"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_gravity="center"
android:onClick="onFacebookLoginClick"
/>
它在 SDK 3.x 上的外观(屏幕截图是在 OnePlus One、运行 CM11S 上截取的):
XML 用于 SDK 4.x(按钮的包已重命名 + 我必须稍微更改宽度和字体以匹配 g+ 按钮):
<com.facebook.login.widget.LoginButton
android:background="@color/com_facebook_blue"
android:id="@+id/login_btn_facebook"
android:layout_width="221dp"
android:layout_height="50dp"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_gravity="center"
android:textSize="7pt"
android:onClick="onFacebookLoginClick"
/>
它在 SDK 4.0 上的外观(在 Genymotion Nexus 5 上截取的屏幕截图,运行 未修改的 4.4.4):
它在 SDK 4.0.1 上的外观(相同的 Genymotion Nexus 5):
附加信息
Login button is updated to properly measure its size.
相关帖子:
- Custom Facebook login button image in Facebook Android SDK 3.5
为了支持不同的屏幕尺寸,在登录按钮上方我有一个 ViewPagerIndicator and a ViewPager 被配置为占据所有可用的垂直 space ,它在定位具有定义高度的元素后仍然存在.
我按照以下步骤成功获得了想要的结果:
打开 Facebook SDK 3.x LoginButton code 并查看按钮的样式:
this.setBackgroundResource(R.drawable.com_facebook_button_blue);
this.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.com_facebook_inverse_icon, 0, 0, 0);
this.setCompoundDrawablePadding(getResources().getDimensionPixelSize(
R.dimen.com_facebook_loginview_compound_drawable_padding));
this.setPadding(getResources().getDimensionPixelSize(
R.dimen.com_facebook_loginview_padding_left),
getResources().getDimensionPixelSize(
R.dimen.com_facebook_loginview_padding_top),
getResources().getDimensionPixelSize(
R.dimen.com_facebook_loginview_padding_right),
getResources().getDimensionPixelSize(
R.dimen.com_facebook_loginview_padding_bottom));
基于this answer中的解决方案,我在onPostCreate()
期间更改了按钮参数如下:
float fbIconScale = 1.45F;
Drawable drawable = hostActivity.getResources().getDrawable(
com.facebook.R.drawable.com_facebook_button_icon);
drawable.setBounds(0, 0, (int)(drawable.getIntrinsicWidth()*fbIconScale),
(int)(drawable.getIntrinsicHeight()*fbIconScale));
authButton.setCompoundDrawables(drawable, null, null, null);
authButton.setCompoundDrawablePadding(hostActivity.getResources().
getDimensionPixelSize(R.dimen.fb_margin_override_textpadding));
authButton.setPadding(
hostActivity.getResources().getDimensionPixelSize(
R.dimen.fb_margin_override_lr),
hostActivity.getResources().getDimensionPixelSize(
R.dimen.fb_margin_override_top),
hostActivity.getResources().getDimensionPixelSize(
R.dimen.fb_margin_override_lr),
hostActivity.getResources().getDimensionPixelSize(
R.dimen.fb_margin_override_bottom));
我的自定义维度如下:
<dimen name="fb_margin_override_top">13dp</dimen>
<dimen name="fb_margin_override_bottom">13dp</dimen>
<!--The next value changes the margin between the FB icon and the left border:-->
<dimen name="fb_margin_override_lr">10dp</dimen>
<!--The next value changes the margin between the FB icon and the login text:-->
<dimen name="fb_margin_override_textpadding">17dp</dimen>
这会产生所需的布局:
我遇到了同样的问题,我通过在 java 代码中设置 padding 和 drawables 解决了这个问题:
authButton.setPadding(0, myTopDp, 0, myBottomDp);
authButton.setCompoundDrawablePadding(hostActivity.getResources().getDimensionPixelSize(R.dimen.fb_margin_override_textpadding));
authButton.setCompoundDrawablesWithIntrinsicBounds(myFbResource, 0, 0, 0);
或者如果您将图像用作可绘制对象
authButton.setCompoundDrawablesWithIntrinsicBounds(myFbDrawable, null, null, null);
我认为不需要 OnPostCreate 方法。
LoginButton
的高度与他的paddings和文字大小有关:
//LoginButton.java
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = (getCompoundPaddingTop() +
(int)Math.ceil(Math.abs(fontMetrics.top) + Math.abs(fontMetrics.bottom)) +
getCompoundPaddingBottom());
//...
}
因此,如果您想通过 xml 文件更改其高度,请使用 android:padding*
和 android:textSize
属性或为其创建样式:
<style name="FacebookLoginButtonStyle">
<item name="android:textSize">16sp</item>
<item name="android:paddingTop">10sp</item>
<item name="android:paddingBottom">10sp</item>
</style>
各位,你只需要设置 paddingTop 和 paddingBottom 值即可。
android:paddingTop="15dp"
android:paddingBottom="15dp"
因为想自定义登录文字gravity
启动,遇到setCompoundDrawablePadding
方法的问题。最后我通过使用自定义布局解决了它。我认为这是自定义 Facebook 登录按钮的更简单的方法。
这是最终结果:
布局xml
:
<LinearLayout
android:id="@+id/fb_login_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:background="@drawable/com_facebook_button_background"
android:orientation="horizontal">
<ImageView
android:layout_width="38dp"
android:layout_height="38dp"
android:layout_gravity="center_vertical"
android:layout_marginBottom="1dp"
android:layout_marginLeft="1dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:padding="8dp"
android:src="@drawable/com_facebook_button_icon" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:padding="8dp"
android:text="Log in with Facebook"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
Java 处理自定义 Facebook 登录按钮点击的代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
findViewById(R.id.fb_login_btn).setOnClickListener(this);
boolean login = AccessToken.getCurrentAccessToken() != null;
updateFacebookLogInButton(login);
new AccessTokenTracker() {
@Override
protected void onCurrentAccessTokenChanged(
AccessToken oldAccessToken,
AccessToken currentAccessToken) {
if (currentAccessToken == null) {
updateFacebookLogInButton(false);
}
}
};
FacebookCallback<LoginResult> facebookCallback = new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
updateFacebookLogInButton(true);
handleLoginResult(loginResult.getAccessToken());
}
@Override
public void onCancel() {
}
@Override
public void onError(FacebookException error) {
error.printStackTrace();
}
};
callbackManager = CallbackManager.Factory.create();
loginManager = LoginManager.getInstance();
loginManager.registerCallback(callbackManager, facebookCallback);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.fb_login_btn:
if (AccessToken.getCurrentAccessToken() == null) {
loginManager.logInWithReadPermissions(this, Arrays.asList("public_profile", "email"));
} else {
String logout = getResources().getString(
com.facebook.R.string.com_facebook_loginview_log_out_action);
String cancel = getResources().getString(
com.facebook.R.string.com_facebook_loginview_cancel_action);
String message;
Profile profile = Profile.getCurrentProfile();
if (profile != null && profile.getName() != null) {
message = String.format(
getResources().getString(
com.facebook.R.string.com_facebook_loginview_logged_in_as),
profile.getName());
} else {
message = getResources().getString(
com.facebook.R.string.com_facebook_loginview_logged_in_using_facebook);
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message)
.setCancelable(true)
.setPositiveButton(logout, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
loginManager.logOut();
}
})
.setNegativeButton(cancel, null);
builder.create().show();
}
break;
default:
break;
}
}
private Bundle getRequestParameters() {
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,email,gender");
return parameters;
}
private void updateFacebookLogInButton(boolean login) {
TextView loginTextView = (TextView) findViewById(R.id.fb_login_tv);
if (login) {
loginTextView.setText("Log out");
} else {
loginTextView.setText("Log in with Facebook");
}
}
private void handleRequestResult(JSONObject object) {
// handle GraphRequest here
}
只需将按钮放入 RelativeLayout 中即可。我的高度是 60dp
<RelativeLayout
android:id="@+id/rlGoogle"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginTop="30dp"
app:layout_constraintTop_toBottomOf="@+id/btnSingInWithFace">
<com.google.android.gms.common.SignInButton
android:id="@+id/btnSingInWithGoogle"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
我正在使用的新 Facebook SDK for Android (v4.0) that was released recently caused strange behavior for a customized LoginButton。下面是相同的 XML 在不同 SDK 版本中的渲染效果对比。
问题似乎是 SDK 4.x 中的 FB 图标无法正确拉伸以适应自定义大小的按钮,而在 4.0.1 中 android:layout_height
属性 完全被忽略。
我的问题是如何让按钮像在 SDK 3.x 中一样出现在 SDK 4.x 中? XML 和Java 解决方案是完全可以接受的。
XML 用于 SDK 3.x:
<com.facebook.widget.LoginButton
android:background="@color/com_facebook_blue"
android:id="@+id/login_btn_facebook"
android:layout_width="225dp"
android:layout_height="50dp"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_gravity="center"
android:onClick="onFacebookLoginClick"
/>
它在 SDK 3.x 上的外观(屏幕截图是在 OnePlus One、运行 CM11S 上截取的):
XML 用于 SDK 4.x(按钮的包已重命名 + 我必须稍微更改宽度和字体以匹配 g+ 按钮):
<com.facebook.login.widget.LoginButton
android:background="@color/com_facebook_blue"
android:id="@+id/login_btn_facebook"
android:layout_width="221dp"
android:layout_height="50dp"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_gravity="center"
android:textSize="7pt"
android:onClick="onFacebookLoginClick"
/>
它在 SDK 4.0 上的外观(在 Genymotion Nexus 5 上截取的屏幕截图,运行 未修改的 4.4.4):
它在 SDK 4.0.1 上的外观(相同的 Genymotion Nexus 5):
附加信息
Login button is updated to properly measure its size.
相关帖子:
- Custom Facebook login button image in Facebook Android SDK 3.5
为了支持不同的屏幕尺寸,在登录按钮上方我有一个 ViewPagerIndicator and a ViewPager 被配置为占据所有可用的垂直 space ,它在定位具有定义高度的元素后仍然存在.
我按照以下步骤成功获得了想要的结果:
打开 Facebook SDK 3.x LoginButton code 并查看按钮的样式:
this.setBackgroundResource(R.drawable.com_facebook_button_blue); this.setCompoundDrawablesWithIntrinsicBounds( R.drawable.com_facebook_inverse_icon, 0, 0, 0); this.setCompoundDrawablePadding(getResources().getDimensionPixelSize( R.dimen.com_facebook_loginview_compound_drawable_padding)); this.setPadding(getResources().getDimensionPixelSize( R.dimen.com_facebook_loginview_padding_left), getResources().getDimensionPixelSize( R.dimen.com_facebook_loginview_padding_top), getResources().getDimensionPixelSize( R.dimen.com_facebook_loginview_padding_right), getResources().getDimensionPixelSize( R.dimen.com_facebook_loginview_padding_bottom));
基于this answer中的解决方案,我在
onPostCreate()
期间更改了按钮参数如下:float fbIconScale = 1.45F; Drawable drawable = hostActivity.getResources().getDrawable( com.facebook.R.drawable.com_facebook_button_icon); drawable.setBounds(0, 0, (int)(drawable.getIntrinsicWidth()*fbIconScale), (int)(drawable.getIntrinsicHeight()*fbIconScale)); authButton.setCompoundDrawables(drawable, null, null, null); authButton.setCompoundDrawablePadding(hostActivity.getResources(). getDimensionPixelSize(R.dimen.fb_margin_override_textpadding)); authButton.setPadding( hostActivity.getResources().getDimensionPixelSize( R.dimen.fb_margin_override_lr), hostActivity.getResources().getDimensionPixelSize( R.dimen.fb_margin_override_top), hostActivity.getResources().getDimensionPixelSize( R.dimen.fb_margin_override_lr), hostActivity.getResources().getDimensionPixelSize( R.dimen.fb_margin_override_bottom));
我的自定义维度如下:
<dimen name="fb_margin_override_top">13dp</dimen> <dimen name="fb_margin_override_bottom">13dp</dimen> <!--The next value changes the margin between the FB icon and the left border:--> <dimen name="fb_margin_override_lr">10dp</dimen> <!--The next value changes the margin between the FB icon and the login text:--> <dimen name="fb_margin_override_textpadding">17dp</dimen>
这会产生所需的布局:
我遇到了同样的问题,我通过在 java 代码中设置 padding 和 drawables 解决了这个问题:
authButton.setPadding(0, myTopDp, 0, myBottomDp);
authButton.setCompoundDrawablePadding(hostActivity.getResources().getDimensionPixelSize(R.dimen.fb_margin_override_textpadding));
authButton.setCompoundDrawablesWithIntrinsicBounds(myFbResource, 0, 0, 0);
或者如果您将图像用作可绘制对象
authButton.setCompoundDrawablesWithIntrinsicBounds(myFbDrawable, null, null, null);
我认为不需要 OnPostCreate 方法。
LoginButton
的高度与他的paddings和文字大小有关:
//LoginButton.java
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = (getCompoundPaddingTop() +
(int)Math.ceil(Math.abs(fontMetrics.top) + Math.abs(fontMetrics.bottom)) +
getCompoundPaddingBottom());
//...
}
因此,如果您想通过 xml 文件更改其高度,请使用 android:padding*
和 android:textSize
属性或为其创建样式:
<style name="FacebookLoginButtonStyle">
<item name="android:textSize">16sp</item>
<item name="android:paddingTop">10sp</item>
<item name="android:paddingBottom">10sp</item>
</style>
各位,你只需要设置 paddingTop 和 paddingBottom 值即可。
android:paddingTop="15dp"
android:paddingBottom="15dp"
因为想自定义登录文字gravity
启动,遇到setCompoundDrawablePadding
方法的问题。最后我通过使用自定义布局解决了它。我认为这是自定义 Facebook 登录按钮的更简单的方法。
这是最终结果:
布局xml
:
<LinearLayout
android:id="@+id/fb_login_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:background="@drawable/com_facebook_button_background"
android:orientation="horizontal">
<ImageView
android:layout_width="38dp"
android:layout_height="38dp"
android:layout_gravity="center_vertical"
android:layout_marginBottom="1dp"
android:layout_marginLeft="1dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:padding="8dp"
android:src="@drawable/com_facebook_button_icon" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:padding="8dp"
android:text="Log in with Facebook"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
Java 处理自定义 Facebook 登录按钮点击的代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
findViewById(R.id.fb_login_btn).setOnClickListener(this);
boolean login = AccessToken.getCurrentAccessToken() != null;
updateFacebookLogInButton(login);
new AccessTokenTracker() {
@Override
protected void onCurrentAccessTokenChanged(
AccessToken oldAccessToken,
AccessToken currentAccessToken) {
if (currentAccessToken == null) {
updateFacebookLogInButton(false);
}
}
};
FacebookCallback<LoginResult> facebookCallback = new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
updateFacebookLogInButton(true);
handleLoginResult(loginResult.getAccessToken());
}
@Override
public void onCancel() {
}
@Override
public void onError(FacebookException error) {
error.printStackTrace();
}
};
callbackManager = CallbackManager.Factory.create();
loginManager = LoginManager.getInstance();
loginManager.registerCallback(callbackManager, facebookCallback);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.fb_login_btn:
if (AccessToken.getCurrentAccessToken() == null) {
loginManager.logInWithReadPermissions(this, Arrays.asList("public_profile", "email"));
} else {
String logout = getResources().getString(
com.facebook.R.string.com_facebook_loginview_log_out_action);
String cancel = getResources().getString(
com.facebook.R.string.com_facebook_loginview_cancel_action);
String message;
Profile profile = Profile.getCurrentProfile();
if (profile != null && profile.getName() != null) {
message = String.format(
getResources().getString(
com.facebook.R.string.com_facebook_loginview_logged_in_as),
profile.getName());
} else {
message = getResources().getString(
com.facebook.R.string.com_facebook_loginview_logged_in_using_facebook);
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message)
.setCancelable(true)
.setPositiveButton(logout, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
loginManager.logOut();
}
})
.setNegativeButton(cancel, null);
builder.create().show();
}
break;
default:
break;
}
}
private Bundle getRequestParameters() {
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,email,gender");
return parameters;
}
private void updateFacebookLogInButton(boolean login) {
TextView loginTextView = (TextView) findViewById(R.id.fb_login_tv);
if (login) {
loginTextView.setText("Log out");
} else {
loginTextView.setText("Log in with Facebook");
}
}
private void handleRequestResult(JSONObject object) {
// handle GraphRequest here
}
只需将按钮放入 RelativeLayout 中即可。我的高度是 60dp
<RelativeLayout
android:id="@+id/rlGoogle"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginTop="30dp"
app:layout_constraintTop_toBottomOf="@+id/btnSingInWithFace">
<com.google.android.gms.common.SignInButton
android:id="@+id/btnSingInWithGoogle"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>