Flex 3: Code-behind problem - flex3

I have some VBox with button. I want my button changes the label after clicking on it. I'm trying to use the code-behind practice but the instance of the button is always null. There is code:
package TestPackage
{
import mx.containers.VBox;
import mx.controls.Button;
public class ControlsBox extends VBox
{
[Bindable]
public var btnPlay : Button;
public function ControlsBox()
{
super();
}
override protected function childrenCreated():void
{
super.childrenCreated();
}
public function ChangeImage():void
{
btnPlay.label = "a";
}
}
}
Here is mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:controls="TestPackage.*">
<controls:ControlsBox id="ctrlVBox">
<mx:Button id="btnPlay" click="this.ctrlVBox.ChangeImage();" label="c"></mx:Button>
</controls:ControlsBox>
</mx:Application>
What am I doing wrong? And how to do that properly?
Thanks

I don't do this very often in flex, but I think you want something like this:
<controls:ControlsBox id="ctrlVBox">
<controls:btnPlay>
<mx:Button click="this.ctrlVBox.ChangeImage();" label="c"></mx:Button>
</controls:btnPlay>
</controls:ControlsBox>

Related

Styling background of TornadoFX ListView

Is it possible to style a ListView component so that none of the elements have a shaded background?
I.e not like this:
But instead have them all styled like the first, third, fifth item etc.
TIA
In the default stylesheet, modena.css the background color for ListCells is governed by the following lines of code:
.list-cell,
.tree-cell {
-fx-background: -fx-control-inner-background;
-fx-background-color: -fx-background;
-fx-text-fill: -fx-text-background-color;
}
/* ... */
.list-cell:odd {
-fx-background: -fx-control-inner-background-alt;
}
So to remove the alternative color for the odd-numbered cells (note that counting is zero-indexed, so the odd-numbered cells are the 2nd, 4th, etc in the list view), you just need to include the following in your external CSS file, to revert the color for the odd-numbered cells to the same as the even-numbered cells:
.list-cell:odd {
-fx-background: -fx-control-inner-background ;
}
If you need to apply this to one specific ListView, you can set an id on that ListView:
ListView myListView ;
// ...
myListView.setId("plain-list-view");
and then the CSS selector becomes
#plain-list-view .list-cell:odd {
-fx-background: -fx-control-inner-background ;
}
You need to create a custom ListCell with a non-null Background. Once you do this, the automatic colour handling of the ListView for selected rows won't work properly any more. So you'll have to handle that yourself. The selection action will invert the colour of the text to white, but that's all. So you need to set the background colour of the cell based on the "Selected" property of the ListCell. In Java it would look like this:
public class Sample1 extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new ListBackgroundWhite(), 300, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
}
public class ListBackgroundWhite extends ListView<String> {
public ListBackgroundWhite() {
super();
setCellFactory(listView -> new WhiteListCell());
setItems(FXCollections.observableArrayList("first line", "second line", "third line", "fourth line"));
}
static class WhiteListCell extends ListCell<String> {
WhiteListCell() {
Background unselectedBackground =
new Background(new BackgroundFill(Color.WHITESMOKE, CornerRadii.EMPTY, Insets.EMPTY));
Background selectedBackground = new Background(new BackgroundFill(Color.BROWN, CornerRadii.EMPTY,
Insets.EMPTY));
backgroundProperty().bind(Bindings.createObjectBinding(() -> isSelected() ? selectedBackground :
unselectedBackground, selectedProperty()));
}
#Override
public void updateItem(String item, boolean isEmpty) {
super.updateItem(item, isEmpty);
if (!isEmpty) {
setText(item);
} else {
setText(null);
}
}
}
}
Once you do this, the cell background is no longer transparent, and the stripe pattern of the ListView itself won't show through.
EDIT:
As pointed out, this IS heavy-handed, except that in most cases a ListView isn't going to be a simple Label with a string in it. It's going to have some sort of layout in the ListCell that is going to require that you create a custom ListCell in any event.
However, messing with the Background directly via a binding to the "Selected" property is clumsy. You can create a new StyleClass, and then just define the modified PseudoClasses in the css. Then add this new StyleClass to the custom ListCell, and then it will handle it automatically as it applies the "EVEN" and "ODD" pseudoclasses.
One thing I found was that since the new "odd" definition gets applied after all of the other definitions in the default Modena css, that the "SELECTED" pseudoclass for ODD lines is suppressed. This means that the odd and even lines look different when they are selected, so a duplicate "SELECTED" definition needed to be added to the new css after the "ODD" definition. Then everything works properly. So the new code looks like this:
The CSS:
.custom-list-cell:odd {
-fx-background: -fx-control-inner-background;
}
.custom-list-cell:selected {
-fx-background: -fx-selection-bar;
-fx-table-cell-border-color: derive(-fx-selection-bar, 20%);
}
The main, now loads the new stylesheet into the Scene:
public class Sample1 extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new ListBackgroundWhite(), 300, 200);
scene.getStylesheets().add(getClass().getResource("/css/samples.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
}
And then the only customization to the ListCell is to add the new StyleClass:
public class ListBackgroundWhite extends ListView<String> {
public ListBackgroundWhite() {
super();
setCellFactory(listView -> new WhiteListCell());
setItems(FXCollections.observableArrayList("first line", "second line", "third line", "fourth line"));
}
static class WhiteListCell extends ListCell<String> {
WhiteListCell() {
getStyleClass().add("custom-list-cell");
}
#Override
public void updateItem(String item, boolean isEmpty) {
super.updateItem(item, isEmpty);
if (!isEmpty) {
setText(item);
} else {
setText(null);
}
}
}
}
But if you really are just wanting to have a ListView with just simple labels in it, you can just have the cell factory add the StyleClass on to the standard TextFieldListCell:
public ListBackgroundWhite() {
super();
setCellFactory(listView -> {
ListCell<String> cell = new TextFieldListCell<>();
cell.getStyleClass().add("custom-list-cell");
return cell;
});
setItems(FXCollections.observableArrayList("first line", "second line", "third line", "fourth line"));
}

textView.setMovementMethod in Android data binding

I want to achieve clickable link in a textview. I am now migrating all my UI to Android data binding and was wondering how to achieve it.
textView.setMovementMethod.
Any suggestions?
Best,
SK
I found out a way to do it. here it is
Create a static method and add BindingAdapter annotation preferably in a separate class
#BindingAdapter("app:specialtext")
public static void setSpecialText(TextView textView, SpecialText specialText) {
SpannableString ss = new SpannableString(specialText.getText());
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
Log.d("tag", "onSpecialClick: ");
}
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(true);
}
};
ss.setSpan(clickableSpan, specialText.getStartIndex(), ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(ss);
}
In your binding layout file
<variable
name="specialText"
type="com.example.test.data.SpecialText" />
<TextView
android:id="#+id/st_textView"
app:specialtext="#{specialText}"/>
In your activity or fragment where you are using the layout
SpecialText specialText = new TCText();
specialText.setStartIndex(15);
specialText.setText(getActivity().getString(R.string.special_text));
binding.setSpecialText(tcText);
Let me know if you know any better way to do it. Thanks !

