LoginSignup
3
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-09-16

シチュエーション

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. 主観的な価値観です。 

3
2
3

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
3
2