Changing Libgdx Button appearance - java

I need to be able to change the appearance of a Libgdx Button when some of my events are triggered.
Here is the declaration of my button:
Button googleButton = new Button(skin.getDrawable("google_sign_in"));
Here are the things I tried:
googleButton.setBackground(skin.getDrawable("google_sign_out"));
googleButton.invalidate();
googleButton.setChecked(true);
googleButton.invalidate();
googleButton.getStyle().up = skin.getDrawable("google_sign_out");
googleButton.invalidate();
I have done a lot of searches but I can't find the answer. Could somebody show me the right way of doing this?

I think the problem is that you're changing the contents of the skin/style after initializing the Button, but the button object does not reference the style after it has been initialized. I'm also not entirely clear on what you're going for. I assume you want to show a "sign in" button, until the user is signed in, and then you want that button to be a "sign out" button.
The invalidate method just triggers a re-layout (to re-compute the size/location of the Actor).
Maybe try forcing the style with setStyle, like this:
googleButton.getStyle().up = ... whatever;
googleButton.setStyle(googleButton.getStyle());
That said, I think you would be better off having two (?) different Button objects (one for logging in, and one for logging out). Pack them in a Stack, and just make one or the other invisible (see Actor.setVisible)

I managed to get this to work. In my Actor, a dice that have 6 possible images:
public Dice(int options) {
super(new Button.ButtonStyle());
}
And when I want to change the face:
public void setValue(int value) {
this.value = value;
Button.ButtonStyle style = getStyle();
style.up = new TextureRegionDrawable(
Assets.instance.dices.facesUp[value]);
style.down = new TextureRegionDrawable(
Assets.instance.dices.facesDown[value]);
style.checked = new TextureRegionDrawable(
Assets.instance.dices.facesChecked[value]);
setSize(getPrefWidth(), getPrefHeight());
}
I think the trick is at the
setSize(getPrefWidth(), getPrefHeight());
If I omit it, the dice doesn't get displayed. And there's no need for setStyle or invalidate().

Use CheckBox class instead;
1- make a .json file for the skin
{
com.badlogic.gdx.graphics.g2d.BitmapFont: { default-font: { file: fontfile.fnt } },
com.badlogic.gdx.graphics.Color: {
green: { a: 1, b: 0, g: 1, r: 0 },
white: { a: 1, b: 1, g: 1, r: 1 },
red: { a: 1, b: 0, g: 0, r: 1 },
black: { a: 1, b: 0, g: 0, r: 0 }
},
com.badlogic.gdx.scenes.scene2d.ui.CheckBox$CheckBoxStyle: {
google-loggin: { checkboxOn: google_sign_in, checkboxOff: google_sign_out, font: default-font, fontColor: white }
},
}
2- make a skin
skin = new Skin(Gdx.files.internal("your.json-file.json"), new TextureAtlas("textureAtlas-file.pack"));
3- create the button ignoring the first argument:
CheckBox loginButton = new CheckBox("", skin, "google-loging");

Just for anyone searching for this through google. To change the style of the button from a style already added to your skin file, after already initialising:
btn.setStyle(skin.get("YOUR BTN STYLE",TextButton.TextButtonStyle.class));

You must add image to button button_1.addActor(image). This image will cover the button origin skin. And then you can switch off and on this image image.setVisible(false)

Related

Android: custom bottom navigation view with one center big icon [duplicate]

