PDA

Просмотр полной версии : textWidth в spark:Label


Genzo
27.12.2011, 18:55
Как узнать ширину текста в s:Label ? По аналогии с :

TextField.textWidth;

alatar
27.12.2011, 19:47
use namespace mx_internal;
...
trace(label.bounds);

Genzo
28.12.2011, 13:04
use namespace mx_internal;
trace( this.labelDisplay.bounds.toString() , this.labelDisplay.bounds.left , this.labelDisplay.bounds.size.toString() );

(x=0, y=0, w=NaN, h=NaN) 0 (x=NaN, y=NaN)

Объясню суть задачи, может кто сталкивался... :

При изменении стейта у ListItem на selected, хочу проверять длинну текста и анимировать движение текста по горизонтали (бегущая строка).




<s:State name="selected" enterState="selectedState(event)"/>

private function selectedState(event:FlexEvent):void
{
this.timer = new Timer(50);
this.timer.addEventListener(TimerEvent.TIMER , moveText);
this.timer.start();
}

private function moveText(e:TimerEvent):void
{
use namespace mx_internal;
if(this.moveLeft)
{
this.labelDisplay.left.selected--;
//if(Math.abs(this.labelDisplay.left) > (this.labelDisplay.width - this.labelDisplay.bounds.width
//Тут нужно знать ширину текста, по аналогии с TextField.textWidth
}

}

alatar
28.12.2011, 14:09
Вы в свойство left назначили объект со свойством selected?
bounds будет иметь корректные данные только после creationComplete labelDisplay, при условии что ему был назначен text.
Что из себя представляет ListItem? Приведите его код целиком.

Genzo
28.12.2011, 14:29
<s:List itemRenderer="***.view.render.Selection" />


<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import mx.core.mx_internal;
import mx.events.FlexEvent;

private var timer:Timer;
private var moveLeft:Boolean = true;

private function normalState(event:FlexEvent):void
{
if(this.timer != null)
{
this.timer.removeEventListener(TimerEvent.TIMER , moveText);
this.timer.stop();
this.timer = null;
this.labelDisplay.left = 8;
}
}

private function selectedState(event:FlexEvent):void
{
this.timer = new Timer(50);
this.timer.addEventListener(TimerEvent.TIMER , moveText);
this.timer.start();
}

private function moveText(e:TimerEvent):void
{
if(this.moveLeft)
{
//Тут нужно знать полную ширину текста
this.labelDisplay.left = String(Number(this.labelDisplay.left) - 4);
if(Math.abs(Number(this.labelDisplay.left)) > this.labelDisplay.parent.width){
this.moveLeft = false;
}
}else{
//Тут нужно знать полную ширину текста
this.labelDisplay.left = String(Number(this.labelDisplay.left) + 4);
if(Math.abs(Number(this.labelDisplay.left)) > this.labelDisplay.parent.width){
this.moveLeft = true;
}
}

}

]]>
</fx:Script>
<s:states>
<s:State name="normal" enterState="normalState(event)"/>
<s:State name="selected" enterState="selectedState(event)"/>
</s:states>


<s:Label id="labelDisplay" left.selected="8" right.selected="8" top.selected="8" bottom.selected="8" fontSize="36" verticalCenter="0"
left.normal="8" right.normal="8" top.normal="8" bottom.normal="8"
verticalCenter.normal="0" maxDisplayedLines="1"/>

</s:ItemRenderer>

alatar
28.12.2011, 15:06
<s:Label id="labelDisplay"
x="8"
x.normal="8"
verticalCenter="0"
fontSize="36"
maxDisplayedLines="1"/>
private function moveText(e:TimerEvent):void
{
if(this.moveLeft)
{
//Тут нужно знать полную ширину текста
labelDisplay.x -= 4;
if(labelDisplay.x < (width - labelDisplay.width - 8))
{
this.moveLeft = false;
}
}
else
{
//Тут нужно знать полную ширину текста
labelDisplay.x += 4;
if(labelDisplay.x > 8)
{
this.moveLeft = true;
}
}
}

Genzo
28.12.2011, 15:22
1 - this.labelDisplay.x не изменяемое свойство у ItemRenderer
2 - labelDisplay.width - не даст ширину текста, а даст ширину блока в который входит текст

может быть есть способ добраться до TextField'ов? или есть способ просчитать ширину текста зная параметры TextLineMetrics?

alatar
28.12.2011, 16:09
1. При чем тут ItemRenderer? x меняется у labelDisplay.
2. При таком подходе ширина labelDisplay будет равна ширине текста + внутренние отступы.

может быть есть способ добраться до TextField'ов?
В spark.controls.Label нет TextField'ов.

Genzo
28.12.2011, 16:24
1. При чем тут ItemRenderer? x меняется у labelDisplay.
ItemRenderer не даст изменить x у labelDisplay, т.к. фактически labelDisplay не находиться на сцене. Как я понял схему, компонент передает ItemRenderer'у параметры инициализации, тот создает labelDisplay и компонент его клонирует, потом передает другие параметры и т.д.
В spark.controls.Label нет TextField'ов.
ну всмысле TextBlock'и и т.п., вообщем что-то кроме String, но относящееся к тексту ;)

alatar
28.12.2011, 16:42
А попробовать не судьба? Заодно и ошибку бы у меня в формулах нашли, ибо писалось на коленке
private function moveText(e:TimerEvent):void
{
if(this.moveLeft)
{
labelDisplay.x -= 4;
if(labelDisplay.x < -labelDisplay.width)
{
this.moveLeft = false;
}
}
else
{
labelDisplay.x += 4;
if(labelDisplay.x > 4)
{
this.moveLeft = true;
}
}
}

