Android超实用的Toast提示框优化分享

作者:daisy 时间:2022-12-20 08:36:32 

前言

相信每位Android开发者都用过Toast,都知道是弹出消息的。类似于js里面的alert,C#里面的MesageBox。当然android里面也有dialogdialog是有焦点的,可与用户交互。而toast是没有焦点的,时间到了自动消失,不能回应用户的交互,下面就跟大家分享下Android中Toast提示框的优化方法。

先看下源码:


public class Toast {

public static final int LENGTH_SHORT = 0;

public static final int LENGTH_LONG = 1;

/**
 * 构造一个空的toast。你必须在调动show()之前,线调用setView()
 * @param context 参数,application或者activity都可以
 */
public Toast(Context context) {
 ...
 //获取系统内置的toast_y_offset常量值
 mTN.mY = context.getResources().getDimensionPixelSize(
   com.android.internal.R.dimen.toast_y_offset);
 mTN.mGravity = context.getResources().getInteger(
   com.android.internal.R.integer.config_toastDefaultGravity);
}

/**
 * 在指定的时长显示view视图
 */
public void show() {
 //如果mNextView为空,即没有设置view
 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
 }
}

/**
 * 关闭一个正在显示的toast, 或者取消一个未显示的toast.
 * 通常你不必调用它,在适当的时长后它会自动消失的。
 */
public void cancel() {
 mTN.hide();

try {
  getService().cancelToast(mContext.getPackageName(), mTN);
 } catch (RemoteException e) {
  // Empty
 }
}

/**
 * 设置toast显示的视图内容,不单单是黑色的界面,你可以自己决定显示什么
 * @see #getView
 */
public void setView(View view) {
 mNextView = view;
}

/**
 * 设置时长,只能是下面这两个常量值,没什么卵用
 * @see #LENGTH_SHORT 2000毫秒
 * @see #LENGTH_LONG 3500毫秒
 */
public void setDuration(@Duration int duration) {
 mDuration = duration;
}

/**
 * 设置view的外间距,不用多说.
 *
 * @param horizontalMargin The horizontal margin, in percentage of the
 *  container width, between the container's edges and the
 *  notification
 * @param verticalMargin The vertical margin, in percentage of the
 *  container height, between the container's edges and the
 *  notification
 */
public void setMargin(float horizontalMargin, float verticalMargin) {
 mTN.mHorizontalMargin = horizontalMargin;
 mTN.mVerticalMargin = verticalMargin;
}

/**
 * 设置notification在屏幕中的方位,大家都知道.上中下左中右什么的都有
 * @see android.view.Gravity
 * @see #getGravity
 */
public void setGravity(int gravity, int xOffset, int yOffset) {
 mTN.mGravity = gravity;
 mTN.mX = xOffset;
 mTN.mY = yOffset;
}

/**
 * 构造一个只包含一个TextView的标准toast对象
 *
 * @param context 通常是application或者activity对象
 * @param text  用于显示的文本,可以是formatted text.
 * @param duration 显示时长. LENGTH_SHORT或LENGTH_LONG
 *
 */
public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
 Toast result = new Toast(context);

LayoutInflater inflate = (LayoutInflater)
   context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

//包含了一个默认的TextView,这个textview的布局位置在

com.android.internal.R.layout.transient_notification,可以去查看下内容
 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;
}

/**
 * 更新通过makeText()方法创建出来的toast对象显示的文本内容
 * @param s 待显示的新文本内容.
 */
public void setText(CharSequence s) {
 if (mNextView == null) {
  throw new RuntimeException("This Toast was not created with Toast.makeText()");
 }

/**
  * 看来com.android.internal.R.layout.transient_notification布局里面的唯一的
  * TextView标签的id是R.id.message。拿到这个textview,设置新文本内容
  */
 TextView tv = (TextView) mNextView.findViewById(com.android.internal.R.id.message);
 if (tv == null) {
  throw new RuntimeException("This Toast was not created with Toast.makeText()");
 }
 tv.setText(s);
}

static private INotificationManager getService() {
 if (sService != null) {
  return sService;
 }
 //获取远程的通知服务
 sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
 return sService;
}

