floattext of a TextField overlaps with initial text content instead of floating up - gluon

I am using the com.gluonhq.charm.glisten.control.TextField class with a floattext, here is the snippet from FXML:
<TextField fx:id="email" floatText="E-Mail" layoutX="50.0" layoutY="357.0">
<opaqueInsets>
<Insets />
</opaqueInsets>
</TextField>
When the field is initially empty, everything works as expected: The floattext "E-Mail" floats up as soon as I click on the TextField. However, when I load already existing data into the TextFiled:
baseView.showingProperty().addListener((_obs, _oldValue, _newValue) -> {
if (_newValue) {
final String _email ="myemail";
Platform.runLater(new Runnable() {
#Override
public void run() {
email.setText(_email);
}
});
}
});
then the float text stays inside the edit area, overlapping with the text "myemail" already set. How can I make the float text initially appear already floated up, a state as if I had entered the text now?
This may not be a bug, but rather a misunderstanding from my side about how to use this feature.

Related

What is the property in control to be set to get the value from AppResult.Text in Xamarin.UITest?

I am trying to create custom control in Xamarin.Forms which has the unique id for automation. So, i have set the android renderer's contentDescription property. So, i can get the AppResult.Label property to identify the control. But, my requirements is that how to get the control's text property? What property i have to set in control level with the corresponding text to get it in AppResult.Text property.
[Test]
[Description("SampleTest")]
public void WelcomeTextIsDisplayed()
{
App.Repl();
AppResult[] results = App.WaitForElement("myControl");
Assert.IsTrue(results[0].Text == "My Control Text", results[0].Text + "\n" + results[0].Description + "\n" + results[0].Id + "\n" + results[0].Label);
}
For more information, I have prepared the simple example to explain better about my case. Here, i have derived my custom control from Grid and i introduced the Text property. When i try to view the element using Repl() method, it does not show the Text property but it shows the text properties for Label & Entry controls.
<StackLayout >
<Label Text="Hello, Custom Renderer!" />
<local:MyEntry Text="In Shared Code" AutomationId="myEntry" />
<local1:CustomView Text="Sample" BackgroundColor="Red" HeightRequest="500" AutomationId="customControl" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/>
</StackLayout>
public class CustomView : Grid
{
public CustomView()
{
}
public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(string),string.Empty);
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
Result while calling App.Repl() ,
I'm not sure how different Xamarin.Forms are to Xamarin.Android (which is mostly what my experience is in.)
What happens if you try
app.Query(c => c.Id("NoResourceEntry-2").Property("Text")).SingleOrDefault();
or some variation of the above? Can you then do something with this? I Hope this helps or points you in the right direction.
Try to use with index position like this:
app.Query(c=>c.Id("NoResourceEntry-2"))[0].Text
similarly you can use class for same:
app.Query(c=>c.Class("LabelRenderer"))[0].Text
Query for Class("LabelRenderer") gave 2 results. So in above example, you can see it gave you 2 results but you have to use index for particular result.

How to higlight button color when hover the mouse after a click?

