2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AndroidAdvent Calendar 2017

Day 14

AndroidのGoogleサインインボタンをカスタムビューで作ってみる

Last updated at Posted at 2017-12-09

image.png

  <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継承

GoogleSignInButton.java
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);
  }
}

image.png

当然、こうなります。寂しい。

キャプションをSign in with Googleにする

GoogleSignInButton.java
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");
  }
}

のように、何も考えずにやると、全部大文字になっちゃう。

image.png

全部大文字にはしない

setSupportAllCaps というメソッドがAppCompatButtonに生えてたのでこいつを使う。

GoogleSignInButton.java
public class GoogleSignInButton extends AppCompatButton {

  // (コンストラクタは省略)

  private void initialize(Context context, @Nullable AttributeSet attrs) {
    setText("Sign in with Google");
    setSupportAllCaps(false);
  }
}

image.png

色指定をする

Googleサインインボタンのスペックをみると

image.png

ということらしいので、XMLでdarkとlightを指定できるようにする。

res/values/google_sign_in_button_styles.xml
<?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>
GoogleSignInButton.java
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);
  }
}

image.png

だんだんそれっぽくなってきた。

Gのアイコンを置く

これが最大に悩みポイント。drawableLeft指定でやってみます。

まずは、SVGの G のアイコンをAndroid用に変換します。

res/drawable/ic_btn_google_sign_in.xml
<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に指定します。

GoogleSignInButton.java
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);
  }
}

image.png

たしかに左側に画像は設定された。でも画像とテキストの間のスペースや、高さが変。

Googleサインインボタンのスペックを改めてみると

image.png

ということで、

  • 高さは40dp
  • 左右は8dpあけるんだけど、 G のアイコンに含まれるパディングを考慮して8dpを設定しないといけない
  • GのアイコンとSign in with Googleの間には24dpあける

あたりを対応する必要がある。

高さを40dpにする

AndroidのButtonは、デフォルトでminWidth, minHeight指定がそこそこ大きめに設定されているので、それを上書きする。

res/values/google_sign_in_button_styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>

  <!-- (色指定・テキスト設定は省略) -->

  <dimen name="google_sign_in_button_height">40dp</dimen>
</resources>
GoogleSignInButton.java
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);
  }
}

image.png

あれ、かわらない。

上下の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はいらなさそうなので消しちゃいましょう。

GoogleSignInButton.java
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);
  }
}

image.png

だいぶそれっぽくなってきた。

G の画像の位置を調整する

Gの左側に8dp空いてるのを切り詰めて、Gとテキストの間に8dp追加すれば良さそうです。

GoogleSignInButton.java
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);
  }
}

image.png

うーむ、どうやら 0dpでは左に行き過ぎちゃうらしい・・・。

paddingLeftを2dpにする

微調整の結果、2dpくらいにするとちょうどになりました。

res/values/google_sign_in_button_styles.xml
<?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>
GoogleSignInButton.java
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);
  }
}

image.png

まとめ

なんとなく練習台としてよさそうだったのでGoogleログインボタンを作ってみただけです。

Googleログインには com.google.android.gms.common.SignInButton を使いましょう。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?