Android 自界说Toast

源码 2024-9-19 18:29:40 93 0 来自 中国
原生的Toast实在相称好用,而且充足简单轻量,但是架不住需求光怪陆离,而且老板一样平常都会以为这个提示不显着!原来Toast是可以自界说样式的,但如今setView方法已颠末期,本文通过自界说View的情势来实现类Toast结果,先上结果图
2.gif 获取屏幕宽高

由于须要将Toast表现到一个大抵固定的位置、只管表现一行且不能超过屏幕宽度,以是须要获取屏幕宽高,这里简单写了个工具类。
object DisplayUtil {    /**     * 可用表现巨细的绝对宽度(以像素为单元)     */    fun getWidth(): Int = Application.getInstance().resources.displayMetrics.widthPixels    /**     * 可用表现巨细的绝对高度(以像素为单元)     */    fun getHeight(): Int = Application.getInstance().resources.displayMetrics.heightPixels}这里使用的是单例Application来获取resources,还不知道的可以网上搜一下,也可以看看这篇文章<<Android 获取当前Activity>> 内里写了单例Application的代码。
自界说Toast

先创建toast_dialog_bg_style.xml用作Toast的配景样式,这里就是黑色有一点点透明的圆角配景。
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"    android:shape="rectangle">    <corners android:radius="85dp"/>    <solid android:color="@color/toast_bg" /></shape>然后是Toast的布局,创建alert_dialog_toast.xml,我这里只放了文本,有爱好的可以在布局里加上图片之类的。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    androidrientation="vertical"    android:layout_width="wrap_content"    android:layout_height="140dp"    android:background="@drawable/toast_dialog_bg_style"    android:padding="20dp"    android:paddingEnd="40dp"    android:paddingStart="40dp"    android:gravity="center">    <TextView        android:id="@+id/toast_text"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textColor="@color/white"        android:gravity="center"        android:textSize="40sp"/></LinearLayout>末了就是核心代码了,由于使用悬浮窗是须要权限,高版本还须要用户授权才可以,以是我这里直接继续PopupWindow来编写。
class MToast private constructor() : PopupWindow(    ViewGroup.LayoutParams.WRAP_CONTENT,    ViewGroup.LayoutParams.WRAP_CONTENT) {    private var mActivity: WeakReference<Activity>? = null    private var mView: WeakReference<View>? = null    private var mText: WeakReference<TextView>? = null    private var textQueue: Queue<ArrayList<Any>> = LinkedBlockingQueue()    // 最大等候表现数量    private val maxWaitShowNumber = 10    // 左右内边距之和    private var paddingWidth = 0    companion object {        fun makeText(            context: Context,            text: String,            showLength: Int = Toast.LENGTH_SHORT        ): MToast {            val instance = Inner.instance            if (instance.maxWaitShowNumber > instance.textQueue.size) {                instance.textQueue.offer(arrayListOf(text, showLength * 2 + 1))            }            val activity = context as Activity            if (instance.mActivity?.get()?.localClassName != activity.localClassName) {                instance.mActivity = WeakReference(activity)                instance.initView()            }            return instance        }    }    private object Inner {        var instance: MToast = MToast()    }    @SuppressLint("InflateParams")    private fun initView() {        mActivity?.get()?.let {            val view = LayoutInflater.from(it)                .inflate(R.layout.alert_dialog_toast, null, false)            mView = WeakReference(view)            mText = WeakReference(view.findViewById(R.id.toast_text))            paddingWidth = view.paddingStart + view.paddingEnd            contentView = view            // 不设置核心            isFocusable = false            // 点击退却键pop消散            isTouchable = false            setBackgroundDrawable(ColorDrawable(0x00000000))            // 设置自带的淡出淡入结果            animationStyle = R.style.Animation_AppCompat_Dialog        }    }    fun show() {        if (!isShowing) {            textQueue.poll()?.let { item ->                mActivity?.get()?.let {                    val nText = item[0] as String                    val showLength = item[1] as Int                    mText?.get()?.let { textView ->                        textView.text = nText                        // 界面宽高                        val heightPixels = DisplayUtil.getHeight()                        val widthPixels = DisplayUtil.getWidth()                        // 内容宽度+布局宽度                        val dw = StaticLayout.getDesiredWidth(nText, textView.paint)                        val cmpWidth = dw.toInt() + paddingWidth                        width = if (cmpWidth > widthPixels)                            widthPixels - paddingWidth                        else                            cmpWidth                        showAtLocation(it.window.decorView, Gravity.CENTER, 0, heightPixels / 2 - heightPixels / 10)                        CoroutineUtil.execIO {                            delay(showLength * 1000L)                            withContext(Dispatchers.Main) {                                hide()                                if (textQueue.size > 0) {                                    show()                                }                            }                        }                    }                }            }        }    }    private fun hide() {        if (isShowing) {            dismiss()        }    }}这里调用和Toast的调用一样,但实际上照旧有一些区别,这里做成了静态单例类,然后有一个队列来装要表现的数据,通过makeText举行添加,show则是按顺序表现在队列里的数据,直到没有为止。
MToast.makeText(context, "msg", Toast.LENGTH_SHORT).show()Acitivity切换的时间应该照旧会存在一些题目,不过通例使用应该可以了
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2025-4-19 19:39, Processed in 0.112939 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表