how to set horizontal scroll to horizontal field manager - user-interface

The following snippet contains a horizontal field manager to which five buttons are added.
1. I am unable to set horizontal scroll to the horizontal field manager because of which I am not able to access button 4 and button 5.
2. Usually we set horizontal scroll in the following manner
horizontalFieldManager =
new HorizontalFieldManager(USE_ALL_WIDTH|HorizontalFieldManager.FIELD_LEFT|HORIZONTAL_SCROLL);
but since I have added the buttons in the constructor of the horizontal field manager I am unable to use this.
3. I found this property : horizontalFieldManager.setHorizontalScroll(position);
which contains the Parameter:position where position is supposed to be the new horizontal scroll position. I tried passing the x-coordinate of the horizontal field manager but it's not working. What should i pass as the position parameter?
HorizontalFieldManager container = new HorizontalFieldManager()
{
protected void sublayout(int maxWidth, int maxHeight)
{
Field field = null;
int x = 0;
int y = 0;
int maxFieldHeight = 0;
for (int i = 0; i < getFieldCount(); i++)
{
field = getField(i);
layoutChild(field, maxWidth, maxHeight);
setPositionChild(field, x,y);
x+=field.getWidth();
if(i==0)
{
maxFieldHeight = field.getHeight(); // height set of the first button since all components have the same height
}
}
setExtent(Display.getWidth(), maxFieldHeight);
}
};
ButtonField button1 = new ButtonField("Button1");
ButtonField button2 = new ButtonField("Button2");
ButtonField button3 = new ButtonField("Button3");
ButtonField button4 = new ButtonField("Button4");
ButtonField button5 = new ButtonField("Button5");
container.add(button1);
container.add(button2);
container.add(button3);
container.add(button4);
container.add(button5);
add(container);

