Gesture Recognition - Manipulation Events do not fire - winrt-xaml

I am trying to implement gesture recognition using ManipulationStarted and ManipulationDelta events in Windows 10 mobile(UW) app. But there is one problem - they do not fire.
Most likely the problem is my overcomplicated xaml view (I have HorizontalyScrollable GridView inside ListView - and to enable vertical scroll it's all packed in ScrollViewer). But I tried adding those events to all containers and they still did not fire.
Does anyone have/know any sollution ? Below is my xaml page tree:
<ScrollViewer Grid.Row="2" x:Name="SubscribersView" ManipulationStarted="SubscribersView_ManipulationStarted" ManipulationDelta="SubscribersView_ManipulationDelta">
(......)
<ListView
Margin="0"
Grid.Row="0"
SelectionMode="None"
IsItemClickEnabled="True"
ScrollViewer.HorizontalScrollMode="Disabled"
ScrollViewer.VerticalScrollMode="Disabled"
HorizontalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
(......)
<GridView Grid.Row="1"
HorizontalAlignment="Stretch"
Margin="-10"
SelectionMode="None"
IsItemClickEnabled="True"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollMode="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Visible">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"></VirtualizingStackPanel>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

For the ScrollViewer you're trying to handle the manipulation events, set the ManipulationMode to All - or as need.
Read more:
https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.uielement.manipulationmode

I found a solution - I used ViewChanged of scrollviwer : below is solution
private void SubscribersView_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
var sv = sender as ScrollViewer;
var verticalOffset = sv.VerticalOffset;
var minVerticalOffset = sv.ExtentHeight - sv.ViewportHeight;
var maxVerticalOffset = sv.ScrollableHeight;
if (maxVerticalOffset < 0 || verticalOffset == maxVerticalOffset || minVerticalOffset <= 0 || verticalOffset <= 0)
{
//reached top or bottom
return;
}
if (verticalOffset > previousVerticalOffset)
{
//Scroll down
if (!popularHidden)
{
MainImageSlideOut.Begin();
popularHidden = true;
}
}
else
{
//Scroll up
if (popularHidden)
{
MainImageSlideIn.Begin();
popularHidden = false;
}
}
previousVerticalOffset = verticalOffset;
}

Related

Xamarin.Forms not centering layouts in android

I have 3 labels - I want to center the second label and to fill the other space with equal sizes for the first and third label.
Instead I see there is a consideration of the string when using the LayoutOption.FillANdExpand
here is my code:
class MainPage : ContentPage
{
public MainPage()
{
StackLayout a = new StackLayout();
a.Orientation = StackOrientation.Horizontal;
a.Spacing = 0;
a.Padding = new Thickness(0, 0, 0, 0);
a.HorizontalOptions = LayoutOptions.FillAndExpand;
Label l1 = new Label { Text = "1111", HorizontalOptions = LayoutOptions.FillAndExpand, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Red, };
Label l2 = new Label { Text = "2222222222222", HorizontalOptions = LayoutOptions.Center, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Gray };
Label l3 = new Label { Text = "333333333333", HorizontalOptions = LayoutOptions.FillAndExpand, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Red };
a.Children.Add(l1);
a.Children.Add(l2);
a.Children.Add(l3);
Content = a;
}
}
the result is this:
I want the 111 and the 33333... labels to have the same size and the 2222 label to be in the center of my page...
You could use Grid with 3 columns:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Text="1111" TextColor="White" BackgroundColor="Red" />
<Label Grid.Column="1" Text="2222222222222" TextColor="White" BackgroundColor="Gray" />
<Label Grid.Column="2" Text="33333" TextColor="White" BackgroundColor="Red" />
</Grid>
While Grid seems to work ok for that, it a little bit overhead. You can try this layout options:
Label l1 = new Label { Text = "1111", HorizontalOptions = LayoutOptions.StartAndExpand, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Red, };
Label l2 = new Label { Text = "2222222222222", HorizontalOptions = LayoutOptions.Center, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Gray };
Label l3 = new Label { Text = "333333333333", HorizontalOptions = LayoutOptions.EndAndExpand, HorizontalTextAlignment = TextAlignment.Center, BackgroundColor = Color.Red };

