Facebook SDK v4 LoginButton忽略XML自定义
最近发布的新版Facebook SDK for Android(v4.0)导致了我正在使用的自定义LoginButton的奇怪行为。 以下是如何在不同的SDK版本中呈现相同的XML的比较。
问题似乎是SDK 4.x中的FB图标不能正确拉伸以适应自定义大小的button,并且在4.0.1处, android:layout_height
属性将被完全忽略 。
我的问题是如何使SDK 4.x中的button像在SDK 3.x中一样? XML和Java解决scheme都是完全可以接受的。
适用于SDK 3.x的XML:
<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(运行CM11S的OnePlus One上的截图)的外观如何:
用于SDK 4.x的XML(button的包已重命名+我不得不改变宽度和字体以匹配g +button):
<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(Same Genymotion Nexus 5)的外观如何:
附加信息
- 摘自4.0 – > 4.0.1 SDK更改日志 :
loginbutton已更新,以正确测量其大小。
-
相关文章:
- Facebook Android SDK 3.5中的自定义Facebookloginbutton图像
-
为了支持不同的屏幕尺寸,在loginbutton的上方,我有一个ViewPagerIndicator和一个ViewPager ,它被configuration为在定位具有定义高度的元素之后占用所有可用的垂直空间。
我设法得到所需的结果,按照以下步骤:
-
打开Facebook SDK 3.x LoginButton代码 ,看看button的样式是如何设置的:
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));
-
基于这个答案中的解决scheme,我在
onPostCreate()
期间改变了button参数,如下所示: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>
这导致所需的布局:
LoginButton
高度与他的填充和文本大小有关:
//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
属性或为其创build样式:
<style name="FacebookLoginButtonStyle"> <item name="android:textSize">16sp</item> <item name="android:paddingTop">10sp</item> <item name="android:paddingBottom">10sp</item> </style>
我遇到了同样的问题,我通过在java代码中设置填充和可绘制来解决这个问题:
authButton.setPadding(0, myTopDp, 0, myBottomDp); authButton.setCompoundDrawablePadding(hostActivity.getResources().getDimensionPixelSize(R.dimen.fb_margin_override_textpadding)); authButton.setCompoundDrawablesWithIntrinsicBounds(myFbResource, 0, 0, 0);
或者如果您使用您的图像作为drawable
authButton.setCompoundDrawablesWithIntrinsicBounds(myFbDrawable, null, null, null);
我相信OnPostCreate方法不是必需的。
因为我想自定义login文本gravity
启动,我遇到了setCompoundDrawablePadding
方法的问题。 最后,我通过使用自定义布局来解决它。 我认为这是一个更简单的方法来定制Facebook的loginbutton。
最终结果如下:
布局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>
处理自定义Facebookloginbutton的Java代码点击:
@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 }
人们,你只需要设置paddingTop和paddingBottom的值。
android:paddingTop="15dp" android:paddingBottom="15dp"