Android: Specify full method path in android:onClick - android

This question is about Android development. In general, how do you tie a layout XML file to a certain Activity java file? This is relevant in a case such as a button with the android:onClick attribute specified. Suppose you have a layout XML file with a button like the following:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_send"
android:onClick="sendMessage" />
So when this button is clicked, a sendMessage(View view) method is called. If more than one Activity has a sendMessage(View view) method, how does Android decide which one to call? There's literally absolutely nothing associating layout files with Activity files. In Android Studio, I've found that the android:onClick="sendMessage" defaults to the main activity's sendMessage method if there is more than one choice. I've also found that Android Studio doesn't let you simply specify the full method path (for example, android:onClick="com.example.Activity2.sendMessage"). Am I missing something?
Edit: I would like to add that Android Studio shows the sendMessage defaulting to a specific activity, REGARDLESS of which Activities have specified the layout via setContentView()

The android:onClick will call the method on the Activity your layout is inflated and attached to. There should be no tight coupling between a layout and it's controller, so thats why you can't specify a "full path".
I'd recommend using a programatical OnClickListener instead of the xml attribute. It gives you much greater control.

There is a tools:context attribute that you can use to tell Android Studio in what context the layout is meant to be used. You specify a class there and then it should take this class to find the correct method
But this attribute is only for the IDE. During Runtime it binds to the method of the activity that inflated the layout.

Of course it will call the method from the activity class of that view. So simply it will call from main activity class if that view is from main activity and if the view is from , for example Activity2, then it will look for the sendMessage method in the Activity2. If it failed to find the sendMessage method in the Activity2 class then it will throw a NullpointerException.

Related

Android DataBinding new button setOnClickListener

I need to use the Android Camera.
Therefore I am using following Template: https://github.com/android/camera-samples/tree/main/Camera2SlowMotion
I added a Butten to the fragment_camera.xml
https://github.com/android/camera-samples/blob/main/Camera2SlowMotion/app/src/main/res/layout/fragment_camera.xml
<Button
android:id="#+id/change_focus_button"
android:layout_width="115dp"
android:layout_height="81dp"
android:text="#string/focusButtonText"
tools:layout_editor_absoluteX="13dp"
tools:layout_editor_absoluteY="473dp" />
In the CameraFragment.kt I now want to call a function when the button is clicked.
In my understanding I therefore need to create a setOnClickListener.
https://github.com/android/camera-samples/blob/main/Camera2SlowMotion/app/src/main/java/com/example/android/camera2/slowmo/fragments/CameraFragment.kt
I thought about adding following line in Line 309. that would call a function i then create. But the "." after fragmentCameraBinding.changeFocusButton is always red and won't go away.
fragmentCameraBinding.changeFocusButton.setOnClickListener { chnageFocuslen() }
What do I need to change / where do I need to add the OnClickListener?
Thank you very much in advance!
I had to download the sample because I couldn't see what the issue was from the snippets in your post.
The issue is that CameraFragment has two layout files, one in the default folder layout, and one in layout-land for landscape orientation. So you need to add your change_focus_button XML to both layout files to make it not nullable when you access it via fragmentCameraBinding in CameraFragment.

Questions related to android:onClick="selfDestruct" xml method

