【Toast】关于Android Toast 的一丁点认识
图片来自百度图片,如有侵权,请联络作者删除
??Android Toast 在项目中是普遍应用的一个控件,应该也是一个使用非常简单的控件。这里,有人会问,Toast 这么简单干嘛还要花时间去学习呢,项目里直接 Toast.makeText 即可以了啊。我的答复是:“由于简单,所以需要去学习,去理解”。
为什么我还要去做一个自己设置Toast?
Android Toast 假如在某个场景交互中,一不小心屡次触发了 Toast show 结果是不停地在你屏幕显示同样的 Toast 信息。我是个有时间洁癖的人,不喜欢由于你多显示一次 Toast 信息白费我一秒钟或者两秒钟,在碎片时间学习中,我更希望花一秒钟看到我更喜欢看到的知识,集中精力去得到我想要的东西。
废话少扯,进入主题。
先看看Android 系统 Toast 的实现源码:
Toast MakeText:
/** * Make a standard toast that just contains a text view. * * @param context The context to use. Usually your {@link android.app.Application} * or {@link android.app.Activity} object. * @param text The text to show. Can be formatted text. * @param duration How long to display the message. Either {@link #LENGTH_SHORT} or * {@link #LENGTH_LONG} * */ public static Toast makeText(Context context, CharSequence text, @Duration int duration) { return makeText(context, null, text, duration); } /** * Make a standard toast to display using the specified looper. * If looper is null, Looper.myLooper() is used. * @hide */ public static Toast makeText(@NonNull Context context, @Nullable Looper looper, @NonNull CharSequence text, @Duration int duration) { Toast result = new Toast(context, looper); LayoutInflater inflate = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null); TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message); tv.setText(text); result.mNextView = v; result.mDuration = duration; return result; }再看看Toast 布局:
<?xml version="1.0" encoding="utf-8"?><!--/* //device/apps/common/res/layout/transient_notification.xml**** Copyright 2006, The Android Open Source Project**** Licensed under the Apache License, Version 2.0 (the "License");** you may not use this file except in compliance with the License.** You may obtain a copy of the License at**** http://www.apache.org/licenses/LICENSE-2.0**** Unless required by applicable law or agreed to in writing, software** distributed under the License is distributed on an "AS IS" BASIS,** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.** See the License for the specific language governing permissions and** limitations under the License.*/--><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="?android:attr/toastFrameBackground"> <TextView android:id="@android:id/message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_horizontal" android:textAppearance="@style/TextAppearance.Toast" android:textColor="@color/bright_foreground_dark" android:shadowColor="#BB000000" android:shadowRadius="2.75" /></LinearLayout>Toast show 和 cancel 方法:
/** * Show the view for the specified duration. */ public void show() { if (mNextView == null) { throw new RuntimeException("setView must have been called"); } INotificationManager service = getService(); String pkg = mContext.getOpPackageName(); TN tn = mTN; tn.mNextView = mNextView; try { service.enqueueToast(pkg, tn, mDuration); } catch (RemoteException e) { // Empty } } /** * Close the view if it's showing, or don't show it if it isn't showing yet. * You do not normally have to call this. Normally view will disappear on its own * after the appropriate duration. */ public void cancel() { mTN.cancel(); }??通过简单查看Toast 源码得知少量信息
- Toast 实现没有对同一条消息显示进行过滤,show 方法调用通知服务 enqueueToast 显示信息。
- Toast 布局很简单,就一个LinearLayout 的圆角布局和显示信息的阴影效果。
android:background="?android:attr/toastFrameBackground" android:shadowColor="#BB000000" android:shadowRadius="2.75"显然,系统的Toast 不满足我的需求,我需要一个自己设置一个能够过滤相同信息的 Toast 。
自己设置Toast 主要思想:
- 创立对应构造器。采用设计模式 Builder 模式构造一个需要的Toast。主要针对有个性化 Toast 需求提供,如自己设置背景颜色,自己设置字体颜色,自己设置 Toast 背景布局等。
- 在Toast 上一次显示后没有 cancel 前,界面某个位置屡次触发,只显示同样的Toast 信息一次。取显示信息对应的 hashCode作为key,缓存对应的Toast 信息,假如我每次传入的信息都是同样的则不做显示,Handler 控制对应的显示时间,即便取消 Toast 显示,清理上次Toast 显示信息。
- Toast 背景圆角问题的少量思考。Android Toast 圆角布局背景调用的Android 系统 xml 布局,假如动态修改 View 布局颜色会丢失 圆角。当然,采用简单的自己设置一个圆角布局即可以处理问题的,具体圆角布局代码可参照代码里 RoundLinearLayout.java,具体使用方式太简单了,这里不做细说。
自己设置相关代码展现:
private void initCustomToast(CustomToastBuilder builder) { runnable = RUNNABLES.get(text.hashCode()); if (isNull(runnable)) { customToast = new CustomToast(mContext); runnable = new ToastRunnable(customToast); RUNNABLES.put(text.hashCode(), runnable); long showTime = builder.showTime; if (showTime > DEFAULT_SHOW_TIME){ mHander.postDelayed(runnable, showTime); }else { mHander.postDelayed(runnable, DEFAULT_SHOW_TIME); } customToast.show(builder.customToastCreator,builder.text,builder.textResId); } } public void show(CharSequence text) { if (!text.equals(TEXTS.get(text.hashCode()))) { TEXTS.put(text.hashCode(), text); systemToast = new SystemToast(mContext); runnable = new ToastRunnable(systemToast); mHander.postDelayed(runnable, DEFAULT_SHOW_TIME); systemToast.show(text); } }private class ToastRunnable implements Runnable { private BaseToast toast; public ToastRunnable(BaseToast toast) { this.toast = toast; } @Override public void run() { toast.cancel(); TEXTS.remove(toast.getText().hashCode()); RUNNABLES.remove(toast.getText().hashCode()); toast = null; runnable = null; } }圆角布局:
@SuppressLint("WrongConstant") private void drawRoundDrawable() { Log.d(TAG, "drawRoundDrawable: "+cornesRadius); if (null == gradientDrawable) { return; } if (cornesRadius != 0) { gradientDrawable.setCornerRadius(cornesRadius); gradientDrawable.setGradientType(GradientDrawable.RECTANGLE); } else if (null != radii) { gradientDrawable.setCornerRadii(radii); gradientDrawable.setGradientType(GradientDrawable.RECTANGLE); } setBackgroundDrawable(); }自己设置 Toast 如何使用,代码(Kotlin)如下:
1. 最简单的使用
JToast.getInstance(this).show("show 一个!") 2. 构造器的使用
var creator = SystemToastCreator.build() .shadowColor(Color.parseColor("#2F4F4F")) .shadowRadius(15f) .setTextColor(Color.parseColor("#ffffff")) .creator() JToast.build() .systemToastBuilder() .setToastCreator(creator) .setShowTime(2000) .setText("show creator!") .show(this)var customCreator = CustomToastCreator.build() .setCustomView(R.layout.layout_toast) .setTextColor(Color.WHITE) .setBackgroundRound(true) .creator()JToast.build() .customToastBuilder() .setToastCreator(customCreator) .setShowTime(2000) .setText("show customCreator!",R.id.message) .show(this)我自己设置的代码都太简单了,这里就不太啰嗦了。不懂的也随时可以联络我。
??总结: 我总感觉我的实现方式不太友好,并不完善,欢迎各位评论区提出你们宝贵的建议,或者直接GitHub 把你们的想法提交。非常感谢各位大神的批评指正!
最后给出 GitHub 链接: JToast
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 【Toast】关于Android Toast 的一丁点认识
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 【Toast】关于Android Toast 的一丁点认识