I am new to mobile development, I started using Gluon mobile for Netbeans and I'm trying to add a Bottom navigation bar to the default Gluon Mobile App. They describe the class in the JavaDoc http://docs.gluonhq.com/charm/javadoc/4.1.0/com/gluonhq/charm/glisten/control/BottomNavigation.html but I can't seem to make it work.
Would someone be able to post a snippet on how and where to do this?
Here is a simple example:
public class GluonApplication extends MobileApplication {
#Override
public void init() {
addViewFactory(HOME_VIEW, () ->
{
StackPane root = new StackPane();
root.getChildren().add(new Label("test"));
View view = new View(root) {
#Override
protected void updateAppBar(AppBar appBar) {
appBar.setTitleText("Home");
}
};
view.setBottom(createBottomNavigation());
return view;
});
}
private BottomNavigation createBottomNavigation() {
BottomNavigation bottomNavigation = new BottomNavigation();
ToggleButton btn1 = bottomNavigation.createButton("View1", MaterialDesignIcon.DASHBOARD.graphic(), e -> showView("view1"));
ToggleButton btn2 = bottomNavigation.createButton("View2", MaterialDesignIcon.AC_UNIT.graphic(), e -> showView("view2"));
ToggleButton btn3 = bottomNavigation.createButton("View3", MaterialDesignIcon.MAP.graphic(), e -> showView("view3"));
bottomNavigation.getActionItems().addAll(btn1, btn2, btn3);
return bottomNavigation;
}
private void showView(String viewName) {
MobileApplication.getInstance().switchView(viewName);
}
}
Related
I created some Chips and they have an X symbol on the right side.
But when I click the X (intending to dismiss or remove the Chip), nothing happens.
I tried to use the method setOnCloseIconClickListener but it did not have an effect.
I click the X icon and the color of the icon changes and a clicking sound appears, but the Chip View remains on the screen.
And I also don't know what to write in the callback method of the click listener.
for(int i = 0; i<products.length; i++) {
//the chip component requires your app theme to be Theme.MaterialComponents (or a
//descendant)
chips[i] = new Chip(this);
//ScrollView can only host one direct child
ll1.addView(chips[i]);
chips[i].setText(products[i]);
chips[i].setCloseIconVisible(true);
}
I tried this, but it said the variable i has to be final which is not possible cause i is incrementing.
chips[i].setOnCloseIconClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
chips[i].close();
}
});
I found the solution. This is the code:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private EditText et1;
private ScrollView sv1;
private LinearLayout ll1;
private Chip[] chips;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et1 = findViewById(R.id.editText);
sv1 = findViewById(R.id.scrollView);
ll1 = new LinearLayout(this);
ll1.setOrientation(LinearLayout.VERTICAL);
sv1.addView(ll1);
}
public void splitToChips(View v) {
String content = et1.getText().toString();
String[] products = content.split(";");
chips = new Chip[products.length];
for(int i = 0; i<products.length; i++) {
chips[i] = new Chip(this);
ll1.addView(chips[i]);
chips[i].setText(products[i]);
chips[i].setCloseIconVisible(true);
chips[i].setOnCloseIconClickListener(this);
}
}
#Override
public void onClick(View v) {
Chip chip = (Chip) v;
ll1.removeView(chip);
}
}
I writing autotests for application. On the start of application it has an onboarding (ViewPager) with some pages and button on the last page. I need to swipe these pages and press the button. This is my class for onboarding
public class Onboarding {
ViewInteraction onboardingScreen = onView(
allOf(withId(R.id.vp_onboarder_pager),
childAtPosition(
allOf(withId(R.id.cl_onboarder),
childAtPosition(
withId(android.R.id.content),
0)),
0),
isDisplayed()));
ViewInteraction skipButton = onView(allOf(withId(R.id.btn_finish)));
ViewAction skipOnboardingScreen = new ViewAction() {
#Override
public Matcher<View> getConstraints() {
return any(View.class);
}
#Override
public String getDescription() {
return null;
}
#Override
public void perform(UiController uiController, View view) {
ViewPager onboardingPager = (ViewPager) view;
OnboarderAdapter adapter = (OnboarderAdapter) onboardingPager.getAdapter();
int currentPage = 0;
int screenCount = adapter.getCount();
while (screenCount > 0){
onboardingPager.setCurrentItem(currentPage);
screenCount--;
currentPage++;
}
skipButton.perform(click());
}
};
public void skipOnboarding() {
onboardingScreen.perform(skipOnboardingScreen);
}
I call my test in this way:
#Test
public void onboardingPass() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Onboarding onboarding = new Onboarding();
onboarding.skipOnboarding();
}
When test executing, onboardingPager.setCurrentItem(currentPage) must switch current page, but it does not. When I saw it in debuger, test execute this line, but pages does not switching. Why it can be? Thanks.
... I need to swipe these pages ...
To swipe in your instrumentation tests use this with your view;
onboardingScreen.perform(swipeRight());
swipeRight() is from AndroidX Test package androidx.test.espresso.action.ViewActions.swipeRight
Read more about the AndroidX Test Espresso ViewActions package here.
Setup the swipes as per your requirement and see if it helps.
If you're trying to scroll to the last page of your ViewPager, then you should use ViewPagerActions.scrollToLast instead. And I'm sure that they can all be reduced to as simple as:
public void skipOnboarding() {
onView(withId(R.id.vp_onboarder_pager)).perform(ViewPagerActions.scrollToLast());
onView(withId(R.id.btn_finish)).perform(click());
}
I am trying to create a Gluon mobile application using javafx. I want to create a login page in which on a successful login i need to load another(Second View) view in a button click. I didn't get a proper example for this. If anyone knows this please help. I have two views Primary presenter and secondary presenter.(gluon application with FXML).Below is my primary view's controller.
public class PrimaryPresenter {
#FXML
private View primary;
private Label label;
#FXML
private TextField username;
#FXML
private Button loginBt;
private Alert alert;
#FXML
private PasswordField password;
public void initialize() {
primary.showingProperty().addListener((obs, oldValue, newValue) -> {
if (newValue) {
AppBar appBar = MobileApplication.getInstance().getAppBar();
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e
-> MobileApplication.getInstance().showLayer(ArjunsApp.MENU_LAYER)));
appBar.setTitleText("Primary");
appBar.getActionItems().add(MaterialDesignIcon.SEARCH.button(e
-> System.out.println("Search")));
}
});
}
#FXML
private void buttonClick(ActionEvent event) {
if(username.getText().equals("")){
alert = new Alert(AlertType.ERROR,"Enter username");
alert.showAndWait();
}else if(password.getText().equals("")){
alert = new Alert(AlertType.ERROR,"Enter password");
alert.showAndWait();
}else{
//Code to load my secondary view
}
}
}
Assuming you are using the Gluon plugin - Multi View project with FXML template, you can switch views easily with MobileApplication.getInstance().switchView(viewName).
In your case:
#FXML
private void buttonClick(ActionEvent event) {
...
MobileApplication.getInstance().switchView("SECONDARY_VIEW");
}
If you are using the Glisten-Afterburner template instead (it also uses FXML), you could use something like:
#FXML
private void buttonClick(ActionEvent event) {
...
AppViewManager.SECONDARY_VIEW.switchView();
}
You can find more about the Gluon Mobile API here.
i created a layout containing multiple text views.
i saved the text view's ids in an ArrayList which is a class variable called _resultId.
now i want to create buttons which suppose to scroll to the correct text view
(the first button to the first text view etc)
the question is: how to pass the correct id to each of the buttons on press method?
i tried using a global variable _counter but when i run the program all the buttons scroll to the last text view
the code of the method:
private void addNavigationView(ViewGroup navigationLayout, ArrayList<Perek> mishnayot)
{
for (int i=0;i<mishnayot.size();i++)
{
_counter=i;
String currentOt=mishnayot.get(i).getOt();
Button button = new Button(getBaseContext());
button.setText(currentOt);
if (_resultId==null)
throw new IllegalAccessError("missing result id link cannot be created");
button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0) //make it scroll to correct textview
{
new Handler().post(new Runnable()
{
#Override
public void run()
{
View currentView=findViewById(_resultId.get(_counter));
ScrollView scrollView=(ScrollView) findViewById(R.id.resultScroll);
scrollView.scrollTo(0, currentView.getTop());
}
});
}
});
navigationLayout.addView(button);//add the button to panel
}
navigationLayout.setVisibility(View.VISIBLE);
}
after learning more on Runnable interface i Found an answer so for those who will struggle with something similar:
you need to create a new class altogether that implements both runnable and the OnClickListener.
this class will contain extra data and a constructor to match your needs.
when you set the onClick method of the button you create a new object of that class.
for instance in my case the new method looked like:
public class ButtonHandler implements OnClickListener,Runnable
{
private String _data;//data to be passed for the button
private ArrayList<Integer> _resultId;//the id's of the text views
private Activity _activity;
public ButtonHandler(String data,ArrayList<Integer> resultId,Activity activity)
{
_data=data;
_resultId=resultId;
_activity=activity;
}
#Override
public void run()
{
View currentView=_activity.findViewById(_resultId.get(Integer.valueOf(_data)));
ScrollView scrollView=(ScrollView) _activity.findViewById(R.id.resultScroll);
scrollView.scrollTo(0, currentView.getTop());
}
#Override
public void onClick(View v)
{
new Handler().post(this);
}
}
now to call it from the main activity i use:
private void addNavigationView(ViewGroup navigationLayout, ArrayList<Perek> mishnayot)
{
for (int i=0;i<mishnayot.size();i++)
{
_counter=i;
String currentOt=mishnayot.get(i).getOt();
Button button = new Button(getBaseContext());
button.setText(currentOt);
if (_resultId==null)
throw new IllegalAccessError("missing result id link cannot be created");
button.setOnClickListener(new ButtonHandler(i+"",_resultId,this));
navigationLayout.addView(button);//add the button to panel
}
navigationLayout.setVisibility(View.VISIBLE);
}
I'm trying to add some options to the context menu in a JavaFX WebView when the user right clicks a link, however I can't figure out how to do it.
I found I could add my own context menu using:
final ContextMenu contextMenu = new ContextMenu();
view.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
System.out.println(mouseEvent.getEventType());
if(mouseEvent.isSecondaryButtonDown()) {
System.out.println("Secondary");
contextMenu.show(view, mouseEvent.getSceneX(), mouseEvent.getSceneY());
} else if (mouseEvent.isPrimaryButtonDown()) {
System.out.println("Primary");
} else if (mouseEvent.isMiddleButtonDown()) {
System.out.println("Middle");
}
}
});
javafx.scene.control.MenuItem menuItem1 = new javafx.scene.control.MenuItem("View Source");
menuItem1.setOnAction(new EventHandler<javafx.event.ActionEvent>() {
#Override
public void handle(javafx.event.ActionEvent actionEvent) {
System.out.println("Link: " + rightClickURL);
System.out.println("You clicked view source");
}
});
contextMenu.getItems().add(menuItem1);
Unfortunately, when I do that both menus appear:
If I use view.setContextMenuEnabled(false); then the default menu disappears. Unfortunately doing that also prevents me from detecting which link was right clicked. Here is the code I'm using for that:
engine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
#Override
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
EventListener listener = new EventListener() {
#Override
public void handleEvent(org.w3c.dom.events.Event evt) {
String domEventType = evt.getType();
if (domEventType.equals(EVENT_TYPE_CLICK)) {
String href = ((Element)evt.getTarget()).getAttribute("href");
} else if (domEventType.equals(EVENT_TYPE_RIGHT_CLICK)) {
String href = ((Element)evt.getTarget()).getAttribute("href");
rightClickURL = href;
System.out.println(href);
}
}
};
Document doc = engine.getDocument();
NodeList nodeList = doc.getElementsByTagName("a");
for (int i = 0; i < nodeList.getLength(); i++) {
((EventTarget) nodeList.item(i)).addEventListener(EVENT_TYPE_CLICK, listener, false);
((EventTarget) nodeList.item(i)).addEventListener(EVENT_TYPE_RIGHT_CLICK, listener, false);
}
}
}
});
So my question is this: how can I access the default ContextMenu so I can customize it? I've scoured the docs but cannot find any method that allows you to access the default ContextMenu. It seems like there must be a way to do this but I'm stumped as to how.
If customizing the default ContextMenu is not possible, does anyone know how I can show a custom context menu when right clicking a link and also capture which link was clicked? I've been trying to achieve this for days with absolutely no luck...
Currently that's not possible. There is an open issue on JavaFX for that:
https://javafx-jira.kenai.com/browse/RT-20306
If you just want to add a different context menu, then you could do that
webView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouse) {
if (mouse.getButton() == MouseButton.SECONDARY) {
menu = new ContextMenu();
//add some menu items here
menu.show(this, mouse.getScreenX(), mouse.getScreenY());
} else {
if (menu != null) {
menu.hide();
}
}
}
});