How to create BottomNavigation with one of the item is larger than the parent, but without using floatingActionButton. For example like this:
I tried to do that by wrapping the icon with Box but it get cut like this:
Then i try to separate that one button and use constraintLayout to position it, but the constraintLayout cover the screen like this. Even when i color it using Color.Transparent, it always feels like Color.White (i dont know why Color.Transparent never work for me). In this picture i give it Red color for clarity reason.
So how to do this kind of bottomNavBar without having to create heavy-custom-composable?
Update: so i try to make the code based on MARSK and Dharman comment (thanks btw). This is what i
BoxWithConstraints(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.background(Color.Transparent)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.background(Color.White)
.align(Alignment.BottomCenter)
)
Row(
modifier = Modifier
.zIndex(56.dp.value)
.fillMaxWidth()
.selectableGroup(),
horizontalArrangement = Arrangement.SpaceBetween,
) {
items.forEach { item ->
val selected = item == currentSection
BottomNavigationItem(
modifier = Modifier
.align(Alignment.Bottom)
.then(
Modifier.height(
if (item == HomeSection.SCAN) 84.dp else 56.dp
)
),
selected = selected,
icon = {
if (item == HomeSection.SCAN) {
ScanButton(navController = navController, visible = true)
} else {
ImageBottomBar(
icon = if (selected) item.iconOnSelected else item.icon,
description = stringResource(id = item.title)
)
}
},
label = {
Text(
text = stringResource(item.title),
color = if (selected) Color(0xFF361DC0) else LocalContentColor.current.copy(
alpha = LocalContentAlpha.current
),
style = TextStyle(
fontFamily = RavierFont,
fontWeight = if (selected) FontWeight.Bold else FontWeight.Normal,
fontSize = 12.sp,
lineHeight = 18.sp,
),
maxLines = 1,
)
},
onClick = {
if (item.route != currentRoute && item != HomeSection.SCAN) {
navController.navigate(item.route) {
launchSingleTop = true
restoreState = true
popUpTo(findStartDestination(navController.graph).id) {
saveState = true
}
}
}
}
)
}
}
}
It works in preview, but doesn't work when i try in app.
This one in the preview, the transparent working as expected:
And this is when i try to launch it, the transparent doesnt work:
Note: I assign that to bottomBar of Scaffold so i could access the navigation component. Is it the cause that Transparent Color doesnt work?
Update 2: so the inner paddingValues that makes the transparent doesnt work. I fixed it by set the padding bottom manually:
PaddingValues(
start = paddingValues.calculateStartPadding(
layoutDirection = LayoutDirection.Ltr
),
end = paddingValues.calculateEndPadding(
layoutDirection = LayoutDirection.Ltr
),
top = paddingValues.calculateTopPadding(),
bottom = SPACE_X7,
)
Custom Composable are not heavy, really.
Anyway, try this:-
Create a Container of MaxWidth (maybe a BoxWithConstraints or something), keep its background transparent, set the height to wrap content. Create the tabs as usual, but keeping the bigger tab's icon size bigger explicitly using Modifier.size(Bigger Size).
After you have this setup, add another container inside this container with white background, covering a specific height of the original container. Let's say 60%
Now set the z-index of all the icons and tabs to higher than the z-index of this lastly added container. Use Modifier.zIndex for this. And viola, you have your Composable ready.
In order to set a specific percentage height of the inner container, you will need access to the height of the original container. Use BoxWithConstraints for that, or just implement a simple custom Layout Composable

How can I change my JavaFx's buttons to look exactly like this?