HorizontalFieldManager Constructor
If you simply change the way you call the HorizontalFieldManager constructor, from this:
HorizontalFieldManager container = new HorizontalFieldManager() {
protected void sublayout(int maxWidth, int maxHeight) {
to this:
HorizontalFieldManager container =
new HorizontalFieldManager(Manager.HORIZONTAL_SCROLL | Manager.HORIZONTAL_SCROLLBAR) {
protected void sublayout(int maxWidth, int maxHeight) {
then, you'll get the ability to scroll horizontally, and reach all five buttons.
sublayout()
In your sublayout() method, you appear to be laying out your fields just as HorizontalFieldManager would normally do. So, I don't think there's any point in adding that code. Simply do this:
HorizontalFieldManager container =
new HorizontalFieldManager(Manager.HORIZONTAL_SCROLL | Manager.HORIZONTAL_SCROLLBAR);
ButtonField button1 = new ButtonField("Button1");
/* the rest of your code is the same */
If you later want to control spacing between the buttons, do it with margins:
ButtonField button1 = new ButtonField("Button1");
button1.setMargin(10, 10, 10, 10);
ButtonField button2 = new ButtonField("Button2");
button2.setMargin(10, 10, 10, 10);
In general, it's usually not a good idea to use a HorizontalFieldManager, or a VerticalFieldManager and also override sublayout(). If you really want custom behavior there, you should probably just extend Manager directly with a subclass of your own.

Related

Can't Trigger MouseEntered on NSButton in Xamarin.Mac

I'm trying to programmatically add a MouseEntered event to a custom NSButton class, and I can't seem to get it to fire. I'm writing a Mac OS application in Visual Studio for Mac, using Xamarin.Mac. I need to add the event in code because I'm creating the buttons dynamically.
Here's my ViewController where these buttons are being created. They're instantiated in the DrawHexMap method near the bottom.
public partial class MapController : NSViewController
{
public MapController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
DrawHexMap();
}
partial void GoToHex(Foundation.NSObject sender)
{
string[] coordinateStrings = ((NSButton)sender).Title.Split(',');
Hex chosenHex = HexRepo.GetHex(coordinateStrings[0], coordinateStrings[1]);
HexService.currentHex = chosenHex;
NSTabViewController tp = (NSTabViewController)ParentViewController;
tp.TabView.SelectAt(1);
}
private void DrawHexMap()
{
double height = 60;
for (int x = 0; x < 17; x++) {
for (int y = 0; y < 13; y++) {
HexButton button = new HexButton(x, y, height);
var handle = ObjCRuntime.Selector.GetHandle("GoToHex:");
button.Action = ObjCRuntime.Selector.FromHandle(handle);
button.Target = this;
View.AddSubview(button);
}
}
}
}
And here's the custom button class.
public class HexButton : NSButton
{
public NSTrackingArea _trackingArea;
public HexButton(int x, int y, double height)
{
double width = height/Math.Sqrt(3);
double doubleWidth = width * 2;
double halfHeight = height/2;
double columnNudge = decimal.Remainder(x, 2) == 0 ? 0 : halfHeight;
Title = x + "," + y;
//Bordered = false;
//ShowsBorderOnlyWhileMouseInside = true;
SetFrameSize(new CGSize(width, height));
SetFrameOrigin(new CGPoint(width + (x * doubleWidth), (y * height) + columnNudge));
_trackingArea = new NSTrackingArea(Frame, NSTrackingAreaOptions.ActiveInKeyWindow | NSTrackingAreaOptions.MouseEnteredAndExited, this, null);
AddTrackingArea(_trackingArea);
}
public override void MouseEntered(NSEvent theEvent)
{
base.MouseEntered(theEvent);
Console.WriteLine("mouse enter");
}
}
So as you can see, I'm creating a tracking area for the button and adding it in the constructor. Yet I can't seem to get a MouseEntered to fire. I know the MouseEntered override in this class works, because when I call button.MouseEntered() directly from my code, the method fires.
A few other things I've tried include: Commenting out the lines that set the Action and Target in the ViewController, in case those were overriding the MouseEntered handler somehow. Setting those values inside the HexButton constructor so that the Target was the button instead of the ViewController. Putting the MouseEntered override in the ViewController instead of the button class. Creating the tracking area after the button was added as a subview to the ViewController. None of these made a difference.
Any help would be much appreciated! It's quite difficult to find documentation for Xamarin.Mac...
Thanks!
You are adding the Frame as the region tracked, but you are attaching the tracking area to the view that you are creating the region from, thus you need to track the Bounds coords.
_trackingArea = new NSTrackingArea(Bounds, NSTrackingAreaOptions.ActiveInKeyWindow | NSTrackingAreaOptions.MouseEnteredAndExited, this, null);
Note: If you were tracking from the view that you are adding the buttons to, then you would need to track the "Frame" as it is the tracking region is relative to the view being tracked, not its children.

Xamarin Forms fade to hidden?

In my current app, I have a bunch of buttons which can hide or show their corresponding stackLayout.
First, i tried using IsVisble property, but this causes a flash,
now im at using LayoutTo() which also flashes?
My code is as below:
async void btnStrike_Clicked(object sender, EventArgs args)
{
var layout = this.FindByName<StackLayout>("stkStrikeInfo");
var rect = new Rectangle(layout.X, layout.Y, layout.Width, layout.Height - layout.Height);
await layout.LayoutTo(rect, 2500, Easing.Linear);
}
Id like to animate the height!
Edit:
I found the following piece of code, which removes the Stacklayout from the page.
The issue now is that the view isnt updating?
I think you'll have better luck with just a default animation that reduces the height of the layout you want to hide to zero.
void btnStrike_Clicked(object sender, EventArgs args)
{
// get reference to the layout to animate
var layout = this.FindByName<StackLayout>("stkStrikeInfo");
// setup information for animation
Action<double> callback = input => { layout.HeightRequest = input; }; // update the height of the layout with this callback
double startingHeight = layout.Height; // the layout's height when we begin animation
double endingHeight = 0; // final desired height of the layout
uint rate = 16; // pace at which aniation proceeds
uint length = 1000; // one second animation
Easing easing = Easing.CubicOut; // There are a couple easing types, just tried this one for effect
// now start animation with all the setup information
layout.Animate("invis", callback, startingHeight, endingHeight, rate, length, easing);
}
If the layout is already hidden and you want to show it, you would replace
double startingHeight = layout.Height;
double endingHeight = 0;
with
double startingHeight = 0;
double endingHeight = 55;
The 55 is just an arbitrary height, if you want it to go back to the height from before, you would save the previous height to a variable before you hide it and use that saved height instead of 55.

How to use TextButtonStyle.overFont?

I'm trying to use overFont and overColor on TextButton so the button appearance can changes when the mouse move over.
Here's the style I defined.
var buttonStyle = new TextButtonStyle();
buttonStyle.fontColor = new Color(1f, 1f, 1f, 1f);
buttonStyle.disabledFontColor = new Color(0, 0, 0, 0.4f);
buttonStyle.down = skin.getDrawable( "button_down");
buttonStyle.up= skin.getDrawable( "button_up");
buttonStyle.over= skin.getDrawable( "button_over");
buttonStyle.overFontColor = new Color(0, 0.3f, 0.3f, 1f);
buttonStyle.font = font
skin.add("default", buttonStyle);
The button is created as follows:
var startGameButton = new TextButton("Start game", skin);
startGameButton.x = buttonX;
startGameButton.y = currentY;
startGameButton.width = BUTTON_WIDTH;
startGameButton.height = BUTTON_HEIGHT;
stage.addActor(startGameButton);
/*startGameButton.addListener ([ Event e |
Gdx.app.log ("App", "Start game") ;
return true ;
])*/
startGameButton.addListener (new ChangeListener () {
override changed(ChangeEvent event, Actor actor) {
Gdx.app.log ("App", "Start game") ;
}
})
While the down and up state are properly taken into account, the over properties are not used: the button doesn't change when the mouse enters the button area.
buttonStyle.fontOverColor = Color.BLUE; works fine for me,
try to pass to your TextButton constructor not skin, but buttonStyle,
in TextButton there is such constructor
public TextButton (String text, TextButtonStyle style)
It's difficult to say something else, because code not looks like real working code, I mean var keyword or this code is not correct (there is no public variables x, y, width, height):
startGameButton.x = buttonX;
startGameButton.y = currentY;
startGameButton.width = BUTTON_WIDTH;
startGameButton.height = BUTTON_HEIGHT;
If changing constructor will not help you, please post your real code.

Layout a Manager with USE_ALL_HEIGHT style without overriding sublayout() in BlackBerry

I want to layout three VerticalFieldManager in a screen with NO_VERTICAL_SCROLL. One manager should be aligned to TOP, one should be aligned to BOTTOM and the last one should consume the rest of the height between the former two.
Can it be achieved without overriding sublaout() for any Manager? The result I want to achieve is:
I layouted this screen with the following code. The problem is that I wasn't able to do it without overriding sublayout().
public class LayoutSandboxScreen extends MainScreen {
public LayoutSandboxScreen() {
super(NO_VERTICAL_SCROLL);
VerticalFieldManager vfmTop = new VerticalFieldManager(USE_ALL_WIDTH);
vfmTop.setBackground(BackgroundFactory.createSolidBackground(Color.GREEN));
vfmTop.add(new ButtonField("TOP", FIELD_HCENTER));
final VerticalFieldManager vfmCenter = new VerticalFieldManager(USE_ALL_WIDTH);
HorizontalFieldManager hfmCenter = new HorizontalFieldManager(USE_ALL_HEIGHT | FIELD_HCENTER);
vfmCenter.setBackground(BackgroundFactory.createSolidBackground(Color.RED));
hfmCenter.add(new ButtonField("CENTER", FIELD_VCENTER));
vfmCenter.add(hfmCenter);
final VerticalFieldManager vfmBottom = new VerticalFieldManager(USE_ALL_WIDTH);
vfmBottom.setBackground(BackgroundFactory.createSolidBackground(Color.BLUE));
final ButtonField btn = new ButtonField("BUTTOM", FIELD_HCENTER);
vfmBottom.add(btn);
VerticalFieldManager vfmSecond = new VerticalFieldManager(USE_ALL_HEIGHT) {
protected void sublayout(int maxWidth, int maxHeight) {
setExtent(maxWidth, maxHeight);
layoutChild(vfmBottom, maxWidth, maxHeight);
int bottomHeight = vfmBottom.getHeight();
layoutChild(vfmCenter, maxWidth, maxHeight - bottomHeight);
setPositionChild(vfmCenter, 0, 0);
setPositionChild(vfmBottom, 0, maxHeight - bottomHeight);
}
};
vfmSecond.add(vfmBottom);
vfmSecond.add(vfmCenter);
add(vfmTop);
add(vfmSecond);
}
}
Since you're already using a MainScreen, have you tried using setTitle() and setStatus() for the top and bottom VerticalFieldManager? I think that will do what you want.
Edit
If MainScreen is too specific, you can write your own MainManager, which supports the same layout components as MainScreen - banner, title, main content, status. You will have to write your own layout code though, so you'll still be implementing sublayout(), which you specifically wanted to avoid. The plus side is that this will be more composable - you won't be overriding the sublayout() method in an ad-hoc way on random UI components.

Blackberry - single line BasicEditField with large text

I have created a customized BasicEditField with Border using Bitmap.Now while typing the text,it crosses the border of the BasicEditField.
This is my code
class customEditField1 extends EditField
{
Bitmap mBorder = null;
customEditField1(Bitmap borderBitmap)
{
mBorder = borderBitmap;
}
protected void paint(Graphics graphics)
{
graphics.drawBitmap(0, 0, mBorder.getWidth(),mBorder.getHeight(), mBorder, 0, 0);
super.paint(graphics);
}
}
I want to create a BasicEditField which should hide the previously entered text and displays the newly entered text and the typed text should be with in the border.It should not depends on the number of chars limit.And i want to Apply padding between the text and the border.
You can put BasicEditField into HorizontalFieldManager.
Don't forget to move border bitmap painting from BasicEditField to HorizontalFieldManager.
class ScrollEdit extends HorizontalFieldManager {
Bitmap mBorder = null;
public BasicEditField mEdit = null;
public ScrollEdit(Bitmap border) {
super(HORIZONTAL_SCROLL | NO_HORIZONTAL_SCROLLBAR);
mBorder = border;
mEdit = new EditField(BasicEditField.NO_NEWLINE);
add(mEdit);
}
protected void paint(Graphics graphics) {
graphics.drawBitmap(0, 0, mBorder.getWidth(), mBorder.getHeight(),
mBorder, 0, 0);
super.paint(graphics);
}
}
But you will have to play around with layout and setExtent to size manager and edit correctly. My advice is to try it without border bitmap first.
See Scroll BasicEditField instead of wrap
Talking about the wrap, set padding to BasicEditField within manager or add white space in border bitmap...

Resources