New to android and programming in general. This question might sound silly but I'd appreciate the answer. The question description and reasoning is at the beginning and the question is at the end of it all.
I want to apply a listener to a button in android. The way I understood from android.googlesource.com is that there is two way to do it:
applying an OnClickListener to the button in the activity.java
or
assign a method to my button in the xml layout using this
{#link android.R.attr#onClick android:onClick}
they gave the following xml layout example:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="selfDestruct"
android:text="#string/self_destruct" />
plus the the code in activity.java
public void selfDestruct(View view) {
// Kabloey
}
android.googlesource.com
Questions:
According to this: {#link android.R.attr#onClick android:onClick} android.R.attr in the example are the following:
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="#string/self_destruct"
?
Does this:
android:text="#string/self_destruct"
android:onClick="selfDestruct"
mean that the button called self_destruct registered as a listener?
If I want to add more than one button listener in xml form how do I write it in the java document?
Thank you in advance
Really appreciate it.
Does this:
android:text="#string/self_destruct" android:onClick="selfDestruct"
mean that the button called self_destruct registered as a listener?
The button isn't "called" anything, it just has the text of the value for #string/self_destruct defined in the strings.xml file.
But, yes, the public void selfDestruct(View view) method is the method that will be called for the listener that is setup by the XML.
If I want to add more than one button listener in xml form how do I write it in the java document?
You can only set one click listener for a View.
Yes, layout_height, layout_width and text are attributes. You
can learn more about android attributes
here.
But keep in mind, that different views can use the same attributes
in different way.
It does not. The android:text attribute in this sample just refer to a string-resource called self_destruct to decide which text should be shown within the button. To distinguish views you can use android:id.
As already mentioned by other people, you are able to specify only one onClickListener using XML.

Crash when clicking button with custom theme

I am creating a custom theme for button and using android:onClick event of Button from xml itself to handle the click of Button.
Due to some reason its crashing with below exception
java.lang.IllegalStateException: Could not find a method MyOnClick(View) in the activity class android.view.ContextThemeWrapper for onClick handler on view class android.widget.Button with id 'button1'
And its working fine if I just remove the theme attribute from the Button, below is my theme for Button
<style name="ButtonTheme" parent="#android:style/Widget.Button">
<item name="android:textColor">#FF0000</item>
<item name="android:shadowColor">#FF000000</item>
</style>
And my Button defined in xml as below,
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_margin="20dp"
android:onClick="MyOnClick"
android:theme="#style/ButtonTheme"
android:text="Button" />
Here is my java code as well,
public void MyOnClick(View view) {
switch (view.getId()) {
case R.id.button1:
getWindow().setStatusBarColor(getResources()
.getColor(R.color.statusBarColor));
getWindow().setNavigationBarColor(getResources()
.getColor(R.color.statusBarColor));
break;
default:
break;
}
}
So, what could be the reason for crashing? I am able to handle the click event if I remove android:theme="#style/ButtonTheme" attribute from Button Widget from xml.
I've never seen anybody applying the android:theme attribute to an individual View, but after a bit of googling I found out that this is indeed possible, but only since Android 5.0.
A hint of this can be seen at the end here.
And some more detail here.
As the second link explains, a ContextThemeWrapper is used to modify the theme associated with the base Context. However, since your Activity will need to hold on to its own theme, I can only imagine that a new ContextThemeWrapper is created and assigned as the new Context of your View. Since this new Context is not your Activity any more, your callback functions don't exist here and you get the error you describe.
You can use the debugger to prove this yourself (I used Android Studio, but you can probably use the IDE of your choice, the details might be different).
Run the app in debug mode with theme attribute set.
When you get the exception, the stacktrace will contain a reference to the View class where it invokes onClick.
Use this to add a breakpoint before the exception occurs.
Now run the app again in debug mode, click the button
When you hit the breakpoint evaluate the expression getContext(). You will see that this returns an object of type ContextThemeWrapper and it will have a member mBase which points back to your actual Activity, so getContext() itself does not return your Activity and does not have the callback functions you defined on your Activity.
Now remove the theme attribute, leave the breakpoint and run the app again.
When you hit the breakpoint, evaluate the expression getContext() again and you will see that this time it returns your Activity directly, which is why your callbacks work, if you don't set the theme attribute.
In short, it seems like you can't use the android:onClick attribute if you want to make use of this new feature, and you will have to manually assign an OnClickListener as described here
Sometimes when we add style to Button It affects default android clickable behavior.
Try adding property clickable="true" in <Button... />
Or
You can also add <item name="android:clickable" >true</item> to style of button.
After spending so much time on this, the thing that worked for me was to apply the theme in code setTheme(R.style.AppToolbar); in the onCreate() instead of ripping out all the android:OnClick from all the layouts.

Add custom XML properties to default android views

I have been searching around with google about this topic, but found no relevant information. It is clear to me how I can do it extending Views, but I don't want to extend anything.
I would like to somewhat "annotate" whichever android view (or whichever descendant of view) with custom properties and then retrieve their value in runtime.
Like this:
<TextView
custom:my_property_name="foo here"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/text_view"
android:text="Rule" />
Then once I have a reference to this TextView I would like to call a method like:
String myProperty = textView.getProperty("my_property_name");
myProperty.equals("foo here");
Is this possible? How?
Thanks.
At the very least you have to create your own class that subclasses one of the standard View classes (or View itself). The existing framework code does not read attributes that are not defined by Android and that are not part of the styleable declaration for that View.
Android documentation has a page describing creating your own views with your own XML attributes: http://developer.android.com/training/custom-views/create-view.html

Android activity loads wrong layout

I copied a .java class and .xml layout. I thought I renamed everything in order to create a new class, but the new class is loading the old layout when I start a new Intent. Am I missing someplace where I need to enter the name of the new layout file I have created from a copy of another class' layout?
I think I missed this line:
setContentView(R.layout.xxx)
This should do it!
If you have not set the launcher activity in manifest then you have to specify which Activity starts first
If you have set old XMl in setContentView(R.layout.xxx) then this loads old layout so check for proper xml.
After trying the other answers, try checking the following attribute on your layout element:
tools:context=".SignUpActivity">
That was it for me.

Categories

Resources