정상에서 IT를 외치다

[Android, Custom Toast] 커스텀 토스트 만들기 본문

안드로이드

[Android, Custom Toast] 커스텀 토스트 만들기

Black-Jin 2020. 11. 30. 08:11
반응형

안녕하세요. 블랙진입니다.


지난 포스팅에 이에 토스트를 커스텀 마이징 하는 법을 확인해보겠습니다.


Custom Dialog Fragment 만들기 

Custom Toast 만들기 (현재)

Custom SnackBar 만들기



토스트


화면 최상단에 자동으로 보였다가 사라지는 팝업을 사용자에게 보여줍니다.



val context = this
Toast.makeText(context, "Welcome to blackjin Tistory", Toast.LENGTH_SHORT).show()

사용법은 간답합니다. 여기에 더불어 gravity 속성을 더해 위치를 변경해 줄 수 있습니다.




Gravity 속성 살펴보기


속성을 하단 왼쪽으로 정해보았습니다.

val toast = Toast.makeText(context, "Welcome to blackjin Tistory", Toast.LENGTH_SHORT)
toast.setGravity(Gravity.BOTTOM or Gravity.START, 0, 0)
toast.show()




화면 하단과 왼쪽 모서리에 붙어서 토스트가 나옴을 확인 할 수 있습니다. setGravity의 코드를 자세히 살펴보겠습니다.

public void setGravity(int gravity, int xOffset, int yOffset) {
if (isSystemRenderedTextToast()) {
Log.e(TAG, "setGravity() shouldn't be called on text toasts, the values won't be used");
}
mTN.mGravity = gravity;
mTN.mX = xOffset;
mTN.mY = yOffset;
}

위와 같이 xOffset, yOffset의 파라미터가 있음을 확인할 수 있습니다. 이 값은 x와 y좌표를 사용해 화면에서 얼마나 떨어져 있는지를 확인할 수 있는데요.




TIP 왼쪽 20dp, 아래 20dp로 마진을 주고 싶으면 어떻게 해야 할까요?




다비이스는 필셀(px) 단위로 이뤄져 있고 해상도가 모두 다릅니다. 이에 픽셀값을 해상도에 맞춰 변환해주는 작업이 필요합니다. 



Dp 구하는 공식

1dp = dpi / 160 * 1px = density * 1px


더 자세한 내용을 확인하고 싶으시면 비트맵에 대한 탐구를 확인해 주세요



이므로 아래와 같은 식이 나옵니다.



ValueToPx ->  density * value

private fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()


ValueToDp -> value / density

private fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()


위 예제에서 20dp 떨어진 토스트는 아래와 같이 구현 됩니다.

val toast = Toast.makeText(context, "Welcome to blackjin Tistory", Toast.LENGTH_SHORT)
toast.setGravity(Gravity.BOTTOM or Gravity.START, 20.toPx(), 20.toPx())
toast.show()




Custom Toast 만들기


그럼 직접 레이아웃을 입힌 Custom Toast 만드는 코드를 공유하겠습니다. 구현 결과물은 아래와 같습니다.




1. layout 만들기 (toast_sample.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">

<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardBackgroundColor="#2B353E"
app:cardCornerRadius="12dp"
app:cardElevation="3dp">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="60dp"
android:paddingStart="20dp"
android:paddingEnd="20dp">

<TextView
android:id="@+id/tvSample"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:text="Hello World!"
android:textColor="@android:color/white"
android:textSize="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/ivSample"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:id="@+id/ivSample"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tvSample"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</layout>


2. 공용으로 사용할 SampleToast object 만들기

object SampleToast {

fun createToast(context: Context, message: String): Toast? {
val inflater = LayoutInflater.from(context)
val binding: ToastSampleBinding =
DataBindingUtil.inflate(inflater, R.layout.toast_sample, null, false)

binding.tvSample.text = message

return Toast(context).apply {
setGravity(Gravity.BOTTOM or Gravity.CENTER, 0, 16.toPx())
duration = Toast.LENGTH_LONG
view = binding.root
}
}

private fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()
}


3. 사용하기

val context = this
SampleToast.createToast(context, "Welcome to blackjin Tistory")?.show()


반응형
Comments