Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possibility to add parameters in button xml?

I currently have an activity with some buttons.

In my xml, buttons are defined like this:

    <ImageButton (...) android:onClick="GoToPageX"/>

and I have in my activity:

public void GotoPageX() {
    startActivity(new Intent(this, PageX.class));
    finish();

}

The problem is that I have hundreds of buttons and do not want to write

<ImageButton (...) android:onClick="GoToPage1"/>
<ImageButton (...) android:onClick="GoToPage2"/>
<ImageButton (...) android:onClick="GoToPage3"/>
...
<ImageButton (...) android:onClick="GoToPage100"/>

and all the scripts.

I am now using

public void GotoPage( int i) {
    startActivity(new Intent(getBaseContext(), activities.get(i)));
    finish();
}

and would like to give the parameter i from the xml, is that possible?

Thank a lot for any help.

like image 758
Waza_Be Avatar asked Apr 18 '11 18:04

Waza_Be


3 Answers

It is not directly possible. However, maybe you could use android:tag to get your parameter.

<ImageButton (...) android:onClick="goToPage" android:tag="25"/>

public void goToPage(View v) {
    String pageNumber = v.getTag().toString(); 
    /* ... */
}
like image 78
OcuS Avatar answered Nov 01 '22 06:11

OcuS


You could also do this by enabling data binding and using a lambda expression for the onClick value. This way is especially useful if you plan to use multiple inputs of different types. Here's an example of a simple MainActivity.xml in which this strategy is used.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="main" type="com.example.android.myapp.MainActivity" />
    </data>
    <LinearLayout android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
        <ImageButton (...) android:onClick='@{() -> main.GotoPage(1,"one")}'/>
        <ImageButton (...) android:onClick='@{() -> main.GotoPage(2,"two")}'/>
        <ImageButton (...) android:onClick='@{() -> main.GotoPage(3,"three")}'/>
        ...
        <ImageButton (...) android:onClick='@{() -> main.GotoPage(100,"one hundred")}'/>
    </LinearLayout>
</layout>

and in MainActivity.java

public void GotoPage(int i, String otherVariable) {
    /** code using i and otherVariable **/
}

UPDATE: For those who don't know how to set up data binding, I will explain it here so you don't have to google around for it. First, enable dataBinding in the build.gradle file:

android {
    ...
    dataBinding {
        enabled = true
    }
    ...
}

Also, make sure jcenter() is in your repositories.

Then, go to the XML of the layout where onClick will be used and wrap its layout in a layout tag with a data section like this:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="main" type="com.example.android.yourapp.MainActivity" />
    </data>
    <YourLayout>
        ...
    </YourLayout>
</layout>

For the variable tag's type parameter, you need to put the class that will contain the function which onClick points to. In this example, I will use the main activity class, which is named MainActivity in my test project.

After you have your layout wrapped in a layout tag like in the example above, clean the project in Android Studio. You may also need to invalidate cache/restart or close and reopen Android Studio.

Next, if the the layout with onClick you are trying to set up data binding for is the same layout set by setContentView in your main activity class, open the file that contains your main activity class. If the layout with onClick you are trying to set up data binding for is inflated programmatically in a different file, open the file in which the layout is inflated instead.

Add these imports to that file:

import com.example.android.yourapp.databinding.YourLayoutBinding;
import android.databinding.DataBindingUtil;

That first class you are importing is generated when you clean the project (and possibly have to invalidate cache/restart) and is automatically named after the XML file you added the layout wrapper to. If the layout file is named your_layout.xml, the import class will be named YourLayoutBinding. The exact import path will depend on your app name and structure, but it will always be within a databinding parent class.

The next step depends on whether the layout you are adding data binding to is set with setContentView or is inflated with inflate. Both versions of the following step make use of the method setMain. The setMain method is automatically generated and named using the value of the name parameter in the layout wrapper we added. Since we put name="main", the method is called setMain.


If the layout you are adding data binding to is the same layout set by setContentView find the line in your main activity class that looks like setContentView(R.layout.your_layout); and change it to use DataBindingUtil.setContentView instead of setContentView, adding this as its first argument. Use binding.setMain to point the layout's main variable to the current activity.

YourLayoutBinding binding = DataBindingUtil.setContentView(this, R.layout.your_layout);
binding.setMain(this);

If the layout you are adding data binding to is not set by setContentView but rather inflated go to where it is inflated in your code. It should look something like this:

return inflater.inflate(R.layout.your_layout, container, false);

Modify it to use DataBindingUtil.inflate, adding the previous inflater as its first argument. Use binding.setMain to point the layout's main variable to the main activity, and use binding.getRoot() to get the view. It should end up like this:

YourLayoutBinding binding = DataBindingUtil.inflate(inflater, R.layout.your_layout, container, false);
binding.setMain((MainActivity) getActivity());
return binding.getRoot();

Now the data binding is ready to use. Add a function for onClick to point to within your main activity class.

public void exampleFunction(int number, String text) {
    System.out.println("Number: " + number + ", Text: " + text);
}

You can call it from the layout you added data binding to using a lambda expression. This example function doesn't require a View, so it can be used like this:

<Button android:id="@+id/buttonID"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textSize="26sp"
    android:text="Test"
    android:onClick='@{() -> main.exampleFunction(123, "test")}'/>

Make sure to use single quotes around the value for onClick if you plan on using a String input.

If you do need to pass the button's view to your function, simply add a View parameter to your function's required arguments and use a lambda expression like this instead:

<Button android:id="@+id/buttonID"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textSize="26sp"
    android:text="Test"
    android:onClick='@{(view) -> main.exampleFunction(view, 123, "test")}'/>
like image 3
omikes Avatar answered Nov 01 '22 04:11

omikes


If you will create some layout element in xml you can use there

<ImageButton
    android:id="@+id/some_id_value" />

where some_id_value is kind of unique string which will be translate into id which is kept in R.java (better for you- don't change anything there) than in code you can get that id by using

R.id.some_id_value

read a little bit there that's really basics.

like image 2
Robert Avatar answered Nov 01 '22 06:11

Robert