How to set TextColor Xamarin.Forms TableSection?

I am a fan of doing as much as possible in xaml, I have aTableView` with a TableSection.
<TableView Intent="Menu">
<TableRoot>
<TableSection Title="Test Section" TextColor="#FFFFFF">
<TextCell Text="Test Item" TextColor="#FFFFFF"/>
</TableSection>
</TableRoot>
</TableView>
For TextCell TextColor="#FFFFFF" seems to work, however whenever I use this attribute on a TableSection I get this:
An unhandled exception occurred.
Is it possible to change the color of the TableSection with xaml?
Custom Renderers! I have two blog posts on this here:
Android:Xamarin.Forms TableView Section Custom Header on Android
iOS: Xamarin.Forms TableView Section Custom Header on iOS
Basically, create a custom view that inherits TableView, then custom renderers that implement custom TableViewModelRenderer. From there you can override methods to get the header view for the section title.
Here's what that might look like for Android:
public class ColoredTableViewRenderer : TableViewRenderer
{
protected override TableViewModelRenderer GetModelRenderer(Android.Widget.ListView listView, TableView view)
{
return new CustomHeaderTableViewModelRenderer(Context, listView, view);
}
private class CustomHeaderTableViewModelRenderer : TableViewModelRenderer
{
private readonly ColoredTableView _coloredTableView;
public CustomHeaderTableViewModelRenderer(Context context, Android.Widget.ListView listView, TableView view) : base(context, listView, view)
{
_coloredTableView = view as ColoredTableView;
}
public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent)
{
var view = base.GetView(position, convertView, parent);
var element = GetCellForPosition(position);
// section header will be a TextCell
if (element.GetType() == typeof(TextCell))
{
try
{
// Get the textView of the actual layout
var textView = ((((view as LinearLayout).GetChildAt(0) as LinearLayout).GetChildAt(1) as LinearLayout).GetChildAt(0) as TextView);
// get the divider below the header
var divider = (view as LinearLayout).GetChildAt(1);
// Set the color
textView.SetTextColor(_coloredTableView.GroupHeaderColor.ToAndroid());
textView.TextAlignment = Android.Views.TextAlignment.Center;
textView.Gravity = GravityFlags.CenterHorizontal;
divider.SetBackgroundColor(_coloredTableView.GroupHeaderColor.ToAndroid());
}
catch (Exception) { }
}
return view;
}
}
}
And the on iOS:
public class ColoredTableViewRenderer : TableViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
{
base.OnElementChanged(e);
if (Control == null)
return;
var coloredTableView = Element as ColoredTableView;
tableView.WeakDelegate = new CustomHeaderTableModelRenderer(coloredTableView);
}
private class CustomHeaderTableModelRenderer : UnEvenTableViewModelRenderer
{
private readonly ColoredTableView _coloredTableView;
public CustomHeaderTableModelRenderer(TableView model) : base(model)
{
_coloredTableView = model as ColoredTableView;
}
public override UIView GetViewForHeader(UITableView tableView, nint section)
{
return new UILabel()
{
Text = TitleForHeader(tableView, section),
TextColor = _coloredTableView.GroupHeaderColor.ToUIColor(),
TextAlignment = UITextAlignment.Center
};
}
}
}
According to the official documentation for TableSection you are out of luck. I'm afraid you would have to write a custom renderer for a subclass of the TableSection class and expose an extra property of type Xamarin.Forms.Color. Then you would be able to set the color from XAML.
You can set this color in the base theme (may apply to other widgets too)
In /Resources/values/styles.xml
<style name="MainTheme.Base" parent="Theme.AppCompat.Light">
<item name="colorAccent">#434857</item>
For Individual Section Titles, the TextColor property now seems to work correctly:
<TableView Intent="Settings">
<TableRoot>
<TableSection Title="App Settings" TextColor="Red">

"Hello World" with ReactiveUI, Xamarin Forms and XAML locking up

I'm trying to do a hello world with Reactive UI and Xamarin Forms.
I have created a ViewModel (based on ReactiveObject), a custom page (based on ReactiveContentPage) and some XAML markup.
The page has an entry and a Label, bound together. When I run it (on iOS and Android), it appears to work for the first few characters typed, then locks up. The console gives a 'too much is happening on the main thread' warning.
What am I missing?
The project is here.
The Model
namespace XamarinFormsReactiveUIExample
{
public class MyPageModel : ReactiveObject
{
private string _userName = "";
public string UserName {
get { return _userName; }
set { this.RaiseAndSetIfChanged (ref _userName, value); }
}
}
}
The Page
namespace XamarinFormsReactiveUIExample
{
public partial class MyPage : ReactiveContentPage<MyPageModel>
{
public MyPage ()
{
InitializeComponent ();
}
}
}
The XAML
<?xml version="1.0" encoding="UTF-8"?>
<reactive:ReactiveContentPage
x:TypeArguments="local:MyPageModel"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinFormsReactiveUIExample.MyPage"
xmlns:local="clr-namespace:XamarinFormsReactiveUIExample;assembly=XamarinFormsReactiveUIExample"
xmlns:reactive="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms">
<reactive:ReactiveContentPage.BindingContext>
<local:MyPageModel />
</reactive:ReactiveContentPage.BindingContext>
<reactive:ReactiveContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="0, 150, 0, 0" />
</reactive:ReactiveContentPage.Padding>
<reactive:ReactiveContentPage.Content>
<StackLayout>
<Entry Text = "{Binding UserName}"></Entry>
<Label Text = "{Binding UserName}"></Label>
</StackLayout>
</reactive:ReactiveContentPage.Content>
</reactive:ReactiveContentPage>
I don't see how this could be anything but a Xamarin bug, ReactiveUI isn't doing anything here. Anyways, you can always try to write these bindings the RxUI way:
<Entry x:Name="userNameEntry" />
<Label x:Name="userNameLabel" />
Then, in the constructor:
public MyPage ()
{
InitializeComponent();
this.ViewModel = new MyPageModel();
this.Bind(ViewModel, vm => vm.UserName, v => v.userNameEntry.Text);
this.OneWayBind(ViewModel, vm => vm.UserName, v => v.userNameLabel.Text);
}
The only thing I saw missing was the ViewModel was never instantiated, and the Binding Context was never set. I can't see what your old code did before you changed it to the new style. Personally, I try to avoid using code behind as much as possible as well. So you should be able to modify your constructor to something like,
public MyPage ()
{
InitializeComponent();
this.ViewModel = new MyPageModel();
this.BindingContext = ViewModel;
}
And revert to using your XAML binding.

Flex : stopPropagation of the event Keyboard.ENTER of a colorpicker

I have a WindowedApplication with a listener on keyboardEvent (on the ENTER key), but when the user choose to use the colorpicker and type an hexadecimal code then hit ENTER the event is propaged to my WindowedApplication too.
I have to stop the propagation.
Any hint or snippet ?
thanks
P.
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
keyDown="appHandler(event)">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
private function appHandler(event:KeyboardEvent):void
{
trace('A key has been pressed inside the app');
}
private function cpHandler(event:KeyboardEvent):void
{
trace('A key has been pressed inside the color picker');
event.stopPropagation();
}
]]>
</fx:Script>
<mx:ColorPicker x="159" y="137" id="cp" keyDown="cpHandler(event)"/>
<s:TextInput x="233" y="137"/>
</s:WindowedApplication>
This is part of the code of the TitleWindow, where cp is the ColorPicker.
...
public function init():void { cp.addEventListener(ColorPickerEvent.ENTER,handler);
}
public function handler(e:ColorPickerEvent):void {
e.stopImmediatePropagation();
}
public function changeColor(e:ColorPickerEvent):void {
Application.application.couleur = cp.selectedColor;
PopUpManager.removePopUp(this);
}
...
And this is from my main mxml :
...
employeeList.addEventListener(KeyboardEvent.KEY_UP, enterListener);
...
private function enterListener(e:KeyboardEvent):void {
if(e.keyCode == Keyboard.ENTER) {
if(employeeList.selectedItem) {
showDetail(employeeList.selectedItem as Employee);
}
}
}