Androidで「もっと読む」ボタン付TextViewを作ってみる
Androidで「もっと読む」ボタン付のTextViewを作ってみました。具体的には、「長文のテキストを省略して途中まで表示し、かつ、後ろ部分に透明なグラデーションをかけて続きがあることを期待させ、下にあるボタンを押すことで続きが表示されるTextView」です。
結局どんなものなのか
こういうありがちな、長文を省略して、かつ後ろに透明なグラデーションかけて「もっと読む」へ誘導するUIをAndroidで作ってみた#Android pic.twitter.com/LBvhG2S2pW
— shyne (@5hy_n3) 2018年8月1日
動画で見るとこんな感じです。
最初は以下のような見た目です。テキストが表示され、下の方の行は徐々に透過されています。
「READ_MORE」ボタンを押すと以下のようにテキストが展開され続きが読めるようになります。
では作っていきましょう。
作り方
Layout
まずはこんな感じのレイアウトを作ります。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:layout_editor_absoluteY="81dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="Hello World!"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:id="@+id/textView"
/>
<Button
android:text="read_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</android.support.constraint.ConstraintLayout>
なんてことはない普通のViewです。テキストを中央上に配置し、その下にボタンを配置しただけです。
Activity
Activityも作っていきます。
import android.graphics.Color
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import android.graphics.Shader
import android.graphics.LinearGradient
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView = findViewById<TextView>(R.id.textView)
val button = findViewById<Button>(R.id.button)
textView.maxLines = 6
textView.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, " +
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " +
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris " +
"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in " +
"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " +
"pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " +
"culpa qui officia deserunt mollit anim id est laborum." +
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, " +
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " +
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris " +
"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in " +
"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " +
"pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " +
"culpa qui officia deserunt mollit anim id est laborum."
val runnable = Runnable {
val shader = LinearGradient(
0F, (textView.height * 0.5).toFloat(), 0F, textView.height.toFloat()*0.95F, textView.currentTextColor, Color.TRANSPARENT, Shader.TileMode.CLAMP)
textView.paint.shader = shader
}
textView.post(runnable)
button.setOnClickListener {
textView.maxLines = Integer.MAX_VALUE
val shader = LinearGradient(
0F, 0F, 0F, textView.height.toFloat(), textView.currentTextColor, textView.currentTextColor, Shader.TileMode.CLAMP)
textView.paint.shader = shader
}
}
}
ポイントはLinearGradient
を使用しているところです。これはViewに対して直線方向のグラデーションを適用できるクラスです。
val shader = LinearGradient(
0F, (textView.height * 0.5).toFloat(), 0F, textView.height.toFloat()*0.95F, textView.currentTextColor, Color.TRANSPARENT, Shader.TileMode.CLAMP)
この部分では、上記LinearGradient
を使用して、縦(X方向)にtextViewの50%の高さで現在のテキストカラーから開始し、95%の高さで透明になるグラデーションを作成しています。その後これを実際に適用する処理が描画後に走るようにpostしています。
ボタンが押された場合は、
textView.maxLines = Integer.MAX_VALUE
こちらでmaxLinesの制限を取り払い
val shader = LinearGradient(
0F, 0F, 0F, textView.height.toFloat(), textView.currentTextColor, textView.currentTextColor, Shader.TileMode.CLAMP)
textView.paint.shader = shader
こちらでさきほどのグラデーションを無効にしています。これでボタンを押すことで続きが表示される機能が実現できます!