起步软件技术论坛
搜索
 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 5640|回复: 0

[分享] toast插件,在非UI主线程运行,解决在后台无法提示的问题

[复制链接]

1014

主题

4371

帖子

1万

积分

论坛元老

Rank: 8Rank: 8

积分
10977
QQ
发表于 2019-9-3 21:44:18 | 显示全部楼层 |阅读模式
覆盖java文件:/Native/plugins/cordova-plugin-x-toast/src/android/nl/xservices/plugins/Toast.java
  1. package nl.xservices.plugins;

  2. import android.graphics.Color;
  3. import android.graphics.drawable.GradientDrawable;
  4. import android.os.Build;
  5. import android.view.Gravity;
  6. import android.view.MotionEvent;
  7. import android.view.View;
  8. import android.view.ViewGroup;

  9. import org.apache.cordova.CallbackContext;
  10. import org.apache.cordova.CordovaPlugin;
  11. import org.apache.cordova.PluginResult;
  12. import org.json.JSONArray;
  13. import org.json.JSONException;
  14. import org.json.JSONObject;

  15. import java.lang.Thread;
  16. import java.lang.Runnable;
  17. import android.os.Handler;
  18. import android.os.Looper;
  19. /*
  20.     // TODO nice way for the Toast plugin to offer a longer delay than the default short and long options
  21.     // TODO also look at https://github.com/JohnPersano/Supertoasts
  22.     new CountDownTimer(6000, 1000) {
  23.       public void onTick(long millisUntilFinished) {toast.show();}
  24.       public void onFinish() {toast.show();}
  25.     }.start();

  26.     Also, check https://github.com/JohnPersano/SuperToasts
  27. */
  28. public class Toast extends CordovaPlugin {

  29.   private static final String ACTION_SHOW_EVENT = "show";
  30.   private static final String ACTION_HIDE_EVENT = "hide";

  31.   private static final int GRAVITY_TOP = Gravity.TOP|Gravity.CENTER_HORIZONTAL;
  32.   private static final int GRAVITY_CENTER = Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL;
  33.   private static final int GRAVITY_BOTTOM = Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL;

  34.   private static final int BASE_TOP_BOTTOM_OFFSET = 20;

  35.   private android.widget.Toast mostRecentToast;
  36.   private ViewGroup viewGroup;

  37.   private static final boolean IS_AT_LEAST_LOLLIPOP = Build.VERSION.SDK_INT >= 21;

  38.   // note that webView.isPaused() is not Xwalk compatible, so tracking it poor-man style
  39.   private boolean isPaused;

  40.   @Override
  41.   public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
  42.     if (ACTION_HIDE_EVENT.equals(action)) {
  43.       if (mostRecentToast != null) {
  44.         mostRecentToast.cancel();
  45.         getViewGroup().setOnTouchListener(null);
  46.       }
  47.       callbackContext.success();
  48.       return true;

  49.     } else if (ACTION_SHOW_EVENT.equals(action)) {

  50.       if (this.isPaused) {
  51.         return true;
  52.       }

  53.       final JSONObject options = args.getJSONObject(0);

  54.       final String message = options.getString("message");
  55.       final String duration = options.getString("duration");
  56.       final String position = options.getString("position");
  57.       final int addPixelsY = options.has("addPixelsY") ? options.getInt("addPixelsY") : 0;
  58.       final JSONObject data = options.has("data") ? options.getJSONObject("data") : null;
  59.       final JSONObject styling = options.optJSONObject("styling");

  60.       //wjw:20190830修改,支持toast可以在后台使用
  61.       new Thread(){
  62.               @Override
  63.               public void run(){
  64.                       // Looper.prepare();
  65.                       new Handler(Looper.getMainLooper()).post(new Runnable() {
  66.       
  67.                               @Override
  68.                               public void run() {

  69.                               final android.widget.Toast toast = android.widget.Toast.makeText(
  70.                                   IS_AT_LEAST_LOLLIPOP ? cordova.getActivity().getWindow().getContext() : cordova.getActivity().getApplicationContext(),
  71.                                   message,
  72.                                   "short".equals(duration) ? android.widget.Toast.LENGTH_SHORT : android.widget.Toast.LENGTH_LONG);

  73.                               if ("top".equals(position)) {
  74.                                 toast.setGravity(GRAVITY_TOP, 0, BASE_TOP_BOTTOM_OFFSET + addPixelsY);
  75.                               } else  if ("bottom".equals(position)) {
  76.                                 toast.setGravity(GRAVITY_BOTTOM, 0, BASE_TOP_BOTTOM_OFFSET - addPixelsY);
  77.                               } else if ("center".equals(position)) {
  78.                                 toast.setGravity(GRAVITY_CENTER, 0, addPixelsY);
  79.                               } else {
  80.                                 callbackContext.error("invalid position. valid options are 'top', 'center' and 'bottom'");
  81.                                 return;
  82.                               }

  83.                               // if one of the custom layout options have been passed in, draw our own shape
  84.                               if (styling != null && Build.VERSION.SDK_INT >= 16) {

  85.                                 // the defaults mimic the default toast as close as possible
  86.                                 final String backgroundColor = styling.optString("backgroundColor", "#333333");
  87.                                 final double opacity = styling.optDouble("opacity", 0.8);
  88.                                 final int cornerRadius = styling.optInt("cornerRadius", 100);
  89.                                 final int horizontalPadding = styling.optInt("horizontalPadding", 50);
  90.                                 final int verticalPadding = styling.optInt("verticalPadding", 30);

  91.                                 GradientDrawable shape = new GradientDrawable();
  92.                                 shape.setCornerRadius(cornerRadius);
  93.                                 shape.setAlpha((int)(opacity * 255)); // 0-255, where 0 is an invisible background
  94.                                 shape.setColor(Color.parseColor(backgroundColor));
  95.                                 toast.getView().setBackground(shape);
  96.                                 toast.getView().setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);

  97.                                 // this gives the toast a very subtle shadow on newer devices
  98.                                 if (Build.VERSION.SDK_INT >= 21) {
  99.                                   toast.getView().setElevation(6);
  100.                                 }
  101.                               }

  102.                               // On Android >= 5 you can no longer rely on the 'toast.getView().setOnTouchListener',
  103.                               // so created something funky that compares the Toast position to the tap coordinates.
  104.                               if (IS_AT_LEAST_LOLLIPOP) {
  105.                                 getViewGroup().setOnTouchListener(new View.OnTouchListener() {
  106.                                   @Override
  107.                                   public boolean onTouch(View view, MotionEvent motionEvent) {
  108.                                     if (motionEvent.getAction() != MotionEvent.ACTION_DOWN) {
  109.                                       return false;
  110.                                     }
  111.                                     if (mostRecentToast == null || !mostRecentToast.getView().isShown()) {
  112.                                       getViewGroup().setOnTouchListener(null);
  113.                                       return false;
  114.                                     }

  115.                                     float w = mostRecentToast.getView().getWidth();
  116.                                     float startX = (view.getWidth() / 2) - (w / 2);
  117.                                     float endX = (view.getWidth() / 2) + (w / 2);

  118.                                     float startY;
  119.                                     float endY;

  120.                                     float g = mostRecentToast.getGravity();
  121.                                     float y = mostRecentToast.getYOffset();
  122.                                     float h = mostRecentToast.getView().getHeight();

  123.                                     if (g == GRAVITY_BOTTOM) {
  124.                                       startY = view.getHeight() - y - h;
  125.                                       endY = view.getHeight() - y;
  126.                                     } else if (g == GRAVITY_CENTER) {
  127.                                       startY = (view.getHeight() / 2) + y - (h / 2);
  128.                                       endY = (view.getHeight() / 2) + y + (h / 2);
  129.                                     } else {
  130.                                       // top
  131.                                       startY = y;
  132.                                       endY = y + h;
  133.                                     }

  134.                                     float tapX = motionEvent.getX();
  135.                                     float tapY = motionEvent.getY();

  136.                                     final boolean tapped = tapX >= startX && tapX <= endX &&
  137.                                         tapY >= startY && tapY <= endY;

  138.                                     if (tapped) {
  139.                                       getViewGroup().setOnTouchListener(null);
  140.                                       return returnTapEvent(message, data, callbackContext);
  141.                                     }
  142.                                     return false;
  143.                                   }
  144.                                 });
  145.                               } else {
  146.                                 toast.getView().setOnTouchListener(new View.OnTouchListener() {
  147.                                   @Override
  148.                                   public boolean onTouch(View view, MotionEvent motionEvent) {
  149.                                     return motionEvent.getAction() == MotionEvent.ACTION_DOWN && returnTapEvent(message, data, callbackContext);
  150.                                   }
  151.                                 });
  152.                               }

  153.                               toast.show();
  154.                               mostRecentToast = toast;

  155.                               PluginResult pr = new PluginResult(PluginResult.Status.OK);
  156.                               pr.setKeepCallback(true);
  157.                               callbackContext.sendPluginResult(pr);
  158.                               }
  159.                       });
  160.               }
  161.       }.start();


  162.       return true;
  163.     } else {
  164.       callbackContext.error("toast." + action + " is not a supported function. Did you mean '" + ACTION_SHOW_EVENT + "'?");
  165.       return false;
  166.     }
  167.   }

  168.   private boolean returnTapEvent(String message, JSONObject data, CallbackContext callbackContext) {
  169.     final JSONObject json = new JSONObject();
  170.     try {
  171.       json.put("event", "touch");
  172.       json.put("message", message);
  173.       json.put("data", data);
  174.     } catch (JSONException e) {
  175.       e.printStackTrace();
  176.     }
  177.     callbackContext.success(json);
  178.     return true;
  179.   }

  180.   // lazy init and caching
  181.   private ViewGroup getViewGroup() {
  182.     if (viewGroup == null) {
  183.       viewGroup = (ViewGroup) ((ViewGroup) cordova.getActivity().findViewById(android.R.id.content)).getChildAt(0);
  184.     }
  185.     return viewGroup;
  186.   }

  187.   @Override
  188.   public void onPause(boolean multitasking) {
  189.     if (mostRecentToast != null) {
  190.       mostRecentToast.cancel();
  191.       getViewGroup().setOnTouchListener(null);
  192.     }
  193.     this.isPaused = true;
  194.   }

  195.   @Override
  196.   public void onResume(boolean multitasking) {
  197.     this.isPaused = false;
  198.   }
  199. }
复制代码


孤舟蓑笠翁,独钓寒江雪。
X5牛刀交流民间第一群:30057529
提供有偿服务,联系WX:18332024
bex5疑难问题解决方案
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|X3技术论坛|Justep Inc.    

GMT+8, 2024-11-21 17:35 , Processed in 0.066960 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

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