Compare commits

...
29 Commits
Author SHA1 Message Date
EddyVerbruggen 9ed9f018a7 #71 ios toast get error while message is integer 2016-03-17 21:30:17 +01:00
EddyVerbruggen fe1aed17e3 #59 Add specific duration of the toast 2016-03-17 21:23:19 +01:00
Eddy Verbruggen 4fb9932c9b Merge pull request #78 from NoahYarian/patch-1
README.md - replaced , with : for valid JSON in success callback example
2016-02-29 22:32:58 +01:00
Noah Yarian 4c65555aca README.md - replaced , with : for valid JSON in success callback example 2016-02-29 15:08:59 -06:00
Eddy Verbruggen aa1a771f7b Update README.md 2016-02-19 09:43:44 +01:00
Eddy Verbruggen 35ace3dd9d Update README.md 2016-02-19 09:43:09 +01:00
Eddy Verbruggen c0daed7ce4 Update README.md 2016-02-19 09:42:57 +01:00
EddyVerbruggen 8dbcc43e68 #75 [Toast-PhoneGap-Plugin] styling.opacity is meanless 2016-02-18 21:18:00 +01:00
Eddy Verbruggen 4f6463e3f2 Update issue_template.md 2016-02-17 21:40:01 +01:00
Eddy Verbruggen 41a568c549 Update issue_template.md 2016-02-17 21:35:34 +01:00
EddyVerbruggen 811e0a82ed issue template 2016-02-17 21:27:24 +01:00
Eddy Verbruggen a2d253bdde Update plugin.xml 2016-02-17 19:50:19 +01:00
Eddy Verbruggen ffe056db75 Merge pull request #73 from Telerik-Verified-Plugins/master
Style the text color
2016-02-17 19:50:05 +01:00
EddyVerbruggen 5e5251bbd2 #2 Allow the user set a textColor - fixed a compiler warning, added doc, and bumped the version 2016-02-17 19:47:32 +01:00
Eddy Verbruggen 37c14a6d2d Merge pull request #2 from ergowerk/master
Allow the user set a textColor
2016-02-17 19:27:24 +01:00
Sino 369ab363b9 fixed naming, id and import 2016-02-16 22:53:43 +01:00
Sino 6ba778dd22 option to set the text color of the toast 2016-02-16 17:00:52 +01:00
Sino e8ade312d9 possibillity to change text color as a styling option 2016-02-16 16:48:24 +01:00
EddyVerbruggen f6479c8846 Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	plugin.xml
2016-01-27 23:07:58 +01:00
EddyVerbruggen 658ee711db Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	plugin.xml
2016-01-27 23:07:49 +01:00
EddyVerbruggen 5f4a0f5636 #4 styling 2016-01-27 20:49:03 +01:00
EddyVerbruggen c7a329a7ac Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	plugin.xml
2016-01-15 15:51:18 +01:00
EddyVerbruggen 577b1704d9 Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	plugin.xml
2016-01-15 15:51:10 +01:00
EddyVerbruggen ac0746b9b9 #65 Success callback not triggered when toast tapped in Android 2016-01-15 13:12:03 +01:00
EddyVerbruggen 7a08e6afd6 sync from upstream 2015-12-08 12:35:44 +01:00
EddyVerbruggen 23d35404b5 sync from upstream 2015-12-08 12:35:37 +01:00
EddyVerbruggen c5b6060973 upstream update 2015-12-08 12:18:08 +01:00
EddyVerbruggen cabeea18ed upstream update 2015-12-08 12:18:00 +01:00
EddyVerbruggen 6e13de8982 Stable ID for AB 2015-10-01 10:34:25 +02:00
12 changed files with 319 additions and 106 deletions
+50 -11
View File
@@ -2,6 +2,9 @@
for Android, iOS and WP8, by [Eddy Verbruggen](http://www.x-services.nl/phonegap-toast-plugin/796)
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=eddyverbruggen%40gmail%2ecom&lc=US&item_name=cordova%2dplugin%2dtoast&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted)
If you like this plugin and want to say thanks please send a PR or donation. Both are equally appreciated!
<table width="100%">
<tr>
@@ -19,6 +22,7 @@ for Android, iOS and WP8, by [Eddy Verbruggen](http://www.x-services.nl/phonegap
3. [Manually](#manually)
3. [PhoneGap Build](#phonegap-build)
4. [Usage](#4-usage)
4. [Styling](#styling)
5. [Credits](#5-credits)
6. [Changelog](#6-changelog)
7. [License](#7-license)
@@ -48,10 +52,18 @@ iOS
![ScreenShot](screenshots/screenshot-ios-toast.png)
A few styling options
![ScreenShot](screenshots/styling-green.png)
![ScreenShot](screenshots/styling-red.png)
Android
![ScreenShot](screenshots/screenshot-android-toast.png)
Windows Phone 8
![ScreenShot](screenshots/screenshot-wp8.jpg)
@@ -129,7 +141,7 @@ Toast.js is brought in automatically. There is no need to change or add anything
### Showing a Toast
You have two choices to make when showing a Toast: where to show it and for how long.
* show(message, duration, position)
* duration: 'short', 'long'
* duration: 'short', 'long', '3000', 900 (the latter are milliseconds)
* position: 'top', 'center', 'bottom'
You can also use any of these convenience methods:
@@ -155,7 +167,7 @@ function showBottom() {
window.plugins.toast.showWithOptions(
{
message: "hey there",
duration: "short",
duration: "short", // which is 2000 ms. "long" is 4000. Or specify the nr of ms yourself.
position: "bottom",
addPixelsY: -40 // added a negative value to move it up a bit (default 0)
},
@@ -184,10 +196,10 @@ called again. You can distinguish between those events of course:
window.plugins.toast.showWithOptions(
{
message: "hey there",
duration: "short",
duration: 1500, // ms
position: "bottom",
addPixelsY: -40, // (optional) added a negative value to move it up a bit (default 0)
data: {'foo','bar'} // (optional) pass in a JSON object here (it will be sent back in the success callback below)
data: {'foo':'bar'} // (optional) pass in a JSON object here (it will be sent back in the success callback below)
},
// implement the success callback
function(result) {
@@ -203,6 +215,31 @@ called again. You can distinguish between those events of course:
);
```
### Styling
Since version 2.4.0 you can pass an optional `styling` object to the plugin.
The defaults make sure the Toast looks the same as when you would not pass in the `styling` object at all.
Note that on WP this object is currently ignored.
```js
window.plugins.toast.showWithOptions({
message: "hey there",
duration: "short", // 2000 ms
position: "bottom",
styling: {
opacity: 0.75, // 0.0 (transparent) to 1.0 (opaque). Default 0.8
backgroundColor: '#FF0000', // make sure you use #RRGGBB. Default #333333
textColor: '#FFFF00', // Ditto. Default #FFFFFF
cornerRadius: 16, // minimum is 0 (square). iOS default 20, Android default 100
horizontalPadding: 20, // iOS default 16, Android default 50
verticalPadding: 16 // iOS default 12, Android default 30
}
});
```
Tip: if you need to pass different values for iOS and Android you can use fi. the device plugin
to determine the platform and pass `opacity: isAndroid() ? 0.7 : 0.9`.
### WP8 quirks
The WP8 implementation needs a little more work, but it's perfectly useable when you keep this in mind:
* You can't show two Toasts simultaneously.
@@ -217,13 +254,15 @@ The Android code was entirely created by me.
For iOS most credits go to this excellent [Toast for iOS project by Charles Scalesse] (https://github.com/scalessec/Toast).
## 6. CHANGELOG
2.3.0: The plugin will now report back to JS if Toasts were tapped by the user.
2.0.1: iOS messages are hidden when another one is shown. [Thanks Richie Min!](https://github.com/EddyVerbruggen/Toast-PhoneGap-Plugin/pull/13)
2.0: WP8 support
1.0: initial version supporting Android and iOS
- 2.5.0: By popular demand: Specify the duration of the Toast on iOS and Android. Pass in `short` (2000ms), `long` (4000ms), or any nr of milliseconds: `900`.
- 2.4.2: You can now also set the Toast `opacity` for iOS.
- 2.4.1: As an addition to 2.4.0, [Sino](https://github.com/SinoBoeckmann) added the option to change the text color!
- 2.4.0: You can now style the Toast with a number of properties. See
- 2.3.2: The click event introduced with 2.3.0 did not work with Android 5+.
- 2.3.0: The plugin will now report back to JS if Toasts were tapped by the user.
- 2.0.1: iOS messages are hidden when another one is shown. [Thanks Richie Min!](https://github.com/EddyVerbruggen/Toast-PhoneGap-Plugin/pull/13)
- 2.0: WP8 support
- 1.0: initial version supporting Android and iOS
## 7. License
+42
View File
@@ -0,0 +1,42 @@
### Expected behaviour
Tell us what should happen.
### Actual behaviour
Tell us what happens instead. Provide a log message if relevant.
### I'm seeing this behaviour on
_Remove this hint: these checkboxes can be checked like this: [x]_
- [ ] iOS device
- [ ] iOS sim
- [ ] Android device
- [ ] Android sim
#### Hardware models
Example: Samsung Galaxy S6, iPhone 6s
#### OS versions
Example: Android 4.4.2, iOS 9.2
### I'm not a dummy, so I've checked these
- [ ] It happens on a fresh Cordova CLI project as well.
- [ ] I'm waiting for `deviceready` to fire.
- [ ] My JavaScript has no errors (`window.onerror` catches nothing).
### So how can we reproduce this?
_Remove this hint: Pick one of these - use the Preview feature of this editor to get a sense which option we like best_
#### Awesome :star::star::star::star::star:
Provide a (link to a) minimal demo app showing the faulty behaviour.
#### Sweet :star::star::star::star:
Provide a concise code sample which can be dropped into a freshly created Cordova CLI app.
#### Good :star::star::star:
Provide your own app and instructions how to reproduce the issue.
#### Meh :star::star:
Provide a code sample with a bunch of magic parameters which I need to interpolate by guessing to reconstruct the actual runtime code.
#### Worst :poop:
Say the source code can't be disclosed and refuse to provide any of the above. Expect this issue to be closed by a bunch of angry aliens :alien::alien::alien::alien::alien: that will hunt you down and :fire: your :computer:. You've been warned. :fire_engine:
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-x-toast",
"version": "2.3.1",
"version": "2.5.0",
"description": "This plugin allows you to show a Toast. A Toast is a little non intrusive buttonless popup which automatically disappears.",
"cordova": {
"id": "cordova-plugin-x-toast",
+1 -1
View File
@@ -2,7 +2,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-x-toast"
version="2.3.1">
version="2.5.0">
<name>Toast</name>
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

+140 -46
View File
@@ -1,9 +1,14 @@
package nl.xservices.plugins;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.CountDownTimer;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
@@ -12,97 +17,156 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/*
// TODO nice way for the Toast plugin to offer a longer delay than the default short and long options
// TODO also look at https://github.com/JohnPersano/Supertoasts
new CountDownTimer(6000, 1000) {
public void onTick(long millisUntilFinished) {toast.show();}
public void onFinish() {toast.show();}
}.start();
Also, check https://github.com/JohnPersano/SuperToasts
*/
public class Toast extends CordovaPlugin {
private static final String ACTION_SHOW_EVENT = "show";
private static final String ACTION_HIDE_EVENT = "hide";
private android.widget.Toast mostRecentToast;
private static final int GRAVITY_TOP = Gravity.TOP|Gravity.CENTER_HORIZONTAL;
private static final int GRAVITY_CENTER = Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL;
private static final int GRAVITY_BOTTOM = Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL;
private static final boolean IS_AT_LEAST_ANDROID5 = Build.VERSION.SDK_INT >= 21;
private static final int BASE_TOP_BOTTOM_OFFSET = 20;
private android.widget.Toast mostRecentToast;
private ViewGroup viewGroup;
// note that webView.isPaused() is not Xwalk compatible, so tracking it poor-man style
private boolean isPaused;
private static CountDownTimer _timer;
@Override
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
if (ACTION_HIDE_EVENT.equals(action)) {
if (mostRecentToast != null) {
mostRecentToast.cancel();
}
hide();
callbackContext.success();
return true;
} else if (ACTION_SHOW_EVENT.equals(action)) {
if (this.isPaused) {
return true;
}
final JSONObject options = args.getJSONObject(0);
final String message = options.getString("message");
final String duration = options.getString("duration");
final String position = options.getString("position");
final int addPixelsY = options.has("addPixelsY") ? options.getInt("addPixelsY") : 0;
final JSONObject data = options.has("data") ? options.getJSONObject("data") : null;
final JSONObject styling = options.optJSONObject("styling");
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
android.widget.Toast toast = android.widget.Toast.makeText(
IS_AT_LEAST_ANDROID5 ? cordova.getActivity().getWindow().getContext() : cordova.getActivity().getApplicationContext(),
int hideAfterMs;
if ("short".equalsIgnoreCase(duration)) {
hideAfterMs = 2000;
} else if ("long".equalsIgnoreCase(duration)) {
hideAfterMs = 4000;
} else {
// assuming a number of ms
hideAfterMs = Integer.parseInt(duration);
}
final android.widget.Toast toast = android.widget.Toast.makeText(
Build.VERSION.SDK_INT >= 21 ? cordova.getActivity().getWindow().getContext() : cordova.getActivity().getApplicationContext(),
message,
"short".equals(duration) ? android.widget.Toast.LENGTH_SHORT : android.widget.Toast.LENGTH_LONG);
android.widget.Toast.LENGTH_LONG // actually controlled by a timer further down
);
// if we want to change the background color some day, we can use this
// try {
// final Method setTintMethod = Drawable.class.getMethod("setTint", int.class);
// setTintMethod.invoke(toast.getView().getBackground(), Color.RED); // default is Color.DKGRAY
// } catch (Exception ignore) {
// }
if ("top".equals(position)) {
toast.setGravity(Gravity.TOP|Gravity.CENTER_HORIZONTAL, 0, 20 + addPixelsY);
toast.setGravity(GRAVITY_TOP, 0, BASE_TOP_BOTTOM_OFFSET + addPixelsY);
} else if ("bottom".equals(position)) {
toast.setGravity(Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 20 - addPixelsY);
toast.setGravity(GRAVITY_BOTTOM, 0, BASE_TOP_BOTTOM_OFFSET - addPixelsY);
} else if ("center".equals(position)) {
toast.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL, 0, addPixelsY);
toast.setGravity(GRAVITY_CENTER, 0, addPixelsY);
} else {
callbackContext.error("invalid position. valid options are 'top', 'center' and 'bottom'");
return;
}
toast.getView().setOnTouchListener(new View.OnTouchListener() {
// if one of the custom layout options have been passed in, draw our own shape
if (styling != null && Build.VERSION.SDK_INT >= 16) {
// the defaults mimic the default toast as close as possible
final String backgroundColor = styling.optString("backgroundColor", "#333333");
final String textColor = styling.optString("textColor", "#ffffff");
final double opacity = styling.optDouble("opacity", 0.8);
final int cornerRadius = styling.optInt("cornerRadius", 100);
final int horizontalPadding = styling.optInt("horizontalPadding", 50);
final int verticalPadding = styling.optInt("verticalPadding", 30);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius(cornerRadius);
shape.setAlpha((int)(opacity * 255)); // 0-255, where 0 is an invisible background
shape.setColor(Color.parseColor(backgroundColor));
toast.getView().setBackground(shape);
final TextView toastTextView;
toastTextView = (TextView) toast.getView().findViewById(android.R.id.message);
toastTextView.setTextColor(Color.parseColor(textColor));
toast.getView().setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);
// this gives the toast a very subtle shadow on newer devices
if (Build.VERSION.SDK_INT >= 21) {
toast.getView().setElevation(6);
}
}
// On newer Android devices you can no longer rely on the 'toast.getView().setOnTouchListener',
// so created something funky that compares the Toast position to the tap coordinates.
getViewGroup().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
JSONObject json = new JSONObject();
try {
json.put("event", "touch");
json.put("message", message);
json.put("data", data);
} catch (JSONException e) {
e.printStackTrace();
}
callbackContext.success(json);
return true;
} else {
if (motionEvent.getAction() != MotionEvent.ACTION_DOWN) {
return false;
}
if (mostRecentToast == null || !mostRecentToast.getView().isShown()) {
getViewGroup().setOnTouchListener(null);
return false;
}
float w = mostRecentToast.getView().getWidth();
float startX = (view.getWidth() / 2) - (w / 2);
float endX = (view.getWidth() / 2) + (w / 2);
float startY;
float endY;
float g = mostRecentToast.getGravity();
float y = mostRecentToast.getYOffset();
float h = mostRecentToast.getView().getHeight();
if (g == GRAVITY_BOTTOM) {
startY = view.getHeight() - y - h;
endY = view.getHeight() - y;
} else if (g == GRAVITY_CENTER) {
startY = (view.getHeight() / 2) + y - (h / 2);
endY = (view.getHeight() / 2) + y + (h / 2);
} else {
// top
startY = y;
endY = y + h;
}
float tapX = motionEvent.getX();
float tapY = motionEvent.getY();
final boolean tapped = tapX >= startX && tapX <= endX &&
tapY >= startY && tapY <= endY;
return tapped && returnTapEvent(message, data, callbackContext);
}
});
toast.show();
// trigger show every 2500 ms for as long as the requested duration
_timer = new CountDownTimer(hideAfterMs, 2500) {
public void onTick(long millisUntilFinished) {toast.show();}
public void onFinish() {toast.cancel();}
}.start();
mostRecentToast = toast;
toast.show();
PluginResult pr = new PluginResult(PluginResult.Status.OK);
pr.setKeepCallback(true);
@@ -117,11 +181,41 @@ public class Toast extends CordovaPlugin {
}
}
@Override
public void onPause(boolean multitasking) {
private void hide() {
if (mostRecentToast != null) {
mostRecentToast.cancel();
getViewGroup().setOnTouchListener(null);
}
if (_timer != null) {
_timer.cancel();
}
}
private boolean returnTapEvent(String message, JSONObject data, CallbackContext callbackContext) {
final JSONObject json = new JSONObject();
try {
json.put("event", "touch");
json.put("message", message);
json.put("data", data);
} catch (JSONException e) {
e.printStackTrace();
}
callbackContext.success(json);
hide();
return true;
}
// lazy init and caching
private ViewGroup getViewGroup() {
if (viewGroup == null) {
viewGroup = (ViewGroup) ((ViewGroup) cordova.getActivity().findViewById(android.R.id.content)).getChildAt(0);
}
return viewGroup;
}
@Override
public void onPause(boolean multitasking) {
hide();
this.isPaused = true;
}
@@ -129,4 +223,4 @@ public class Toast extends CordovaPlugin {
public void onResume(boolean multitasking) {
this.isPaused = false;
}
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
// each makeToast method creates a view and displays it as toast
- (void)makeToast:(NSString *)message;
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)interval position:(id)position;
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position addPixelsY:(int)addPixelsY data:(NSDictionary*)data commandDelegate:(id <CDVCommandDelegate>)commandDelegate callbackId:(NSString *)callbackId;
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position addPixelsY:(int)addPixelsY data:(NSDictionary*)data styling:(NSDictionary*)styling commandDelegate:(id <CDVCommandDelegate>)commandDelegate callbackId:(NSString *)callbackId;
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)interval position:(id)position image:(UIImage *)image;
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)interval position:(id)position title:(NSString *)title;
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)interval position:(id)position title:(NSString *)title image:(UIImage *)image;
+58 -20
View File
@@ -53,6 +53,7 @@ static id commandDelegate;
static id callbackId;
static id msg;
static id data;
static id styling;
@interface UIView (ToastPrivate)
@@ -79,13 +80,22 @@ static id data;
[self showToast:toast duration:duration position:position];
}
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position addPixelsY:(int)addPixelsY data:(NSDictionary*)_data commandDelegate:(id <CDVCommandDelegate>)_commandDelegate callbackId:(NSString *)_callbackId {
commandDelegate = _commandDelegate;
callbackId = _callbackId;
msg = message;
data = _data;
UIView *toast = [self viewForMessage:message title:nil image:nil];
[self showToast:toast duration:duration position:position addedPixelsY:addPixelsY];
- (void)makeToast:(NSString *)message
duration:(NSTimeInterval)duration
position:(id)position addPixelsY:(int)addPixelsY
data:(NSDictionary*)_data
styling:(NSDictionary*)_styling
commandDelegate:(id <CDVCommandDelegate>)_commandDelegate
callbackId:(NSString *)_callbackId {
commandDelegate = _commandDelegate;
callbackId = _callbackId;
msg = message;
data = _data;
styling = _styling;
UIView *toast = [self viewForMessage:message title:nil image:nil];
[self showToast:toast duration:duration position:position addedPixelsY:addPixelsY];
}
- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position title:(NSString *)title {
@@ -130,11 +140,14 @@ static id data;
UIView *v = [vc view];
[v addSubview:toast];
NSNumber * opacity = styling[@"opacity"];
CGFloat theOpacity = opacity == nil ? CSToastOpacity : [opacity floatValue];
[UIView animateWithDuration:CSToastFadeDuration
delay:0.0
options:(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction)
animations:^{
toast.alpha = CSToastOpacity;
toast.alpha = theOpacity;
} completion:^(BOOL finished) {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:duration target:self selector:@selector(toastTimerDidFinish:) userInfo:toast repeats:NO];
// associate the timer with the toast view
@@ -295,7 +308,9 @@ static id data;
// create the parent view
UIView *wrapperView = [[UIView alloc] init];
wrapperView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
wrapperView.layer.cornerRadius = CSToastCornerRadius;
NSNumber * cornerRadius = styling[@"cornerRadius"];
wrapperView.layer.cornerRadius = cornerRadius == nil ? CSToastCornerRadius : [cornerRadius floatValue];
if (CSToastDisplayShadow) {
wrapperView.layer.shadowColor = [UIColor blackColor].CGColor;
@@ -304,12 +319,20 @@ static id data;
wrapperView.layer.shadowOffset = CSToastShadowOffset;
}
wrapperView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:CSToastOpacity];
NSString * backgroundColor = styling[@"backgroundColor"];
UIColor *theColor = backgroundColor == nil ? [UIColor blackColor] : [self colorFromHexString:backgroundColor];
NSNumber * horizontalPadding = styling[@"horizontalPadding"];
NSNumber * verticalPadding = styling[@"verticalPadding"];
CGFloat theHorizontalPadding = horizontalPadding == nil ? CSToastHorizontalPadding : [horizontalPadding floatValue];
CGFloat theVerticalPadding = verticalPadding == nil ? CSToastVerticalPadding : [verticalPadding floatValue];
wrapperView.backgroundColor = theColor;
if(image != nil) {
imageView = [[UIImageView alloc] initWithImage:image];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.frame = CGRectMake(CSToastHorizontalPadding, CSToastVerticalPadding, CSToastImageViewWidth, CSToastImageViewHeight);
imageView.frame = CGRectMake(theHorizontalPadding, theVerticalPadding, CSToastImageViewWidth, CSToastImageViewHeight);
}
CGFloat imageWidth, imageHeight, imageLeft;
@@ -318,18 +341,21 @@ static id data;
if(imageView != nil) {
imageWidth = imageView.bounds.size.width;
imageHeight = imageView.bounds.size.height;
imageLeft = CSToastHorizontalPadding;
imageLeft = theHorizontalPadding;
} else {
imageWidth = imageHeight = imageLeft = 0.0;
}
if (title != nil) {
NSString * titleLabelTextColor = styling[@"textColor"];
UIColor *theTitleLabelTextColor = titleLabelTextColor == nil ? [UIColor whiteColor] : [self colorFromHexString:titleLabelTextColor];
titleLabel = [[UILabel alloc] init];
titleLabel.numberOfLines = CSToastMaxTitleLines;
titleLabel.font = [UIFont boldSystemFontOfSize:CSToastFontSize];
titleLabel.textAlignment = NSTextAlignmentLeft;
titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
titleLabel.textColor = [UIColor whiteColor];
titleLabel.textColor = theTitleLabelTextColor;
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.alpha = 1.0;
titleLabel.text = title;
@@ -341,11 +367,14 @@ static id data;
}
if (message != nil) {
NSString * messageLabelTextColor = styling[@"textColor"];
UIColor *theMessageLabelTextColor = messageLabelTextColor == nil ? [UIColor whiteColor] : [self colorFromHexString:messageLabelTextColor];
messageLabel = [[UILabel alloc] init];
messageLabel.numberOfLines = CSToastMaxMessageLines;
messageLabel.font = [UIFont systemFontOfSize:CSToastFontSize];
messageLabel.lineBreakMode = NSLineBreakByWordWrapping;
messageLabel.textColor = [UIColor whiteColor];
messageLabel.textColor = theMessageLabelTextColor;
messageLabel.backgroundColor = [UIColor clearColor];
messageLabel.alpha = 1.0;
messageLabel.text = message;
@@ -362,8 +391,8 @@ static id data;
if(titleLabel != nil) {
titleWidth = titleLabel.bounds.size.width;
titleHeight = titleLabel.bounds.size.height;
titleTop = CSToastVerticalPadding;
titleLeft = imageLeft + imageWidth + CSToastHorizontalPadding;
titleTop = theVerticalPadding;
titleLeft = imageLeft + imageWidth + theHorizontalPadding;
} else {
titleWidth = titleHeight = titleTop = titleLeft = 0.0;
}
@@ -374,8 +403,8 @@ static id data;
if(messageLabel != nil) {
messageWidth = messageLabel.bounds.size.width;
messageHeight = messageLabel.bounds.size.height;
messageLeft = imageLeft + imageWidth + CSToastHorizontalPadding;
messageTop = titleTop + titleHeight + CSToastVerticalPadding;
messageLeft = imageLeft + imageWidth + theHorizontalPadding;
messageTop = titleTop + titleHeight + theVerticalPadding;
} else {
messageWidth = messageHeight = messageLeft = messageTop = 0.0;
}
@@ -384,8 +413,8 @@ static id data;
CGFloat longerLeft = MAX(titleLeft, messageLeft);
// wrapper width uses the longerWidth or the image width, whatever is larger. same logic applies to the wrapper height
CGFloat wrapperWidth = MAX((imageWidth + (CSToastHorizontalPadding * 2)), (longerLeft + longerWidth + CSToastHorizontalPadding));
CGFloat wrapperHeight = MAX((messageTop + messageHeight + CSToastVerticalPadding), (imageHeight + (CSToastVerticalPadding * 2)));
CGFloat wrapperWidth = MAX((imageWidth + (theHorizontalPadding * 2)), (longerLeft + longerWidth + theHorizontalPadding));
CGFloat wrapperHeight = MAX((messageTop + messageHeight + theVerticalPadding), (imageHeight + (theVerticalPadding * 2)));
wrapperView.frame = CGRectMake(0.0, 0.0, wrapperWidth, wrapperHeight);
@@ -406,4 +435,13 @@ static id data;
return wrapperView;
}
// Assumes input like "#00FF00" (#RRGGBB)
- (UIColor*) colorFromHexString:(NSString*) hexString {
unsigned rgbValue = 0;
NSScanner *scanner = [NSScanner scannerWithString:hexString];
[scanner setScanLocation:1]; // bypass '#' character
[scanner scanHexInt:&rgbValue];
return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16) / 255.0 green:((rgbValue & 0xFF00) >> 8) / 255.0 blue:(rgbValue & 0xFF) / 255.0 alpha:1.0];
}
@end
+20 -22
View File
@@ -5,40 +5,38 @@
@implementation Toast
- (void)show:(CDVInvokedUrlCommand*)command {
NSDictionary* options = [command.arguments objectAtIndex:0];
NSString *message = [options objectForKey:@"message"];
NSString *duration = [options objectForKey:@"duration"];
NSString *position = [options objectForKey:@"position"];
NSDictionary *data = [options objectForKey:@"data"];
NSNumber *addPixelsY = [options objectForKey:@"addPixelsY"];
NSDictionary* options = [command argumentAtIndex:0];
NSString *message = options[@"message"];
NSString *duration = options[@"duration"];
NSString *position = options[@"position"];
NSDictionary *data = options[@"data"];
NSNumber *addPixelsY = options[@"addPixelsY"];
NSDictionary *styling = options[@"styling"];
if (![position isEqual: @"top"] && ![position isEqual: @"center"] && ![position isEqual: @"bottom"]) {
CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"invalid position. valid options are 'top', 'center' and 'bottom'"];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
return;
}
NSInteger durationInt;
if ([duration isEqual: @"short"]) {
durationInt = 2;
} else if ([duration isEqual: @"long"]) {
durationInt = 5;
NSTimeInterval durationMS;
if ([duration.lowercaseString isEqualToString: @"short"]) {
durationMS = 2000;
} else if ([duration.lowercaseString isEqualToString: @"long"]) {
durationMS = 4000;
} else {
CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"invalid duration. valid options are 'short' and 'long'"];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
return;
durationMS = [duration intValue];
}
[self.webView makeToast:message
duration:durationInt
duration:durationMS / 1000
position:position
addPixelsY:addPixelsY == nil ? 0 : [addPixelsY intValue]
data:data
styling:styling
commandDelegate:self.commandDelegate
callbackId:command.callbackId];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
pluginResult.keepCallback = [NSNumber numberWithBool:YES];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
@@ -46,7 +44,7 @@
- (void)hide:(CDVInvokedUrlCommand*)command {
[self.webView hideToast];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
+2 -2
View File
@@ -126,10 +126,10 @@ namespace WPCordovaClassLib.Cordova.Commands
return;
}
int hideDelay = 2800;
int hideDelay = 2500;
if ("long".Equals(duration))
{
hideDelay = 5500;
hideDelay = 5000;
}
else if (!"short".Equals(duration))
{
+4 -2
View File
@@ -11,12 +11,12 @@ Toast.prototype.optionsBuilder = function () {
return {
withMessage: function(m) {
message = m;
message = m.toString();
return this;
},
withDuration: function(d) {
duration = d;
duration = d.toString();
return this;
},
@@ -43,6 +43,8 @@ Toast.prototype.optionsBuilder = function () {
Toast.prototype.showWithOptions = function (options, successCallback, errorCallback) {
options.duration = (options.duration === undefined ? 'long' : options.duration.toString());
options.message = options.message.toString();
cordova.exec(successCallback, errorCallback, "Toast", "show", [options]);
};