Добавлено через 11 минут
ItemRenderer не даст изменить x у labelDisplay, т.к. фактически labelDisplay не находиться на сцене. Как я понял схему, компонент передает ItemRenderer'у параметры инициализации, тот создает labelDisplay и компонент его клонирует, потом передает другие параметры и т.д.
Вы заблуждаетесь.

Добавлено через 19 минут
или есть способ просчитать ширину текста зная параметры TextLineMetrics?
Я вам в первом же посте ответил как получить ширину текста. На момент вызова moveText bounds имеет корректные размеры.

Genzo
28.12.2011, 17:10
А попробовать не судьба? Заодно и ошибку бы у меня в формулах нашли, ибо писалось на коленке
Естественно попробовал, результат уже написал, не меняется x

Я вам в первом же посте ответил как получить ширину текста. На момент вызова moveText bounds имеет корректные размеры.
label.bounds - ширина самого label'а, при изменении left, он расширяется.

alatar
28.12.2011, 17:31
Естественно попробовал, результат уже написал, не меняется x
В mxml поменяйте параметры как описано тут http://www.flasher.ru/forum/showpost.php?p=1054085&postcount=6 с той кашей что вы написали, там вообще ничто меняться не будет.

Добавлено через 5 минут
label.bounds - ширина самого label'а, при изменении left, он расширяется.
use namespace mx_internal;
private function moveText(e:TimerEvent):void
{
if(this.moveLeft)
{
labelDisplay.x -= 4;
if(labelDisplay.x < -labelDisplay.width)
{
this.moveLeft = false;
}
}
else
{
labelDisplay.x += 4;
if(labelDisplay.x > 4)
{
this.moveLeft = true;
}
}

var g:Graphics = labelDisplay.graphics;
var b:Rectangle = labelDisplay.bounds;

g.lineStyle(1, 0xFF0000);
g.drawRect(b.x, b.y, b.width, b.height);
}

Genzo
28.12.2011, 17:51
Так работает, но в таком случае текст не становиться isTruncated.А из-за этого и весь сыр-бор, Копаюсь дальше...

alatar
28.12.2011, 17:55
А из-за этого и весь сыр-бор, Копаюсь дальше...
Увы, я не обладаю телепатическими способностями.

Добавлено через 16 минут
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
width="100%">
<fx:Script>
<![CDATA[
import mx.core.mx_internal;
import mx.events.FlexEvent;

private var timer:Timer;
private var moveLeft:Boolean=true;


private function normalState(event:FlexEvent):void
{
if (this.timer != null)
{
this.timer.removeEventListener(TimerEvent.TIMER, moveText);
this.timer.stop();
this.timer=null;
this.labelDisplay.left=8;
}
}

private function selectedState(event:FlexEvent):void
{
this.timer=new Timer(50);
this.timer.addEventListener(TimerEvent.TIMER, moveText);
this.timer.start();
}

use namespace mx_internal;

private function moveText(e:TimerEvent):void
{
var labelLeft:Number=Number(labelDisplay.left);
var bounds:Rectangle=labelDisplay.bounds;

if (this.moveLeft)
{
labelLeft-=4;
if (labelLeft < -bounds.width)
{
this.moveLeft=false;
}
}
else
{
labelLeft+=4;
if (labelLeft > 4)
{
this.moveLeft=true;
}
}

labelDisplay.left=labelLeft;
}
]]>
</fx:Script>
<s:states>
<s:State name="normal"
enterState="normalState(event)"/>
<s:State name="selected"
enterState="selectedState(event)"/>
</s:states>


<s:Label id="labelDisplay"
left="8"
left.normal="8"
right="8"
fontSize="36"
verticalCenter="0"
maxDisplayedLines="1"/>

</s:ItemRenderer>

Genzo
28.12.2011, 19:02
alatar спасибо за помощь, решил сделать так :
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
import mx.core.mx_internal;
import mx.events.FlexEvent;

private var timer:Timer;
private var moveLeft:Boolean = true;

private const PADDING:uint = 12;
private const SPEED:uint = 4;

private function normalState(event:FlexEvent):void
{
if(this.timer != null)
{
this.timer.removeEventListener(TimerEvent.TIMER , moveText);
this.timer.stop();
this.timer = null;
this.labelDisplay.setStyle("paddingLeft" , PADDING);
}
}

private function selectedState(event:FlexEvent):void
{
var textWidth:Number = this.labelDisplay.measuredWidth - this.labelDisplay.getStyle("paddingLeft");
if(textWidth > this.labelDisplay.width + PADDING);
this.timer = new Timer(50);
this.timer.addEventListener(TimerEvent.TIMER , moveText);
this.timer.start();
}

private function moveText(e:TimerEvent):void
{
var textWidth:Number = this.labelDisplay.measuredWidth - this.labelDisplay.getStyle("paddingLeft");
if(this.moveLeft)
{
this.labelDisplay.setStyle("paddingLeft" , this.labelDisplay.getStyle("paddingLeft") - SPEED);
if(Math.abs(this.labelDisplay.getStyle("paddingLeft")) > textWidth - this.labelDisplay.width + PADDING){
this.moveLeft = false;
}
}else{
this.labelDisplay.setStyle("paddingLeft" , this.labelDisplay.getStyle("paddingLeft") + SPEED);
if(this.labelDisplay.getStyle("paddingLeft") > PADDING){
this.moveLeft = true;
}
}

}

]]>
</fx:Script>
<s:states>
<s:State name="normal" enterState="normalState(event)"/>
<s:State name="selected" enterState="selectedState(event)"/>
</s:states>


<s:Label id="labelDisplay"
left="{PADDING}" right="8" top="8" bottom="8"
fontSize="36" verticalCenter="0" maxDisplayedLines="1"/>

</s:ItemRenderer>