Responding to Input Android Way
OK, so one way or another we have a text field and a button on the screen. To round off the section that showed how to build a user-interface the Android way, I'll show you how to respond to the button and get the text from the EditText
.
The Android way is slightly different if you built the UI programmatically or using XML so I'll need to show you both ways. Also, there's a mixed way to do it that we'll look at too.
Respond to the Send Button
The XML way
Warning as of right now the "XML way" doesn't work! I'll go ahead and write this section as if it works but be warned: it doesn't!
According to the
Button
docs, our button inherited an android:onClick
XML attribute from android.view.View
. If you're like me, you'll be alarmed to note that this is one of those rare XML attributes that doesn't have a 'Related Method'!
To use this attribute, we just specify the name of a method in the activity that we want to call like this:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send"
android:onClick="sendMessage" />
Then all we need to do is add the sendMessage
method to the activity:
def sendMessage(view)
end
As an easy way to test that our button is hooked up as expected, we'll have it create a toast like so:
def sendMessage(view)
message = 'Howdy'
duration = Java::android.widget.TOAST::LENGTH_SHORT
toast = Java::android.widget.TOAST.makeText(self, message, duration)
toast.show()
end
And that's all there is to it!
The Programmatic Way
Let's pretend like XML doesn't exist and go back to our old app. It's just one file, which I've prettied up a bit since you last saw it:
class FirstAppActivity
LAYOUT = Java::android.widget.LinearLayout
EDIT_TEXT = Java::android.widget.EditText
BUTTON = Java::android.widget.Button
attr_accessor :layout, :edit_text, :button
def on_create(bundle)
super
create_layout
create_edit_text
create_button
self.content_view = layout
end
def create_layout
@layout = LAYOUT.new(self)
end
def create_edit_text
@edit_text = EDIT_TEXT.new(self)
edit_text.hint = 'Enter Some Text!'
layout.add_view edit_text
layout_params = edit_text.layout_params
layout_params.weight = 1
end
def create_button
@button = BUTTON.new(self)
button.text = 'Send'
layout.add_view button
end
end
Please note that in the above I used the same substitutions as the Ruboto way (setHint
became hint=
and getLayoutParams
became layout_params
). As it turns out, you don't need Ruboto to get these conversions. They come from JRuby too! Neat! It's also important that in the above I call self.content_view=
instead of content_view=
.
To respond to click events programmatically, we just need to set the onClickListener
for the button. The way this works out in the wash is pretty interesting. Take a look:
TOAST = Java::android.widget.Toast
def create_button
@button = BUTTON.new(self)
button.text = 'Send'
layout.add_view button
button.on_click_listener = proc { howdy }
end
def howdy
message = 'Howdy'
duration = TOAST::LENGTH_SHORT
toast = TOAST.make_text(self, message, duration)
toast.show
end
The docs will tell you that the setOnClickListener
method is just looking for a callback. In Ruby one way to do that is to set the listener to a proc
like the above, then whatever is in the proc will get called when the button gets clicked.
Another way is to use the set
form of the method and hand it a block
:
button.set_on_click_listener { howdy }
A Blended Approach
The last approach that I'll explore, is one where we still declare our UI over in the XML, but instead of attaching an onClick
directly, we'll fetch the object from the XML and work with it programmatically. From what I've seen so far, this approach is pretty common to a lot of problem solving in Android land, so let's take a look.
First, we need to fetch the button from the XML. We can get views (which the button is) via the Activity
class's findViewById
method. This method just needs an identifier integer which we can access again via our resources package R
. If we give our button an id like so:
<Button android:id="@+id/send_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send" />
then the integer can be retrieved from the id package. Using the ruboto/package
we can get a reference to the button as R.id.send_button
. We can use that id to retrieve the view with the findViewById
method available to our activity.
Altogether that's:
require 'ruboto/package'
class FirstAppActivity
TOAST = Java::android.widget.Toast
def on_create(bundle)
super
self.content_view = R.layout.first_layout
button = find_view_by_id(R.id.send_button)
button.set_on_click_listener { howdy }
end
def howdy
message = 'Howdy'
duration = TOAST::LENGTH_SHORT
toast = TOAST.make_text(self, message, duration)
toast.show
end
end