<io.github.yusukeiwaki.android.widget.GoogleSignInButton
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<io.github.yusukeiwaki.android.widget.GoogleSignInButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:color_style="dark"/>
<io.github.yusukeiwaki.android.widget.GoogleSignInButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:color_style="light"/>
<io.github.yusukeiwaki.android.widget.GoogleSignInButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:color_style="dark"/>
カスタムビューの練習としていいネタだったので作ってみただけです。
※ 多くの場合、 com.google.android.gms.common.SignInButton
を使えば事足りるので、おそらく実用性はありませんw 単なる読み物としてお楽しみくださいませw
とりあえずAppCompatButton継承
public class GoogleSignInButton extends AppCompatButton {
public GoogleSignInButton(Context context) {
super(context);
}
public GoogleSignInButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GoogleSignInButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
当然、こうなります。寂しい。
キャプションをSign in with Googleにする
public class GoogleSignInButton extends AppCompatButton {
public GoogleSignInButton(Context context) {
super(context);
initialize(context, null);
}
public GoogleSignInButton(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs);
}
public GoogleSignInButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context, attrs);
}
private void initialize(Context context, @Nullable AttributeSet attrs) {
setText("Sign in with Google");
}
}
のように、何も考えずにやると、全部大文字になっちゃう。
全部大文字にはしない
setSupportAllCaps
というメソッドがAppCompatButtonに生えてたのでこいつを使う。
public class GoogleSignInButton extends AppCompatButton {
// (コンストラクタは省略)
private void initialize(Context context, @Nullable AttributeSet attrs) {
setText("Sign in with Google");
setSupportAllCaps(false);
}
}
色指定をする
ということらしいので、XMLでdarkとlightを指定できるようにする。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="GoogleSignInButton">
<attr name="google_sign_in_button_color_style" format="enum">
<enum name="light" value="0" />
<enum name="dark" value="1" />
</attr>
</declare-styleable>
<color name="google_sign_in_light_button_color">#FFFFFF</color>
<color name="google_sign_in_light_button_text_color">#88000000</color>
<color name="google_sign_in_dark_button_color">#4285F4</color>
<color name="google_sign_in_dark_button_text_color">#FFFFFF</color>
</resources>
public class GoogleSignInButton extends AppCompatButton {
private static final int COLOR_STYLE_LIGHT = 0;
private static final int COLOR_STYLE_DARK = 1;
private int colorStyle;
// (コンストラクタは省略)
private void initialize(Context context, @Nullable AttributeSet attrs) {
colorStyle = COLOR_STYLE_LIGHT;
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GoogleSignInButton, 0,0);
colorStyle = a.getInt(R.styleable.GoogleSignInButton_google_sign_in_button_color_style, colorStyle);
a.recycle();
}
if (colorStyle == COLOR_STYLE_DARK) {
setSupportBackgroundTintList(ContextCompat.getColorStateList(context, R.color.google_sign_in_dark_button_color));
setTextColor(ContextCompat.getColor(context, R.color.google_sign_in_dark_button_text_color));
} else {
setSupportBackgroundTintList(ContextCompat.getColorStateList(context, R.color.google_sign_in_light_button_color));
setTextColor(ContextCompat.getColor(context, R.color.google_sign_in_light_button_text_color));
}
setText("Sign in with Google");
setSupportAllCaps(false);
}
}
だんだんそれっぽくなってきた。
Gのアイコンを置く
これが最大に悩みポイント。drawableLeft指定でやってみます。
まずは、SVGの G のアイコンをAndroid用に変換します。
<vector android:height="40dp" android:viewportHeight="46.0"
android:viewportWidth="46.0" android:width="40dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF"
android:pathData="M5,3L41,3A2,2 0,0 1,43 5L43,41A2,2 0,0 1,41 43L5,43A2,2 0,0 1,3 41L3,5A2,2 0,0 1,5 3z"
android:strokeColor="#00000000" android:strokeWidth="1"/>
<path android:fillColor="#4285F4"
android:pathData="M31.64,23.2C31.64,22.57 31.58,21.95 31.48,21.36L23,21.36L23,24.85L27.84,24.85C27.64,25.97 27,26.92 26.05,27.56L26.05,29.82L28.96,29.82C30.66,28.25 31.64,25.95 31.64,23.2L31.64,23.2Z"
android:strokeColor="#00000000" android:strokeWidth="1"/>
<path android:fillColor="#34A853"
android:pathData="M23,32C25.43,32 27.47,31.19 28.96,29.82L26.05,27.56C25.24,28.1 24.21,28.42 23,28.42C20.66,28.42 18.67,26.84 17.96,24.71L14.96,24.71L14.96,27.04C16.44,29.98 19.48,32 23,32L23,32Z"
android:strokeColor="#00000000" android:strokeWidth="1"/>
<path android:fillColor="#FBBC05"
android:pathData="M17.96,24.71C17.78,24.17 17.68,23.59 17.68,23C17.68,22.41 17.78,21.83 17.96,21.29L17.96,18.96L14.96,18.96C14.35,20.17 14,21.55 14,23C14,24.45 14.35,25.83 14.96,27.04L17.96,24.71L17.96,24.71Z"
android:strokeColor="#00000000" android:strokeWidth="1"/>
<path android:fillColor="#EA4335"
android:pathData="M23,17.58C24.32,17.58 25.51,18.03 26.44,18.93L29.02,16.34C27.46,14.89 25.43,14 23,14C19.48,14 16.44,16.02 14.96,18.96L17.96,21.29C18.67,19.16 20.66,17.58 23,17.58L23,17.58Z"
android:strokeColor="#00000000" android:strokeWidth="1"/>
</vector>
それを、 setCompoundDrawablesWithIntrinsicBounds
を使ってdrawableLeftに指定します。
public class GoogleSignInButton extends AppCompatButton {
private static final int COLOR_STYLE_LIGHT = 0;
private static final int COLOR_STYLE_DARK = 1;
private int colorStyle;
// (コンストラクタは省略)
private void initialize(Context context, @Nullable AttributeSet attrs) {
// (色指定・テキスト設定は省略)
Drawable leftDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_btn_google_light_filled);
setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);
}
}
たしかに左側に画像は設定された。でも画像とテキストの間のスペースや、高さが変。
Googleサインインボタンのスペックを改めてみると
ということで、
- 高さは40dp
- 左右は8dpあけるんだけど、 G のアイコンに含まれるパディングを考慮して8dpを設定しないといけない
- GのアイコンとSign in with Googleの間には24dpあける
あたりを対応する必要がある。
高さを40dpにする
AndroidのButtonは、デフォルトでminWidth, minHeight指定がそこそこ大きめに設定されているので、それを上書きする。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- (色指定・テキスト設定は省略) -->
<dimen name="google_sign_in_button_height">40dp</dimen>
</resources>
public class GoogleSignInButton extends AppCompatButton {
private static final int COLOR_STYLE_LIGHT = 0;
private static final int COLOR_STYLE_DARK = 1;
private int colorStyle;
// (コンストラクタは省略)
private void initialize(Context context, @Nullable AttributeSet attrs) {
// (色指定・テキスト設定は省略)
Drawable leftDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_btn_google_light_filled);
setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);
int height = getResources().getDimensionPixelSize(R.dimen.google_sign_in_button_height);
setMinimumHeight(height);
}
}
あれ、かわらない。
上下のpaddingは0にする
Log.d("GoogleSIgnInButton",
String.format("padding: left=%d top=%d right=%d bottom=%d",
getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom()));
みたいなログを仕込んでみるとわかるように、Android標準のボタンには
12-10 00:58:12.206 D/GoogleSIgnInButton( 8544): padding: left=24 top=20 right=24 bottom=20
上下左右に微妙なpaddingが指定されています。
が、少なくとも上下のpaddingはいらなさそうなので消しちゃいましょう。
public class GoogleSignInButton extends AppCompatButton {
private static final int COLOR_STYLE_LIGHT = 0;
private static final int COLOR_STYLE_DARK = 1;
private int colorStyle;
// (コンストラクタは省略)
private void initialize(Context context, @Nullable AttributeSet attrs) {
// (色指定・テキスト設定は省略)
Drawable leftDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_btn_google_light_filled);
setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);
int height = getResources().getDimensionPixelSize(R.dimen.google_sign_in_button_height);
setMinimumHeight(height);
setPadding(getPaddingLeft(), 0, getPaddingRight(), 0);
}
}
だいぶそれっぽくなってきた。
G の画像の位置を調整する
Gの左側に8dp空いてるのを切り詰めて、Gとテキストの間に8dp追加すれば良さそうです。
public class GoogleSignInButton extends AppCompatButton {
private static final int COLOR_STYLE_LIGHT = 0;
private static final int COLOR_STYLE_DARK = 1;
private int colorStyle;
// (コンストラクタは省略)
private void initialize(Context context, @Nullable AttributeSet attrs) {
// (色指定・テキスト設定は省略)
Drawable leftDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_btn_google_light_filled);
setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);
int height = getResources().getDimensionPixelSize(R.dimen.google_sign_in_button_height);
setMinimumHeight(height);
int originalPaddingLeft = getPaddingLeft();
setPadding(0, 0, getPaddingRight(), 0);
setCompoundDrawablePadding(originalPaddingLeft);
}
}
うーむ、どうやら 0dpでは左に行き過ぎちゃうらしい・・・。
paddingLeftを2dpにする
微調整の結果、2dpくらいにするとちょうどになりました。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- (色指定・テキスト設定は省略) -->
<dimen name="google_sign_in_button_height">40dp</dimen>
<dimen name="google_sign_in_button_padding_left">2dp</dimen>
</resources>
public class GoogleSignInButton extends AppCompatButton {
private static final int COLOR_STYLE_LIGHT = 0;
private static final int COLOR_STYLE_DARK = 1;
private int colorStyle;
// (コンストラクタは省略)
private void initialize(Context context, @Nullable AttributeSet attrs) {
// (色指定・テキスト設定は省略)
Drawable leftDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_btn_google_light_filled);
setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);
int height = getResources().getDimensionPixelSize(R.dimen.google_sign_in_button_height);
setMinimumHeight(height);
int paddingLeft = getResources().getDimensionPixelSize(R.dimen.google_sign_in_button_padding_left);
int originalPaddingLeft = getPaddingLeft();
setPadding(paddingLeft, 0, getPaddingRight(), 0);
setCompoundDrawablePadding(originalPaddingLeft);
}
}
まとめ
なんとなく練習台としてよさそうだったのでGoogleログインボタンを作ってみただけです。
Googleログインには com.google.android.gms.common.SignInButton
を使いましょう。