In Appcelerator Titanium (iOS project) I have a TextField with height:50. The TextField contains much more text but the fact that its height is set to 50 lets me use the TextField as a preview of the remaining text: under the TextField I have a button and when I tap this button I want to show the entire text, so I would like to animate the TextField from its current height to Ti.UI.SIZE. Is this possible? How? I noticed some iOS properties (eg. anchorPoint) but I could not understand if they can be useful in my case.
You need to use TextArea instead of TextField if you want multiple lines and word wrapping.
I've added the TextArea to a View so I can animate it to both expand and shrink it.
You can try something like this..
// Create the text area for multiple lines and word wrapping.
var messageField = Ti.UI.createTextArea({
backgroundColor: 'transparent',
color: 'black',
height: Ti.UI.SIZE, // Set here the height to SIZE and the view's height to the required one, ex. 50
textAlign: 'left',
value: 'This text should be displayed in more than one line in a text area, but that behavior is not supported by a text field, again, This text should be displayed in more than one line in a text area, but that behavior is not supported by a text field.',
verticalAlign: Ti.UI.TEXT_VERTICAL_ALIGNMENT_TOP,
width: '90%',
font: { fontSize: 20 }
});
// Add the text area to a view to be able to animate it
var view = Titanium.UI.createView({
height: 50, // Required height
top: 250,
width: '90%',
borderColor: 'black',
borderRadius: 10,
borderWidth: 2,
});
view.add(messageField);
// Create animation object
var animation = Titanium.UI.createAnimation();
animation.duration = 1000; // Set the time of animation, 1000 --> 1 second
var button = Ti.UI.createButton({
title: "Show More",
font: { fontSize: 18 },
width: 100,
top: 200
});
var isExpanded = false;
button.addEventListener('click', function() { // Event listener for your button
if(isExpanded) {
isExpanded = false;
animation.height = 50; // Set the animation height to 50 to shrink the view
view.animate(animation); // Start animating the view to the required height
button.title = "Show More";
} else {
isExpanded = true;
animation.height = Ti.UI.SIZE; // Set the animation height to SIZE to make it expand
view.animate(animation); // Start animating the view to the required height
button.title = "Show Less";
}
});
var win = Ti.UI.createWindow({
backgroundColor: 'white'
});
win.add(button);
win.add(view);
win.open();
Related
is there a way to change color of the plotline label when the movement goes up and change it again in different font color when movement goes down?
yAxis.addPlotLine({
value: 66,
color: 'red',
width: 2,
id: 'plot-line-1',
label: {
text: 66,
align: 'right',
style: {
color: 'red',
fontWeight: 'bold'
},
y: newY,
x: 0
}
});
Here is a working file http://jsfiddle.net/kttfv1h3/9/
thanks for the help
You can add css style options to your plotLabel like to a simple object; docs
var prev_val = 0; // global
plotlabel = yAxis.plotLinesAndBands[0].label;
if(prev_val <= y) {
plotlabel.css({'color':'blue'});
} else {
plotlabel.css({'color':'green'});
}
prev_val = y;
My jsFiddle: http://jsfiddle.net/kttfv1h3/12/
After playing around a bit with the different settings I found a way to achieve what you are seeking.
By delcaring a new variable oldY
And doing the following in setInterval, the label color changes depending on if the value is increasing or decreasing:
if(y < oldY) {
yAxis.plotLinesAndBands["0"].label.element.style.fill = 'red';
} else {
yAxis.plotLinesAndBands["0"].label.element.style.fill = 'green';
}
oldY = y;
See jsfiddle for a working example based on the one you supplied.
I am trying to repurpose code to create a custom progress bar - but I am unable to understand how to make the final change.
The current implementation does the progress bar. What I would like is for the progress bar to update the text and then disappear on its own.
var win = Ti.UI.createWindow({
backgroundColor: 'white',
});
var label1 = Ti.UI.createLabel({
text: 'Working on it...',
textAlign:'center',
});
var track = Ti.UI.createView({
width: "60%", height: "20%",
borderRadius:40,
backgroundColor: 'red'
});
var progress = Ti.UI.createView({
borderRadius:40,
left: 0,
width: 5, height: "100%",
backgroundColor : "green"
});
track.add(progress);
track.add(label1);
win.add(track);
win.addEventListener('open', function () {
progress.animate({
width: "100%",
duration: 1000
});
});
win.open();
So when the final green progress is complete - I would like to
a. replace the "working on it" with "complete"
b. after 1000 ms - make the entire progress bar disappear.
No need to add Listener for complete event, you can add anonymous function in animate method itself
e.g
progress.animate({
width: "100%",
duration: 1000
},function(e){
label1.text = "complete";
win.remove(track);
});
You can use complete event listener of Animation object
// create the animation
var animation = Ti.UI.createAnimation({
width: "100%",
duration: 1000
});
animation.addEventListener("complete", function onAnimationComplete(e){
// YOUR CODE HERE
animation.removeEventListener("complete", onAnimationComplete);
});
progress.animate(animation);
More details Titanium.UI.Animation
I am developing on iOS 9.2 SDK & Titannium SDK v5.1.2.GA.
In my iPad app; there is a product tab page, which has a "Discount" button. When you click it, a Popover with a TextField and Picker is shown like this:
The above is created on the fly. (not using a controller + view).
This works as intended. I wanted to extend this a little further by recording the given discount to a product in alloy.js in a global array variable called Alloy.Globals.ProductDiscounts = []; (so it can be used later).
The way I "capture" the new discount price is by listening to the "hide" event on the picker. Then update the global array.
For debugging purpose, I added a console log to make sure it's getting recorded correctly and then in the Appcelerator Studio console window, I started see this endless output like this:
I had to kill the simulator to stop this weird constant output of nulls.
This is my code so far, any idea why the console window is spazzing out? Also, why isn't my global array isn't getting set? or is it getting set, but I missed the actual console.log entry?
// Subscribe to line discount button click event
lineDiscountButton.addEventListener('click', function(e)
{
// Stop further events
e.cancelBubble = true;
// Create popover
var discountPopover = Titanium.UI.iPad.createPopover({
arrowDirection: Titanium.UI.iPad.POPOVER_ARROW_DIRECTION_RIGHT,
orignalPrice: e.source.orignalPrice,
priceButton: e.source.priceButton
});
var discountPopoverView = Titanium.UI.createView({
width: 250,
height: 210
});
// Create discount popover view wrapper
var discountPopoverViewWrapper = Titanium.UI.createView({
top: 10,
left: 10,
right: 10,
bottom: 10,
layout: 'vertical'
});
discountPopoverViewWrapper.add(Titanium.UI.createLabel({
top: 0,
left: 0,
color: '#5C5C5C',
font: {
fontSize: 12
},
text: 'Enter a new Price'
}));
discountPopoverViewWrapper.add(Titanium.UI.createView({
top: 0,
height: 1,
backgroundColor: '#0088CE',
width: '100%'
}));
var discountPrice = Titanium.UI.createTextField({
top: 0,
width: '100%',
height: Titanium.UI.SIZE,
hintText: discountPopover.orignalPrice,
value: discountPopover.orignalPrice,
backgroundColor: '#FFFFFF',
font: {
fontSize: 18,
fontWeight: 'bold'
},
color: '#5C5C5C'
});
discountPopoverViewWrapper.add(discountPrice);
discountPopoverViewWrapper.add(Titanium.UI.createLabel({
top: 10,
left: 0,
color: '#5C5C5C',
font: {
fontSize: 12
},
text: 'Or Select a Discount Percent'
}));
discountPopoverViewWrapper.add(Titanium.UI.createView({
top: 0,
height: 1,
backgroundColor: '#0088CE',
width: '100%'
}));
var discountPercentPicker = Titanium.UI.createPicker({
top: 0,
width: Titanium.UI.FILL,
height: 112
});
var discountPercentValues = [];
for (var i = 0; i <= 100; i++) {
discountPercentValues.push(Titanium.UI.createPickerRow({
title: i +'%'
}));
}
discountPercentPicker.add(discountPercentValues);
discountPercentPicker.addEventListener('change', function(e) {
if (parseInt(e.rowIndex) === 0) {
discountPrice.value = discountPopover.orignalPrice;
} else {
discountPrice.value = (discountPopover.orignalPrice - (discountPopover.orignalPrice * (parseInt(e.rowIndex) / 100))).toFixed(2);
}
});
discountPopoverViewWrapper.add(discountPercentPicker);
// Add discount popover view wrapper to view
discountPopoverView.add(discountPopoverViewWrapper);
// Set popover content view
discountPopover.contentView = discountPopoverView;
// Subscribe to popover hide event
discountPopover.addEventListener('hide', function(e) {
e.cancelBubble = true;
Alloy.Globals.ProductDiscounts[discountPopover.priceButton.sku] = parseFloat(discountPrice.value).toFixed(2);
Alloy.Globals.LiveBasketCollection.executeQuery("UPDATE live_basket SET Price = "+ discountPrice.value +" WHERE Sku = '"+ discountPopover.priceButton.sku +"'");
discountPopover.priceButton.price = Alloy.Globals.DeviceDefaults.CurrencySymbol + discountPrice.value;
discountPopover.priceButton.title = (discountPopover.priceButton.basketQuantity > 0 ? discountPopover.priceButton.basketQuantity +' x ' : '') + discountPopover.priceButton.price;
Titanium.App.fireEvent('redrawBasket');
discountPopover = discountPopoverView = discountPrice = discountPercentPicker = discountPercentValues = null;
console.log(Alloy.Globals.ProductDiscounts);
});
// Show popover
discountPopover.show({
view: lineDiscountButton,
animated: true
});
});
Just as a Question... Why are you cancelling bubbling.
without more of the code base I can only try and make a suggestion.
1) addeventlistener.
lineDiscountButton.addEventListener('click', setupData);
2) setupData
Function setupData(e) {
lineDiscountButton.removeEventListener('click', setupData);
Your code from the inline function.
}
Basically remove the event listener once activated, so add and remove as required.
I don't want to teach you to suck eggs, but to remove an event listener, you have to use exactly the same parameters as adding it. Thus inline function on event listeners are not ideal, although they work separating the code out into its own function is preferable.
Next Alloy globals.... Not good practice. I am guessing you want to have the data only for the duration of the running of the app, and not for future use.
If you need it for future use, you can store the data in properties.
Hope this helps
T.
I have a problem with getting labels within a TableView to display correctly, and I hope someone can help.
Here is a screenshot of the problem:
The labels with the (...) behind them are cut off.
This problem does not occur when I set a fixed height to my rows, but since the text is of varying lengths, that's not a good solution for me.
I've tried the answers in this question, but to no avail.
Here is my code to generate the table:
var aSection = Ti.UI.createTableViewSection({
rows: [],
headerView: header
});
for (var p = 0; p < answers.length; p++){
var currentAnswer = answers[p];
var arow = Ti.UI.createTableViewRow({
selectedBackgroundColor:'#f5f5f5',
answID: currentAnswer['aId'],
map: currentAnswer['aMap'],
isSelected: false,
height: 'auto',
rightImage: '/images/icons/radio-unselected.png'
});
var atext = Ti.UI.createLabel({
font:{fontSize:gui.defaultFontSize+2, fontFamily: gui.defaultFont},
color: '#333',
text: currentAnswer['aText'],
left:10, top: 10, bottom: 10, right: 10,
width:'auto',
height: 'auto',
borderWidth: 0,
borderColor: "#000",
});
arow.add(atext);
aSection.add(arow);
}
var sections = [];
sections[0] = aSection;
var answView = Ti.UI.createTableView({
backgroundColor:'white',
data: sections,
bottom: 1,
minRowHeight: 40,
});
I'm really at a loss with this. Any pointers are appreciated.
If your text is too long then it overlaps the right side button but still you want to show full text then you should either set left & right or set width to Ti.UI.SIZE so If you want to overlaps right button then you should use Ti.UI.SIZE or not then you can set left & right
so in short, set width to Ti.UI.SIZE or set left and right property.
Use Ti.UI.SIZE for both height and width instead of auto, auto has been deprecated a long time ago. Something like this would help you
var aSection = Ti.UI.createTableViewSection({
rows: [],
headerView: header
});
for (var p = 0; p < answers.length; p++){
var currentAnswer = answers[p];
var arow = Ti.UI.createTableViewRow({
selectedBackgroundColor:'#f5f5f5',
answID: currentAnswer['aId'],
map: currentAnswer['aMap'],
isSelected: false,
height:Ti.UI.SIZE,
rightImage: '/images/icons/radio-unselected.png'
});
var atext = Ti.UI.createLabel({
font:{fontSize:gui.defaultFontSize+2, fontFamily: gui.defaultFont},
color: '#333',
text: currentAnswer['aText'],
left:10, right: 10,
width:Ti.UI.SIZE,
height:Ti.UI.SIZE,
borderWidth: 0,
borderColor: "#000",
});
arow.add(atext);
aSection.add(arow);
}
var sections = [];
sections[0] = aSection;
var answView = Ti.UI.createTableView({
backgroundColor:'white',
data: sections,
bottom: 1,
minRowHeight: 40,
});
Try using: minimumFontSize:'18sp'
Or some size that suits your display needs. This will shrink the font down to the minimum size to fit everything.
I have 4 objects in a view with a horizontal layout in this order:
label
slider
label
button
labels and button are set to Ti.UI.SIZE and slider is set to Ti.UI.FILL
I am basically making my own video controls so
currentTimeLabel, slider, totalTimeLabel, playPauseButton
My issue is when I set the slider to FILL it fills the parent (which it should do I suppose) and pushes the 2nd label and button to a new line.
I need all 4 items on the same line. I've tried turning horizontalWrap to false on the parent view, but that just makes it so I cannot see the remaining two items.
The reason I am not using static widths is I need this slider to adjust its width based off the phone being in portrait and landscape modes.
If I use SIZE instead of fill, the slider basically has 0 width.
My simplified code is below:
var win = Ti.UI.currentWindow;
var transportBg = Ti.UI.createView({
bottom:0,
height:50,
width:'100%',
backgroundColor:'#50000000'
});
win.add(transportBg);
var transportControls = Ti.UI.createView({
layout:'horizontal',
width:'100%'
});
transportBg.add(transportControls);
var currentTimeText = Ti.UI.createLabel({
left:25,
width:Ti.UI.SIZE,
height:Ti.UI.SIZE,
text: '0:00',
color:'#fff',
font: {
fontSize: 10
},
shadowColor: '#000',
shadowOffset: {x:0, y:1}
});
var transport = Titanium.UI.createSlider({
min:0,
max:100,
value:0,
width:Ti.UI.FILL,
backgroundColor:'red'
});
var totalTimeText = Ti.UI.createLabel({
width:Ti.UI.SIZE,
height:Ti.UI.SIZE,
text: '0:00',
textAlign: Ti.UI.TEXT_ALIGNMENT_RIGHT,
color:'#fff',
font: {
fontSize: 10
},
shadowColor: '#000',
shadowOffset: {x:0, y:1}
});
var playPauseBtn = Ti.UI.createButton({
backgroundImage:'/images/pause.png',
width:Ti.UI.SIZE,
height:Ti.UI.SIZE
});
transportControls.add(currentTimeText);
transportControls.add(transport);
transportControls.add(totalTimeText);
transportControls.add(playPauseBtn);
And a screen shot of the current layout
In your case horizontal layout isn't very helpful and best effects can be achieved with absolute layout and setting left, right properties. The only problem which you have is that you have to make sure how much space you have to leave on both sides of slider.
Here are changes to your code which I've made:
var transportControls = Ti.UI.createView();
Removed width and layout property
var transport = Titanium.UI.createSlider({
left: 50,
right: 70,
…
});
Removed width property and set left/right property.
var totalTimeText = Ti.UI.createLabel({
right: 40,
…
});
var playPauseBtn = Ti.UI.createButton({
right: 0,
…
});
Add right property.