//TN是一个瞬态通知的子类,里面包含显示和隐藏两个任务对象
private static class TN extends ITransientNotification.Stub {
 final Runnable mShow = new Runnable() {
  @Override
  public void run() {
   handleShow();
  }
 };

final Runnable mHide = new Runnable() {
  @Override
  public void run() {
   handleHide();
   // Don't do this in handleHide() because it is also invoked by handleShow()
   mNextView = null;
  }
 };

//出现Handler了哦
 final Handler mHandler = new Handler();

/**
  * 调度handleShow任务到执行线程中
  */
 @Override
 public void show() {
  if (localLOGV) Log.v(TAG, "SHOW: " + this);
  //handler发送异步任务了
  mHandler.post(mShow);
 }

/**
  * 同上
  */
 @Override
 public void hide() {
  if (localLOGV) Log.v(TAG, "HIDE: " + this);
  mHandler.post(mHide);
 }

//...
}

}

通过上面的源码解读,了解到有远程通知,handler异步任务等信息,不多说,自己看。

重点是toast的用法:

1、直接调用makeText静态方法即可,返回的是Toast对象,最后别忘了调用show方法显示:


Toast.makeText(context, text, duration).show();



Toast toast = Toast.makeText(context, text, duration);
pre name="code" class="html"> toast.setView(view);
toast.setText(s);
toast.setGravity(gravity, xOffset, yOffset);
toast.setDuration(duration);
toast.show();

2、还可以使用new的方式创建,别忘了setView()方法:


Toast toast = new Toast();
toast.setView(view);
toast.setText(s);
toast.setGravity(gravity, xOffset, yOffset);
toast.setDuration(duration);
toast.show();

以上这些都不值得一提,很简单。

在开发过程中,有这样的需求:在项目总,我们偷懒,想连串toast出多个变量的值或者其他任务,可在操作手机时直观可见。问题来了,弹出是无论我们的操作有多快,这些toast内容都是一个跟着一个显示,没办法快进。哪怕我们玩完了,退出了app,它还在弹。怎么办?有没有办法让toast的内容与我们的操作同步,快速反应?


public class T {
private static Toast toast;

public static void show(Context context, String msg) {
 if (toast == null) {
  toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
 } else {
  toast.setText(msg);
 }
 toast.show();
}
}

单例模式,每次创建toast都调用这个类的show方法,Toast的生命周期从show开始,到自己消失或者cancel为止。如果正在显示,则修改显示的内容,你持有这个对象的引用,当然可以修改显示的内容了。若每次你都makeText或者new一个toast对象,即每次通过handler发送异步任务,调用远程通知服务显示通知,当然是排队等待显示了。

结束语

标签:android,toast,优化
0
投稿

猜你喜欢

  • Spring如何基于aop实现事务控制

    2021-07-21 11:26:06
  • Java实现两人五子棋游戏(三) 画出棋子

    2021-05-29 04:53:53
  • Kotlin Flow操作符及基本使用详解

    2022-08-24 16:32:30
  • 浅谈Java中的Filter过滤器

    2023-07-23 10:00:08
  • Android布局之LinearLayout自定义高亮背景的方法

    2022-07-05 09:48:10
  • SpringBoot+hutool实现图片验证码

    2021-06-17 02:55:27
  • android使用PullToRefresh实现下拉刷新和上拉加载

    2023-08-06 11:06:58
  • springcloud使用Hystrix进行微服务降级管理

    2023-02-02 06:51:30
  • Java实现的最大匹配分词算法详解

    2021-12-30 00:50:04
  • java HashMap通过value反查key的代码示例

    2022-06-07 08:50:55
  • Android中基于XMPP协议实现IM聊天程序与多人聊天室

    2022-05-06 07:37:51
  • C#操作字符串方法总结实例代码

    2022-03-29 20:04:54
  • Spring IOC与DI核心深入理解

    2023-10-29 14:09:15
  • 使用C#实现读取系统配置文件的代码实例讲解

    2023-02-18 10:36:56
  • Struts2实现文件上传时显示进度条功能

    2021-10-13 05:22:22
  • IDEA插件EasyCode及MyBatis最优配置步骤详解

    2023-11-09 03:19:19
  • Android编程解析XML方法详解(SAX,DOM与PULL)

    2022-12-07 16:03:46
  • C#微信公众号开发之自定义菜单

    2023-01-23 02:07:08
  • java创建子类对象设置并调用父类的变量操作

    2023-10-13 18:16:13
  • Unity实现文本转贴图

    2022-05-10 19:53:04
  • asp之家 软件编程 m.aspxhome.com