I'm doing a piano application thought to be played on mobile devices (Android). All the piano keys are UI buttons that have the "property" pressed color to a grey one in order to properly indicate when a piano key is emiting sound.
My current problem is that when I first click on a key and after that I drag the mouse over the following keys, only the first one that I clicked is getting the change of color (the idea is that the change of color duration finishes when other key starts sound and then the new key where I pass the mouse-finger gets the grey color).
I also tryied setting the higlighted color property to the same color as the pressed color with the Navigation parameter to none (if it's set to automatic it happens some kind of bug that the color is getting "stuck" until I make sound another key), but the result it's still the same.
EDIT:
I update the issue with some progress thath I made:
I'm trying to change the pressed color with a script thanks to the events Pointer enter and exit (both events are placed on a Event trigger in every button).
Code:
public class ChangeKeyColor : MonoBehaviour{
public Button button;
void Start()
{
}
void Update()
{
}
public void EnterKey () {
Debug.Log("Enter the key");
ColorBlock colors = button.colors;
colors.normalColor = new Color(179, 179, 179, 255);
//colors.highlightedColor = new Color32(179, 179, 179, 255);
button.colors = colors;
}
public void ExitKey()
{
Debug.Log("Exits the key");
ColorBlock colors = button.colors;
colors.normalColor = Color.white;
//colors.highlightedColor = new Color32(255, 255, 255, 255);
//colors.pressedColor = Color.white;
button.colors = colors;
}
}
The only improvement that I obtained is that now when I'm dragging the mouse (maintaning it) the first button returns to white color, but I think that this is happening because now I only setted to gray color the pressed color option...
Does anyone know why the pressed color change that I'm making in the script isn't happening? When I drag the mouse to another key isn't considered as a pressed button?
Regards!
I'm not sure if you are still looking for the answer, but I finally had some time to try it myself.
What I did is changing color and debug-logging transform's name instead of playing sound.
My code for Images/Buttons (attached to each Image, I didn't use Button components):
using UnityEngine;
using UnityEngine.UI;
public class ChangeColor : MonoBehaviour {
public Color activeColor, notActiveColor;
private Image thisImage;
void Awake () {
thisImage = GetComponent<Image>();
}
public void OnPointerClick()
{
Activate();
}
public void OnPointerEnterAndDown()
{
if (Input.GetKey(KeyCode.Mouse0))
{
Activate();
}
}
public void OnPointerExit()
{
thisImage.color = notActiveColor;
}
private void Activate()
{
Debug.Log(transform.name);
thisImage.color = activeColor;
}
}
EventTrigger settings:
And this is what it looks like in the end:
(This should be a comment, but it's a little long, so reply me and I'll update the answer)
I don't know why are you having this problem, I do the simple test creating 2 UI Buttons and setting the highlighted color to red, and the pressed to blue.
By default (there's no script attached to anything) the behaviour is the follow:
1.If I press (and mantain) the click on a button, that button is blue, when I release the "pression", the button keeps red.
2.While this first button is red, if I drag the mouse over the second button, this will be also red.
3.If now I press on the second button, the first behaviour applies to the second button, and the first one will be white again.
This is the following behaviour that you want, according to what I understood.
So, if this is not the desired behaviour, tell us more about what you want.

Label not centered after data change in Xamarin Forms

In my Xamarin Forms application I have Label:
<Label Text="{Binding Number}" HorizontalTextAlignment ="Center">
In ViewModel:
private int _number;
public int Number
{
get { return _number; }
set { SetProperty(ref _number, value); }
}
When message is received, I update number:
MessagingCenter.Subscribe<EmptyMessage>(this, "NUMBER_CHANGED", OnNumberChanged);
private async void OnNumberChanged(EmptyMessage emptyMessage)
{
Number = ReadNumberFromDB();
}
All of this is on MainPage. When "NUMBER_CHANGED" message is triggered from MainPage, Number is updated on UI and label containing Number is properly centered.
From MainPage, one can PushAsync SecondPage. From SecondPage "NUMBER_CHANGED" can also be triggered. After triggering it and returning to MainPage, Number is updated, label containing it has proper value but instead of being centered it is left aligned.
Is this Xamarin UI bug? Is there a workaround for this? I need somehow to tell label to refresh it's position. I want label to always be centered. I don't know why it is left aligned after refreshing it's content.
HorizontalTextAlignment and VerticalTextAlignment, not working after a data change is a known bug. Bug 55359 details this for a TabbedPage, but it occurs in many places, such as Bug 49311.
The workaround is to use HorizontalOptions or VerticalOptions for the moment.
I ran into this problem recently. I simply made a constant variable to track what page needed to be updated OnResume and just reassigned my bindings accordingly.

Change Label Value on button click in Xamarin MVVM

I'm facing an issue in Xamarin forms Mvvm. I have 2 different layouts say Layout1 and Layout2 which are bounded with a common ViewModel. Layout1 contains multiple Labels which I'm generating dynamically using for loop in xaml.cs file and bind each Label'sTextProperty using SetBinding. Layout2 contain a button.
Now I want to change Text of a particular Label when button clicked.
Layout1.xaml
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Layout1">
<StackLayout x:Name="ParentStack">
// dynamic Labels to be added here..
</StackLayout>
</StackLayout>
Layout1.xaml.cs
public partial class Layout1: StackLayout
{
public Label dummyLabel;
public Layout1()
{
InitializeComponent();
for (int i = 0; i < 3; i++)
{
dummyLabel= new Label
{
Text = " ",
};
dummyLabel.SetBinding (Label.TextProperty,"PhaseValue");
parentRowCells.Children.Add(dummyLabel);
var tapGestureRecognizer_1 = new TapGestureRecognizer();
tapGestureRecognizer_1.SetBinding(TapGestureRecognizer.CommandProperty,"LabelClicked");
tapGestureRecognizer_1.CommandParameter = dummyLabel;
dummyLabel.GestureRecognizers.Add(tapGestureRecognizer_1);
}
}
}
Layout2.Xaml
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Layout2">
<StackLayout x:Name="ParentStack">
<Button Command={Binding ButtonClickedCommand} Text="Click Me" />
</StackLayout>
</StackLayout>
ViewModel.cs
class ViewModel
{
public Label label = new Label();
public string textstring = "new text string";
ICommand _labelClicked;
public ICommand LabelClicked
{
get
{
this._labelClicked= this._labelClicked?? new Command(s =>
{
label = s as Label;
label.Text = "new text"; //this change the text of particular label when clicked but i need it from button clicked event from another layout.
// here I'm getting the instance of label which i clicked on label.
});
return this._labelClicked;
}
}
public ICommand ButtonClickedCommand{ protected set; get; }
public ViewModel()
{
this.ButtonClickCommand = new Command<Button>((key) =>
{
//here I want to change the value of label when button command is clicked.
aa.Text = "this is not changing the text";
});
}
}
Any help in this or do I need to follow some other pattern..??
My first thought would be to add each Label that you add to a List<Label> somewhere that you can access from both layouts... your View Model would seem like the logical place. Then when you click your button, you can find the particular Label whose text you want to change and change it. You will likely then have to reload your list.
However I think that a better way would be to use a ListView instead of a StackLayout. Then you can have an ItemTemplate for the ListView that includes one Label. You can then set up an ObservableCollection<T> of objects to use as the ListView.ItemsSource. You would want to make some custom object that has a Text property, or whatever you want to call the property that will hold the text for the Labels. It is better to use an object for the T in ObservableCollection<T> rather than using ObservableCollection<string> because changes to a string type will not be reflected in the ListView item, but changes to a property of an object (assuming of course that you make it a Bindable Property) will be reflected in those controls that are bound to that property. So in a nutshell, something like (in your ViewModel):
// Class level variable
ObservableCollection<CustomType> dummyLabelContents;
// then either in the ViewModel constructor or somewhere else:
dummyLabelContents = new ObservableCollection<CustomType>();
CustomType dummyText;
for (int i = 0; i < 3; i++)
{
dummyText = new CustomType
{
Text = " ",
};
}
dummyLabelContents.Add(dummyText);
And your CustomType would just be a simple class with only a BindableProperty called Text.
Set up like this, you can assign your ListView.ItemsSource to be the dummyLabelContents ObservableCollection and then whenever you add an item to the ObservableCollection, the ListView will update automatically. Also, since using a custom type with a bindable text property in the ObservableCollection, when that text property is changed the item in the ListView should also update accordingly.

JavaFX: Focusing textfield programmatically

I wrote an application with JavaFX which will only be usable with keyboard's arrows.
So I prevented MouseEvent on Scene's stage, and I "listen" to KeyEvents.
I also switched off focusability of all nodes :
for(Node n : children) {
n.setFocusTraversable(false);
Now I have some textfields, checkboxes, and buttons.
I would like to change the state of my input controls (textfield, checkbox,..) programatically: for example I would like to enter the textfield to edit the content programatically.
So my question is: how to enter in a non-focus-traversable textfield?
Because textfield.requestFocus(); doesn't work anymore since I set false to focustraversable property of my textfield.
Thanks
By
n.setFocusTraversable(false);
the node is made non-focus-traversable instead of non-focusable. It can still be focused for example by mouse or programmatically. Since you prevented mouse events, here the other option:
Platform.runLater(new Runnable() {
#Override
public void run() {
textfield.requestFocus();
}
});
Scene scene = new Scene(root);
EDIT: as per comment,
The javadoc of requestFocus states:
... To be eligible to receive the focus, the node must be part of a scene,
it and all of its ancestors must be visible, and it must not be
disabled. ...
So this method should be called after construction of scene graph as follow:
Scene scene = new Scene(root);
textfield.requestFocus();
However, Platform.runLater in the above will run at the end, after the main method start(), which ensures the call of requestFocus will be after scene graph cosntruction.
There maybe other reasons depending on the requestFocus implementation code.
set the .requestFocus(); on initialize method to fire on .fxml file loading controller
#Override
public void initialize(URL url, ResourceBundle rb) {
/* the field defined on .fxml document
#FXML
private TextField txtYear;
*/
txtYear.requestFocus();
}

Resources