[2]: Below is a piece of what I've done so far. Can't seem to get it to look like the pic that I've attached.
gp.getColumnConstraints().addAll(rc, rc1, rc2);
gp.setAlignment(Pos.TOP_CENTER);
gp.add(prev, 0, 0);
gp.add(search, 1, 0);
gp.add(next, 2, 0);
Button add = new Button("Add + ");
add.setPrefSize(75, 10);
add.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
if (!fNameFld.getText().toString().equals("")) {
Contact c = new Contact(fNameFld.getText().toString(), numF.getText().toString(),
emailf.getText().toString());
contact.add(c);
i = contact.indexOf(c);
System.out.println(i);
}
}
});
Button edit = new Button("Edit * ");
edit.setPrefSize(75, 10);
edit.setOnAction(new EventHandler<ActionEvent>() {
I wouldn't use a GridPane for this. In fact, I’m pretty sure a GridPane alone can’t do what you want.
You can make a center-aligned HBox for each row, and put those rows into a single VBox:
Collection<HBox> buttonRows = Arrays.asList(
new HBox(6, previous, search, next),
new HBox(6, add, edit, remove),
new HBox(6, clear, quit));
buttonRows.forEach(hbox -> hbox.setAlignment(Pos.CENTER));
VBox buttonPane = new VBox(12);
buttonPane.getChildren().addAll(buttonRows);
You should get rid of all calls to setPrefSize. Your buttons are perfectly capable of defining their own sizes. If you want to give them larger internal margins, set their -fx-label-padding CSS properties.

Grouping objects in JavaFX?

So I'm currently making a JavaFX GUI (with SceneBuilder) for a Connect4 game, and I was wondering if there's a way to 'group' objects together so that I can perform an action on all of them together?
Examples of what I mean:
I have 7 buttons for the columns (colButton1-7) and I want to disable all of them at once.
I use Ellipses for counters (counter1-40) and would like to change the color of all of them to white.
I searched around but couldn't find anything. I know how to do both for an individual object, but can't think of a way to easily apply the changes to all of them at the same time. Any help would be appreciated :)
There is no grouping mechanism to perform a single action on all of the members of the same group. On the contrary, you can have a single group/container to hold all your controls and apply the same action to each of its member.
For example, lets say I have a VBox containing Buttons and I want to disable them all.
for(Node node:vBox.getChildren()) {
node.setDisable(true);
}
or, to set Styling
for(Node node:vBox.getChildren()) {
node.setStyle("-fx-something");
}
For disabling, if you disable a node, then all it's child nodes will have disabled set to true. So you can do:
VBox buttonHolder = new VBox();
Button button = new Button(...);
buttonHolder.getChildren().add(button);
// repeat as necessary...
buttonHolder.setDisable(true); // all buttons in the VBox will now be disbaled
For styled properties, such as the fill of a shape, you should use an external style sheet. If you change the style class of the parent, then with an appropriate external style sheet you can change the style of all the children in one shot.
E.g.
Pane counterPane = new Pane();
for (int i=0; i<numCounters; i++) {
Ellipse counter = new Ellipse(...);
counter.getStyleClass().add("counter");
counterPane.getChildren().add(counter);
}
// ...
counterPane.getStyleClass().add("counter-pane"); // all counters white
// change to red:
counterPane.getStyleClass().remove("counter-pane");
counterPane.getStyleClass().add("warning");
External style sheet:
.counter-pane > .counter {
-fx-fill: white ;
}
.warning > .counter {
-fx-fill : red ;
}

StateListDrawable containing Drawables with different bounds

Suppose I have a StateListDrawable. I want to add 2 drawables inside it: the first if it is clicked, second for any other state.
I tried it as following (pseudo-code):
Drawable clickdDrawable = getResourses.getDrawable(R.drawable.presseddrawable);
clickDrawable.setBounds(-100, -100, 100, 100);
Drawable otherStateDrawable = getResources().getDrawable(R.drawable.somedrawable);
otherStateDrawable.setBounds(-50,-50, 50, 50);
StateListDrawable sld = new StateListDrawable();
sld.addState(new int[]{andriod.R.attr.state_pressed, android.R.attr.state_focussed}, clickDrawable);
sld.addState(StateSet.WILDCARD, otherStateDrawable);
sld.setBounds(-50, -50, 50, 50);
now if I'm in state pressed I will get the presseddrawable, but it sticks to the bounds of StateListDrawable. So my question is: How to store Drawables with different bounds inside a StateListDrawable? Is this possible?
You will have to create "custom" Drawables, but before you go that way, let me invite you (and whoever is involved, often a designer) to re-think a bit what you are doing, some years ago I did a heavy work on programmatically drawn extends Drawables (yet it was awesome) just to trash it few months later in favor of simplicity and practicality, I don't see why you can't achieve something like this with a well made 9-patch (a.k.a. n-patch) rather than hardcode dimensions, anyways before you call me grandpa here is a quick answer that could work for ya:
In example say you are using color drawables:
public class FixedBoundsColorDrawable extends ColorDrawable {
private boolean mFixedBoundsSet = false; // default
public FixedBoundsColorDrawable(int color) {
super(color);
}
#Override
public void setBounds(int left, int top, int right, int bottom) {
if (!mFixedBoundsSet) {
mFixedBoundsSet = true;
super.setBounds(left, top, right, bottom);
}
}
}
With red as pressed and blue as wildcard and your values you get on a Nexus 4:
You could also create a wrapper to wrap any drawable and call its methods but I would go that way as there are some final methods that you certainly will need.

Disable previous and next month buttons on com.google.gwt.user.datepicker.client.DatePicker?

I have a com.google.gwt.user.datepicker.client.DatePicker and I don't want the user to be able to select the previous month or the next month in certain cases.
For example I don't want the user to be able to select a day before today.
I figured out how to disable the actual days in the calendar, but the user can still click on the << and go back a month, which all the days are disabled.
I can't find any way to get a reference to the << and >> buttons/links to preferably hide them or alternatively disable them.
I am using GWT 2.1.1 and can go to GWT 2.2.0 if that matters.
Does anyone know how to get a reference to these widgets?
The DefaultDateMonthSelector (com.google.gwt.user.datepicker.client) used by the DatePicker does not expose these widgets and hence it is not possible to disable these buttons directly.
To implement this feature, write a new DateMonthSelector (you could start with the source of DefaultMonthSelector http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/datepicker/client/DefaultMonthSelector.java ). For e.g.,
public final class LimitedMonthSelector extends MonthSelector {
// Keep the PushButtons disabled
// Modified from the original DefaultMonthSelector
#Override
protected void setup() {
// Set up backwards.
backwards = new PushButton();
backwards.getUpFace().setHTML("«");
backwards.setStyleName(css().previousButton());
backwards.setEnabled(false); // Disable the back button
forwards = new PushButton();
forwards.getUpFace().setHTML("»");
forwards.setStyleName(css().nextButton());
forwards.setEnabled(false); // Disable the forward button
// Set up grid.
grid = new Grid(1, 3);
grid.setWidget(0, 0, backwards);
grid.setWidget(0, 2, forwards);
CellFormatter formatter = grid.getCellFormatter();
formatter.setStyleName(0, 1, css().month());
formatter.setWidth(0, 0, "1");
formatter.setWidth(0, 1, "100%");
formatter.setWidth(0, 2, "1");
grid.setStyleName(css().monthSelector());
initWidget(grid);
}
}
And then use this MonthSelector implementation in a DatePicker implementation. Like,
public class LimitedDatePicker extends DatePicker {
public MonthYearDatePicker() {
super(new LimitedMonthSelector(), new DefaultCalendarView(), new CalendarModel());
}
}
This new LimitedDatePicker would have its back/forward buttons disabled.

Categories