💡
Android のダイアログで吹き出しを表現する
はじめに
ダイアログで吹き出しを表示するサンプルがなかったので作成してみました!
少し考えれば実装できるような内容ですが、ちょっとした追加機能をお知らせする際の強調表示などに使えると思います。
実行結果
最終的にはこのような吹き出しが表示されます。
layout
Dialog の setView に設定する layout です。
<?xml version="1.0" encoding="utf-8"?>
<layout
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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40dp"
android:text="▲"
android:textColor="#de3949ab"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginEnd="12dp"
android:rotation="290"
tools:ignore="HardcodedText,SpUsage" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="28dp"
app:cardCornerRadius="4dp"
app:cardElevation="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:background="#de3949ab"
android:orientation="vertical">
<TextView
android:id="@+id/text_normal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
tools:text="細字はこのように表示されます" />
<TextView
android:id="@+id/text_bold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textStyle="bold"
tools:text="太字はこのように表示されます" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
吹き出し部分は TextView を用いて ▲
を回転させることで表現しています。
先にこの TextView を持ってくることで CardView の下へ設定できました。
textSize を sp で設定してしまうとフォント設定に依存してしまうので、dp 指定しています。
実際には三角形の画像がよいと思います。
DialogFragment
引数を増やせば矢印の位置だったり向きだったりを変えられると思いますが、サンプルなので最低限の引数にしています。
class BubbleDialogFragment : DialogFragment() {
private lateinit var argNormalText: String
private lateinit var argBoldText: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.run {
argNormalText = getString(ARGS_TEXT_NORMAL) ?: throw IllegalArgumentException("arg is null")
argBoldText = getString(ARGS_TEXT_BOLD) ?: throw IllegalArgumentException("arg is null")
}
}
override fun onCreateDialog(savedInstanceState: Bundle?) = context?.let { context ->
AlertDialog.Builder(context).apply {
setView(FragmentBubbleDialogBinding.inflate(layoutInflater).apply {
textNormal.text = argNormalText
textBold.text = argBoldText
}.root.apply {
setOnClickListener { dismiss() }
})
}.create().apply {
window?.run {
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
attributes = attributes.apply {
width = ViewGroup.LayoutParams.MATCH_PARENT
height = ViewGroup.LayoutParams.MATCH_PARENT
gravity = Gravity.BOTTOM
y = 30
}
}
}
}!!
companion object {
const val ARGS_TEXT_NORMAL = "bubble_dialog_text_normal"
const val ARGS_TEXT_BOLD = "bubble_dialog_text_bold"
fun newInstance(normalText: String, boldText: String, isPremium: Boolean) =
BubbleDialogFragment().apply {
arguments = Bundle().apply {
putString(ARGS_TEXT_NORMAL, normalText)
putString(ARGS_TEXT_BOLD, boldText)
}
}
}
}
layout.root の setOnClickListener に dismiss を入れることで画面のどこをタップしても消えるようにしました。
また、window.setBackgroundDrawable に透明を指定することで CardView の角や吹き出し部分に白い枠が出ないようにしています。
attributes.y などで画面に合わせて表示する位置を変えていただければと思います。
最後に…
工夫の余地はありますが、流れは掴めたでしょうか??
どなたかの参考になれば幸いです<(_ _)>
Discussion