Help us understand the problem. What is going on with this article?

Android で TextView を継承しているウィジェットの minWidth を表示した String の幅にする黒魔術

More than 1 year has passed since last update.

シチュエーション

InstagramTwitter などのサービスに見られる「フォロー」ボタンを実装するとします。
未フォロー状態の文言を「フォローする」、フォローしている状態の文言を「フォロー中」とした場合、ボタンの表記は 6 文字と 5 文字のパターンが存在することになります。

問題点

ボタンの横幅を wrap_content にすると、フォロー状態が切り替わる度にボタンのサイズが変化するという少しダサい挙動になってしまいます1

フォローする フォロー中
Screenshot_1537127857.png Screenshot_1537129653.png

解決策

予め TextView.setHint() で文字列「フォローする」を設定しておくことで全角 6 文字分の幅を最低限確保します。

サンプル

strings.xml
<resources>
    <string name="follow">フォローする</string>
    <string name="following">フォロー中</string>
</resources>
FollowButton.kt
import android.content.Context
import android.content.res.ColorStateList
import android.support.design.button.MaterialButton
import android.support.v4.content.ContextCompat
import android.util.AttributeSet

/**
 * 「フォロー」ボタン
 */
class FollowButton(context: Context?, attrs: AttributeSet?) : MaterialButton(context, attrs) {

    init {
        setHint(R.string.follow)
        switchFollow()
        setOnClickListener { toggle() }
    }

    private fun switchFollow() = context?.let { context ->
        setText(R.string.follow)
        setTextColor(ContextCompat.getColor(context, android.R.color.white))
        backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(context, android.R.color.holo_blue_light))
    }

    private fun switchFollowing() = context?.let { context ->
        setText(R.string.following)
        setTextColor(ContextCompat.getColor(context, android.R.color.black))
        backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(context, android.R.color.white))
    }

    private fun toggle() = context?.let { if (text == it.getString(R.string.following)) switchFollow() else switchFollowing() }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <tokyo.sample.FollowButton
            android:id="@+id/follow_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:cornerRadius="16dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    </android.support.constraint.ConstraintLayout>
</layout>
MainActivity.kt
import android.databinding.DataBindingUtil
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import tokyo.sample.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
    }
}

結果

MaterialButton の幅を常時テキストが「フォローする」である場合のサイズに固定することができました。

フォローする フォロー中
Screenshot_1537127857.png Screenshot_1537127859.png

  1. 主観的な価値観です。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away