How to know which element is in focus in Universal windows application in windows 10

I have a xaml page in universal windows application in windows 10. This page contains two listboxes. Both listboxes have the same ItemsSource like
public class CategoryModel
{
public int CategoryId {get; set;}
public string CategoryName {get; set;}
public List<string> ImageURL {get; set;}
}
The top listbox creates Menu header at the top in Horizontal manner and the bottom listbox creates Menu data at the bottom of the menu header in Vertical manner.
The problem is that how to know which menu data element at the bottom is in focus, so that I can highlight the same element in Menu header?
<ListView x:Name="lvMenuBar" Grid.Column="1" FlowDirection="LeftToRight" ItemsSource="{Binding MenuCategories}" Width="Auto">
<ListView.ItemTemplate>
<DataTemplate>
<Button Click="MenuBarClick" HorizontalAlignment="Center" VerticalAlignment="Top" Tag="{Binding CategoryId}" Content="{Binding CategoryName}" Style="{StaticResource CustomButtonStyle}" FontFamily="Segoe UI" FontWeight="SemiBold" FontSize="18" Margin="0" Padding="20" BorderBrush="Red" BorderThickness="0" Opacity="0.5" Foreground="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
<ListView x:Name="lvMenuBar" Grid.Column="1" FlowDirection="LeftToRight" ItemsSource="{Binding MenuCategories}" Width="Auto">
<ListView.ItemTemplate>
<DataTemplate>
The above is my XAML
If I understand the question correctly, you want to select (or otherwise highlight) an item in the top list whenever that item is selected in the bottom list. You can do this with data binding, e.g.:
<ListView
Grid.Row="0"
ItemsSource="{Binding MenuCategories}"
Margin="8"
SelectedIndex="{Binding SelectedIndex, ElementName=verticalList, Mode=OneWay}"
>
Here the SelectedIndex property of the top list mirrors that of the bottom list.
In context, something like this:
<Page.Resources>
<Style x:Key="CustomButtonStyle" TargetType="Button" />
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListView
Grid.Row="0"
ItemsSource="{Binding MenuCategories}"
Margin="8"
SelectedIndex="{Binding SelectedIndex, ElementName=verticalList, Mode=OneWay}"
>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CategoryModel">
<Button
HorizontalAlignment="Center"
VerticalAlignment="Top"
Tag="{Binding CategoryId}"
Content="{Binding CategoryName}"
Style="{StaticResource CustomButtonStyle}"
FontFamily="Segoe UI"
FontWeight="SemiBold"
FontSize="18"
Margin="0"
Padding="20"
BorderBrush="Red"
BorderThickness="0"
Opacity="0.5"
Foreground="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
<ListView
x:Name="verticalList"
Grid.Row="1"
ItemsSource="{Binding MenuCategories}"
Margin="8"
IsItemClickEnabled="True"
SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:CategoryModel">
<Button
HorizontalAlignment="Center"
VerticalAlignment="Top"
Tag="{Binding CategoryId}"
Content="{Binding CategoryName}"
Style="{StaticResource CustomButtonStyle}"
FontFamily="Segoe UI"
FontWeight="SemiBold"
FontSize="18"
Margin="0"
Padding="20"
BorderBrush="Red"
BorderThickness="0"
Opacity="0.5"
Foreground="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>
Caveat: When you click one of your buttons, the ListView doesn't see that click; if you want that click to select an item, do it in code-behind.
Note also the IsItemClickEnabled property on the second (vertical) list.
EDIT: If I understand you correctly, you want the selection in the upper horizontal list to track scrolling in the lower vertical instead of selection. In that case you need to get hold of the built-in ScrollViewer and do something like this:
public MainPage()
{
InitializeComponent();
DataContext = this;
Loaded += (sender, args) =>
{
ScrollViewer scrollViewer = FindVisualChild<ScrollViewer>(verticalList);
if (scrollViewer != null)
{
scrollViewer.ViewChanged += (o, eventArgs) =>
{
int length = MenuCategories.Length;
double offset = scrollViewer.VerticalOffset;
double height = scrollViewer.ExtentHeight;
int index = (int)(length * offset / height);
horizontalList.SelectedIndex = index;
};
}
};
}
private static T FindVisualChild<T>(DependencyObject parent)
where T : DependencyObject
{
if (parent != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
T candidate = child as T;
if (candidate != null)
{
return candidate;
}
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return default(T);
}
You'll probably need to experiment with the calculations here; this is a bit experimental on my part.
This piece of code has solved much of my issue
private double _scrollExtentHeight;
private ScrollViewer _scrollViewer;
_scrollViewer = FindVisualChild<ScrollViewer>(lvMenuItems);
if (_scrollViewer != null)
{
_scrollViewer.ManipulationMode = ManipulationModes.TranslateY;
_scrollViewer.DirectManipulationCompleted += scrollViewerDirectManipulationCompleted;
_scrollExtentHeight = _scrollViewer.ExtentHeight;
}
private static T FindVisualChild<T>(DependencyObject parent)
where T : DependencyObject
{
if (parent != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
T candidate = child as T;
if (candidate != null)
{
return candidate;
}
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return default(T);
}
private void scrollViewerDirectManipulationCompleted(object sender, object e)
{
_menuVM.StartDispatcher();
if (_scrollViewer != null)
{
int length = _menuVM.Categories.Count;
double offset = _scrollViewer.VerticalOffset;
//Horizontal scroll viewer
List<Button> menuItems = GetAllMenuItemControl(lvMenuBar);
int currIndex = 0, index = 0;
//Categories height ratio contains the height ratio of each element for total height
for (; index < _menuVM.CategoriesHeightRatio.Count; index++)
{
if ((_menuVM.CategoriesHeightRatio[index - 1 > 0 ? index - 1 : 0] * _scrollExtentHeight) < offset && (_menuVM.CategoriesHeightRatio[index] * _scrollExtentHeight) >= offset)
{
currIndex = index;
}
else
{
menuItems[index].BorderThickness = new Thickness(0, 0, 0, 0);
menuItems[index].Opacity = 0.5;
}
}
menuItems[currIndex].BorderThickness = new Thickness(0, 0, 0, 2);
menuItems[currIndex].Opacity = 1;
var transform = lvMenuBar.TransformToVisual(menuItems[currIndex]);
Point absolutePoint = transform.TransformPoint(new Point(0, 0));
svMenuBar.ChangeView(Math.Abs(absolutePoint.X), null, null, false);
}
}
private List<Button> GetAllMenuItemControl(DependencyObject parent)
{
var _List = new List<Button>();
for (int index = 0; index < VisualTreeHelper.GetChildrenCount(parent); index++)
{
var _Child = VisualTreeHelper.GetChild(parent, index);
if (_Child is Button)
_List.Add(_Child as Button);
_List.AddRange(GetAllMenuItemControl(_Child));
}
return _List;
}

limit 4 items per page in a ListView in a universal app

I am trying to set 4 items per page in my ListView,I have in total 5 items,my code works fine,but I get always 5 items instead of 4 when I execute my code:
ObservableCollection<NvBarberry.Models.One_searchs> customers = new ObservableCollection<NvBarberry.Models.One_searchs>();
ObservableCollection<NvBarberry.Models.One_searchs> filtered = new ObservableCollection<NvBarberry.Models.One_searchs>();
int currentPageIndex = 0;
int itemPerPage = 4;
int totalPage = 0;
private void Page_Loaded(object sender, RoutedEventArgs e)
{
getLocalsList();
}
private void ShowCurrentPageIndex()
{
this.tbCurrentPage.Text = (currentPageIndex + 1).ToString();
if (Convert.ToInt32(tbCurrentPage.Text.ToString()) == totalPage)
{
this.tbNextPage.Text = "";
}
else
{
this.tbNextPage.Text = (currentPageIndex + 2).ToString();
}
NextBorder.Opacity = 0.5;
}
void Filter()
{
ObservableCollection<NvBarberry.Models.One_searchs> filtered = new ObservableCollection<NvBarberry.Models.One_searchs>();
foreach (NvBarberry.Models.One_searchs item in customers)
{
int index = customers.IndexOf(item);
if (index >= itemPerPage * currentPageIndex && index < itemPerPage * (currentPageIndex + 1))
{
filtered.Add(item);
}
}
this.listme.DataContext = filtered;
}
private void btnFirst_Click(object sender, RoutedEventArgs e)
{
// Display the first page
if (currentPageIndex != 0)
{
currentPageIndex = 0;
Filter();
}
ShowCurrentPageIndex();
}
private void btnPrev_Click(object sender, RoutedEventArgs e)
{
// Display previous page
if (currentPageIndex > 0)
{
currentPageIndex--;
Filter();
}
ShowCurrentPageIndex();
}
private void btnNext_Click(object sender, RoutedEventArgs e)
{
// Display next page
if (currentPageIndex < totalPage - 1)
{
currentPageIndex++;
Filter();
}
ShowCurrentPageIndex();
}
private void btnLast_Click(object sender, RoutedEventArgs e)
{
// Display the last page
if (currentPageIndex != totalPage - 1)
{
currentPageIndex = totalPage - 1;
Filter();
}
ShowCurrentPageIndex();
}
private async void getLocalsList()
{
try
{
string UriString2 = "MyWebService";
var http = new HttpClient();
http.MaxResponseContentBufferSize = Int32.MaxValue;
var response = await http.GetStringAsync(UriString2);
var rootObject1 = JsonConvert.DeserializeObject<Nv.Models.RootObject>(response);
listme.ItemsSource = rootObject1.one_searchs;
int itemcount = 5;
// Calculate the total pages
totalPage = itemcount / itemPerPage;
if (itemcount % itemPerPage != 0)
{
totalPage += 1;
}
Filter();
ShowCurrentPageIndex();
}
catch (Exception e)
{
e.Message.ToString();
}
and this is my xaml code:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="100"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<ListView x:Name="listme" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ID}"></TextBlock>
<TextBlock Text="{Binding Name}"></TextBlock>
<TextBlock Text="{Binding Age}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
<Grid Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal">
<Button Height="50" HorizontalAlignment="Left" Name="btnFirst"
VerticalAlignment="Bottom" Width="75" Click="btnFirst_Click" Background="Transparent">
<Button.Content>
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="25"/>
</Button.Content>
</Button>
<Button Height="50" HorizontalAlignment="Left" Name="btnPrev" Background="Transparent"
VerticalAlignment="Bottom" Click="btnPrev_Click">
<Button.Content>
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="25"/>
</Button.Content>
</Button>
<Border Name="CurrentBorder" Height="50" Width="50" Background="Purple">
<TextBlock Name="tbCurrentPage" Height="50" Width="50"></TextBlock>
</Border>
<Border Name="NextBorder" Height="50" Width="50" Background="Purple">
<TextBlock Name="tbNextPage" Height="50" Width="50"></TextBlock>
</Border>
<Button Height="50" Name="btnNext" Background="Transparent"
VerticalAlignment="Bottom" Click="btnNext_Click">
<Button.Content>
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="25"/>
</Button.Content>
</Button>
<Button Height="50" HorizontalAlignment="Right" Name="btnLast" Background="Transparent"
VerticalAlignment="Bottom" Click="btnLast_Click">
<Button.Content>
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="25"/>
</Button.Content>
</Button>
</StackPanel>
</Grid>
</Grid>
I have a problem in setting only 4 items per page instead of putting them all in one page in my ListView,which I get with my code,I have set the "itemPerPage" variable to 4 but I get always the same problem
so,please how can I correct my code to put only 4 items per page in my ListView
thanks fr help
Index is 0 base value not 1 and you are using >= in your if condition. just remove = and you will get 4 items on first page and 8 on second.
int index = customers.IndexOf(item);
if (index > itemPerPage * currentPageIndex && index < itemPerPage * (currentPageIndex + 1))
{
filtered.Add(item);
}
else { break; }//all items are added no need to traverse all the list.
Update
int index = 0;
foreach (NvBarberry.Models.One_searchs item in customers)
{
if (index > itemPerPage * currentPageIndex && index < itemPerPage * (currentPageIndex + 1))
{
filtered.Add(item);
} else {break; }
index++;
}
Update 2
private async void getLocalsList()
{
try
{
string UriString2 = "MyWebService";
var http = new HttpClient();
http.MaxResponseContentBufferSize = Int32.MaxValue;
var response = await http.GetStringAsync(UriString2);
var rootObject1 = JsonConvert.DeserializeObject<Nv.Models.RootObject>(response);
///No need, as data will be assigned filter mehtod listme.ItemsSource = rootObject1.one_searchs;
int itemcount = 5;
// Calculate the total pages
totalPage = itemcount / itemPerPage;
if (itemcount % itemPerPage != 0)
{
totalPage += 1;
}
currentPageIndex = 1
Filter();
ShowCurrentPageIndex();
}
catch (Exception e)
{
e.Message.ToString();
}

Trimming text to a given pixel width in SVG

I'm drawing text labels in SVG. I have a fixed width available (say 200px). When the text is too long, how can I trim it ?
The ideal solution would also add ellipsis (...) where the text is cut. But I can also live without it.
Using d3 library
a wrapper function for overflowing text:
function wrap() {
var self = d3.select(this),
textLength = self.node().getComputedTextLength(),
text = self.text();
while (textLength > (width - 2 * padding) && text.length > 0) {
text = text.slice(0, -1);
self.text(text + '...');
textLength = self.node().getComputedTextLength();
}
}
usage:
text.append('tspan').text(function(d) { return d.name; }).each(wrap);
One way to do this is to use a textPath element, since all characters that fall off the path will be clipped away automatically. See the text-path examples from the SVG testsuite.
Another way is to use CSS3 text-overflow on svg text elements, an example here. Opera 11 supports that, but you'll likely find that the other browsers support it only on html elements at this time.
You can also measure the text strings and insert the ellipsis yourself with script, I'd suggest using the getSubStringLength method on the text element, increasing the nchars parameter until you find a length that is suitable.
Implementing Erik's 3rd suggestion I came up with something like this:
//places textString in textObj, adds an ellipsis if text can't fit in width
function placeTextWithEllipsis(textObj,textString,width){
textObj.textContent=textString;
//ellipsis is needed
if (textObj.getSubStringLength(0,textString.length)>=width){
for (var x=textString.length-3;x>0;x-=3){
if (textObj.getSubStringLength(0,x)<=width){
textObj.textContent=textString.substring(0,x)+"...";
return;
}
}
textObj.textContent="..."; //can't place at all
}
}
Seems to do the trick :)
#user2846569 show me how to do it ( yes, using d3.js ). But, I have to make some little changes to work:
function wrap( d ) {
var self = d3.select(this),
textLength = self.node().getComputedTextLength(),
text = self.text();
while ( ( textLength > self.attr('width') )&& text.length > 0) {
text = text.slice(0, -1);
self.text(text + '...');
textLength = self.node().getComputedTextLength();
}
}
svg.append('text')
.append('tspan')
.text(function(d) { return d; })
.attr('width', 200 )
.each( wrap );
The linearGradient element can be used to produce a pure SVG solution. This example fades out the truncated text (no ellipsis):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<defs>
<linearGradient gradientUnits="userSpaceOnUse" x1="0" x2="200" y1="0" y2="0" id="truncateText">
<stop offset="90%" stop-opacity="1" />
<stop offset="100%" stop-opacity="0" />
</linearGradient>
<linearGradient id="truncateLegendText0" gradientTransform="translate(0)" xlink:href="#truncateText" />
<linearGradient id="truncateLegendText1" gradientTransform="translate(200)" xlink:href="#truncateText" />
</defs>
<text fill="url(#truncateLegendText0)" font-size="50" x="0" y="50">0123456789</text>
<text fill="url(#truncateLegendText1)" font-size="50" x="200" y="150">0123456789</text>
</svg>
(I had to use linear gradients to solve this because the SVG renderer I was using does not support the textPath solution.)
Try this one, I use this function in my chart library:
function textEllipsis(el, text, width) {
if (typeof el.getSubStringLength !== "undefined") {
el.textContent = text;
var len = text.length;
while (el.getSubStringLength(0, len--) > width) {}
el.textContent = text.slice(0, len) + "...";
} else if (typeof el.getComputedTextLength !== "undefined") {
while (el.getComputedTextLength() > width) {
text = text.slice(0,-1);
el.textContent = text + "...";
}
} else {
// the last fallback
while (el.getBBox().width > width) {
text = text.slice(0,-1);
// we need to update the textContent to update the boundary width
el.textContent = text + "...";
}
}
}
There is several variants using d3 and loops for search smaller text that fit. This can be achieved without loops and it work faster. textNode - d3 node.
clipText(textNode, maxWidth, postfix) {
const textWidth = textNode.getComputedTextLength();
if (textWidth > maxWidth) {
let text = textNode.textContent;
const newLength = Math.round(text.length * (1 - (textWidth - maxWidth) / textWidth));
text = text.substring(0, newLength);
textNode.textContent = text.trim() + postfix;
}
}
My approach was similar to OpherV's, but I tried doing this using JQuery
function getWidthOfText(text, fontSize, fontFamily) {
var span = $('<span></span>');
span.css({
'font-family': fontFamily,
'font-size' : fontSize
}).text(text);
$('body').append(span);
var w = span.width();
span.remove();
return w;
}
function getStringForSize(text, size, fontSize, fontFamily) {
var curSize = getWidthOfText(text, fontSize, fontFamily);
if(curSize > size)
{
var curText = text.substring(0,text.length-5) + '...';
return getStringForSize(curText, size, fontSize, fontFamily);
}
else
{
return text;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Now when calling getStringForSize('asdfasdfasdfasdfasdfasdf', 110, '13px','OpenSans-Light') you'll get "asdfasdfasdfasd..."

changing the location of a component in different states

Hello my good people of stackOverflow,
Recently, i was building a component where a certain dropDownList component with id = languageCombo, has to be relocated dynamically as the states change..here is the code for the two states: initial and chaingrp. i want the dropDownList component to change from one position X in the initial state to another position X = 500 in the tree_changeHandler function when the chaingrp state is called but the dropDownList component doesn't change. Could anyone point me to what the problem could be?
Thanks
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:components="components.*"
xmlns:searchComponents="searchComponents.*"
minHeight="500" minWidth="500">
<fx:Metadata>
[Event(name="SearchClick", type="eventClass.SelectedTableEvent")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import eventClass.SelectedTableEvent;
import mx.collections.ArrayCollection;
import mx.events.ListEvent;
import mx.events.TreeEvent;
import spark.events.IndexChangeEvent;
namespace simo="http://www.simo-project.org/simo";
[Bindable]
public var parentXmlCopy:XML;
[Bindable]
public var treeXml:XML;
[Bindable]
private var newXml:XML;
private var transferredname:String;
public var modelType:String;
public var selectedModelchainIndex:int;
public var selectedTaskIndex:int;
public function set variables(_xml:XML):void{
parentXmlCopy = _xml;
}
private function languageChange(event:Event):void{
trace("languageChange");
var cb:DropDownList=event.target as DropDownList;
var temp:Object=cb.selectedItem;
var chain:Array=[];
for (var i:int=0; i < cb.dataProvider.length; i++)
{
if(cb.dataProvider[i].label == temp.label)
{
chain.push(cb.dataProvider[i].locale);
resourceManager.localeChain=chain;
}
}
}
protected function tree_changeHandler(event:ListEvent):void
{
use namespace simo;
var selectedItem:XML;
transferredname = tree.selectedItem.localName();
switch (transferredname){
case "chain_group" : currentState = "chaingroup";
languageCombo.X = 500;
selectedItem = XML(tree.selectedItem);
trace(selectedItem);
this.chainGrpId.displayChainGrp(selectedItem);
break;
}
}
private function treeLabel(item:Object):String
{
return item.localName();
}
]]>
</fx:Script>
<s:states>
<s:State name="initial"/>
<s:State name="chaingroup"/>
</s:states>
<s:HGroup><!--overall outer Hgroup-->
<s:HGroup gap="8">
<s:HGroup gap="5">
<s:VGroup height="460" paddingLeft="10" paddingTop="5">
<s:HGroup gap="3">
<searchComponents:AutoComplete/>
<s:Button
id="searchBT"
height="24"
width="24"
skinClass="skins.searchBTskin"/>
</s:HGroup>
<s:List id="treeDP" height="120" width="180" labelField="#name"
change="treeDP_changeHandler(event)">
<s:dataProvider>
<s:XMLListCollection source="{parentXmlCopy.children()}" />
</s:dataProvider>
</s:List>
<s:Button id="delListBT" label="delList"/>
<s:HGroup gap="70">
<s:Button
id="backBT"
label="back"
height="24"
width="24"
/>
<s:Button
id="nextBT"
label="next"
height="24"
width="24"
/>
</s:HGroup>
<mx:Tree id="tree" dataProvider="{treeXml}" labelField="{treeXml.localName()}"
top="72" left="50" labelFunction="treeLabel"
maxHorizontalScrollPosition="20"
maxVerticalScrollPosition="10"
showRoot="true"
change="tree_changeHandler(event)"
height="225" width="180"/>
<s:Button id="delTreeBT" label="delTree"/>
</s:VGroup>
<s:Group includeIn="chaingroup/>
</s:HGroup>
</s:HGroup>
<s:HGroup paddingLeft="200" paddingTop="5"
x.modelOperation="-38" y.modelOperation="-22" width.modelOperation="737"
x.modelPrediction="-18" y.modelPrediction="-20">
<s:DropDownList id="languageCombo" width="150" change="languageChange(event)" includeIn="initial"
dataProvider="{new ArrayCollection([{locale:'fi_FI',label:'Suomi'}, {locale:'en_US', label:'English'}])}"
prompt="{resourceManager.getString('modelChainUI','lang')}"
x.chaingroup="900"
x.condition="900"
x.modelchain="900"
x.task="900"/>
</s:HGroup>
</s:HGroup><!--overall hgroup ends here!-->
<s:VGroup gap="5" paddingLeft="10"
x.chaingroup="144" y.chaingroup="-69" height.chaingroup="148">
<components:ChainGroup id="chainGrpId" includeIn="chaingroup"/>
</s:VGroup>
Your languageCombo is within HGroup. HGroup is a container with horizontal layout. Horizontal layout doesn't consider any x and y coordinates of children (because of it is horizontal layout).
Maybe it better to use simple Group (taking in mind your HGroup has only one child — so horizontal layout hasn't sense)?

Resources