Adding a button to activity

Hi Guys,
I would like to add a simple button to my AndroidHarness based activity.
what is the best practice to do so?
the AndroidHarness GLSurfaceView is stretched all over the activity and I want a button above it in the center-bottom of the screen.
I prefer it will be a simple regular android button but if there is a JME dedicated UI element I’ll settle for it as well.

Looking for best practice for adding UI elements to my app.
Thank you

Regarding GUI libraries… Last time i tried Lemur on android it had issues loading groovy-all - which i think paul actually wanted to look into but nobody was up for helping much. That leaves you with Nifty or TonegodGui. I cant really decide which one you should use, but those are the “out of the box” choices you have.

99% sure that groovy-all is only required if you want to use the styling language (or the default styles). If you choose to avoid loading the default glass style then it shouldn’t be an issue.

For a simple button, styles are probably not required. Either use the unstyled button or give it a simple quad background.

Button b = new Button(“Hello, world”);
b.setBackground(new QuadBackgroundComponent(ColorRGBA.Gray);
…or whatever.
guiNode.attachChild(b);

I was hoping someone would answer him regarding a native button but yeah, otherwise Lemur should work ok for a simple button with no styling.

If OP is curious:

Just avoid the “Initializing a Default Style” section on Android.

Yeah it’s a bit difficult to use Android stuff in jME. However, if you really want something like that, you can look at the file “src\main\res\layout\main.xml” or something. With button it should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
	xmlns:android='http://schemas.android.com/apk/res/android'
	android:layout_height='fill_parent'
	android:layout_width='fill_parent'
	android:orientation='vertical'>
	<fragment
		android:id='@+id/jmeFragment'
		android:layout_height='wrap_content'
		android:layout_width='match_parent'
		android:layout_weight="3"
		android:name='beb.MainActivity$JmeFragment' />
	<Button
		android:id="@+id/button1"
		android:layout_height="wrap_content"
		android:layout_width="match_parent"
		android:layout_weight="1"
		android:padding="16dp" />
</LinearLayout>

… or something like that.
After that comes the task of hooking up that button to jME.


Also, here’s most of Lemur’s glass style, written in Java:

public static void loadGlassStyle(Application app) {
	GuiGlobals.initialize(app);
	
	////
	
	Styles styles = GuiGlobals.getInstance().getStyles();
	Attributes attrs;
	
	TbtQuadBackgroundComponent gradient = TbtQuadBackgroundComponent.create(
			app.getAssetManager().loadTexture("/com/simsilica/lemur/icons/bordered-gradient.png"),
			1f, 1, 1, 126, 126,
			1f, false);
	
	TbtQuadBackgroundComponent bevel = TbtQuadBackgroundComponent.create(
			app.getAssetManager().loadTexture("/com/simsilica/lemur/icons/bevel-quad.png"),
			1f, 1, 1, 126, 126,
			1f, false);
	
	TbtQuadBackgroundComponent border = TbtQuadBackgroundComponent.create(
			app.getAssetManager().loadTexture("/com/simsilica/lemur/icons/border.png"),
			1f, 1, 1, 126, 126,
			1f, false);
	
	TbtQuadBackgroundComponent border2 = TbtQuadBackgroundComponent.create(
			app.getAssetManager().loadTexture("/com/simsilica/lemur/icons/border.png"),
			1f, 1, 1, 126, 126,
			1f, false);
	
	QuadBackgroundComponent doubleGradient = new QuadBackgroundComponent(new ColorRGBA(.5f, .75f, .85f, .5f));
	doubleGradient.setTexture(app.getAssetManager().loadTexture("/com/simsilica/lemur/icons/double-gradient-128.png"));
	
	attrs = styles.getSelector("glass");
	attrs.set("fontSize", 24);
	
	attrs = styles.getSelector("label", "glass");
	attrs.set("insets", new Insets3f(2, 2, 0, 2));
	attrs.set("color", new ColorRGBA(0.5f, 0.75f, 0.75f, 0.85f));
	
	attrs = styles.getSelector("container", "glass");
	TbtQuadBackgroundComponent gradient_clone_container = gradient.clone();
	gradient_clone_container.setColor(new ColorRGBA(.25f, .5f, .5f, .5f));
	attrs.set("background", gradient_clone_container);
	
	Command<Button> pressedCommand = new Command<Button>() {
		@Override
		public void execute(Button source) {
			if(source.isPressed()) {
				source.move(1, -1, 0);
			} else {
				source.move(-1, 1, 0);
			}
		}
	};
	
	Map<ButtonAction, List<Command<? super Button>>> stdButtonCommands = new HashMap<>();
	List<Command<? super Button>> listButtonCommands = new ArrayList<>();
	listButtonCommands.add(pressedCommand);
	stdButtonCommands.put(ButtonAction.Down, listButtonCommands);
	stdButtonCommands.put(ButtonAction.Up, listButtonCommands);
	
//		selector( "title", "glass" ) {
//		    color = color(0.8, 0.9, 1, 0.85f)
//		    highlightColor = color(1, 0.8, 1, 0.85f)
//		    shadowColor = color(0, 0, 0, 0.75f)
//		    shadowOffset = new com.jme3.math.Vector3f(2, -2, -1);
//		    background = new QuadBackgroundComponent( color(0.5, 0.75, 0.85, 0.5) );
//		    background.texture = texture( name:"/com/simsilica/lemur/icons/double-gradient-128.png", 
//		                                  generateMips:false )
//		    insets = new Insets3f( 2, 2, 2, 2 );
//		    
//		    buttonCommands = stdButtonCommands;
//		}
	
	attrs = styles.getSelector("title", "glass");
	
	attrs = styles.getSelector("button", "glass");
	TbtQuadBackgroundComponent gradient_clone_button = gradient.clone();
	gradient_clone_button.setColor(new ColorRGBA(0, .75f, .75f, .5f));
	attrs.set("background", gradient_clone_button);
	attrs.set("color", new ColorRGBA(.8f, .9f, 1f, .85f));
	attrs.set("insets", new Insets3f(2, 2, 2, 2));
	attrs.set("buttonCommands", stdButtonCommands);
	
	
	////
	
	styles.setDefaultStyle("glass");
}

… I wrote this a while back ago, but it should work.

Thank you guys. You gave me plenty of options to try out. I understand that it’s best practice not to use native Android GUI in JME apps so I’ll try that first.

If I remember correctly the JME-Android is implemented as a Fragment, right? Then in this case you can have your JME fragment next to Native components…

But I stopped developing on Android years ago, so I might be wrong…

99% sure that groovy-all is only required if you want to use the styling language (or the default styles)

Yes, I can confirm.

Correct me if i’m wrong guys - it seems that Nifty is the “official” UI package for JME?
I’m trying to decide where to put my learning efforts.
So - which is the best UI package to use for the long term in your opinion?

I personally think Lemur is much much much much more jme aware as it has Spatials and the like you know from jme. Nifty is just a gui lib which also work with jme.
I worked with both and I like Lemur better (ok it lacks documentation a bit :wink:)

For some reason Lemur brings JME (ext.jmeVersion=‘3.1.0-alpha4’ // but must be alpha4 or better) Alpha version which collides with the current JME i’m using in my project.
Is there a way to tell it (in the gradle file) not to bring JME with it?

As long as @pspeed is around I’d pick Lemur, of course! :slight_smile:
Otherwise, I’d just roll out my own (I don’t like Nifty and tonegodgui receive almost no support, unfortunately).

You want Lemur but don’t want JME???
What’s next, you want to run bytecode without a JVM? :frowning:

What version of JME are you trying to use?

Lemur requires some JME… the latest versions will work with any version after 3.1 alpha4… else you have to go back to a much earlier release if you are still using 3.0.

I’m using JME 3.1.0-stable. I have added it as a jar dependency so for some reason it collides with the JME3.1.0-alpha4 that gradle brings with Lemur.
Anyway, I managed to overcome the problem by removing the JME jar (from the dependency tab) and bring it via gradle. Now it works but I’m getting run-time exception regarding missing bulletjme??

All I wanted is to add a simple button to my Android activity :grinning:
Can anyone assist with this bulletjme run-time problem - what should I do?

Thanks

I’m confused… are you using gradle or the SDK? You have something very strange going on.

If your gradle project refers to JME 3.1 stable then it shouldn’t be bringing in alpha4 because stable is newer. That’s why all of the gradle-based Lemur examples work fine:

None of this has anything to do with bullet. Lemur definitely doesn’t use it.

Edit: just noticed that is referring to JME beta… but stable should work just the same.

I started using the SDK and it worked great. Then I tried to add Lemur via gradle and I started getting all kind of errors. Do you suggest working only with gradle?
What will my gradle dependencies will look like? I need JME+Lemur and it is an Android project

Dude… just add the jars you need to your project in the SDK. It’s literally on the getting started page.

Get the required dependencies as exactly specified… add them to your project. Done.

I’ll do that. I will remove all the gradle stuff and add it to the project. I somehow thought that using gradle considered best practice…

OK, removed all the gradle stuff and now adding the JARS in my project and getting this at run-time:
java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/script/ScriptEngineManager;
at com.simsilica.lemur.style.StyleLoader.(StyleLoader.java:72)
at com.simsilica.lemur.style.StyleLoader.(StyleLoader.java:62)
at com.simsilica.lemur.style.BaseStyles.loadStyleResources(BaseStyles.java:72)
at com.simsilica.lemur.style.BaseStyles.loadGlassStyle(BaseStyles.java:62)
at com.scenemaxng.projector.SceneMaxApp.simpleInitApp(SceneMaxApp.java:55)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:220)
at com.jme3.app.AndroidHarness.initialize(AndroidHarness.java:478)
at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:328)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1590)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1286)

I’m getting close…
what do you think?

OK, so I remarked the two lines loading the “glass” style and now the app doesn’t crash and I can see the UI elements. It’s a major progress :grinning:
Here is a link to my app in action. It’s going to be some kind of 3D scripting language for kids:
https://www.youtube.com/watch?v=e9NX2U7vxV8

1 Like

Guys where can I find Lenur sample codes?
For example I’m trying to find how to use Button.addClickCommands() and cant find any samples in the online docs…

Thanks