Android: automatically make variables for all IDs in xml
Asked Answered
C

5

21

I noticed one of the most tedious parts of Android development is the layout design, even with layout builder.

After setting up the graphics, then the layout, making variable associations with the layout elements is very tedious, such as ImageButton myButton = (ImageButton)findViewById(R.id.myButton);

in larger layouts, these can get tedious to keep track of (recalling the names of the elements) and then the need to add more variables in any kind of order gets frustrating.

To slightly mitigate this, it would be very convenient if all of the IDs I declared in the XML were automatically associated with their proper variables, and all of those datatypes were already included in that class

Is there something that already does this?

for instance if I write

 <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/myButton" android:id="@+id/myButton"></ImageButton>

then I would like the classes which include this layout to already have

 import android.ImageButton;

 ImageButton myButton;

 myButton = (ImageButton)findViewById(R.id.myButton);

is this a setting or a feature to request? I am using the Eclipse IDE and it would be very convenient

Cardialgia answered 1/8, 2011 at 21:47 Comment(2)
Not that I know of, but would be cool - maybe write it? :)Zimmer
Sure, I've never made an auto-code listener thing... how would I start? Would that portion of the Android AVD be open source as well?Cardialgia
S
16

Try using Android Annotations. It provides useful annotations to replace boilerplate code.

For instance, see @ViewById documentation: just declare the fields annotated

@ViewById
EditText myEditText;

@ViewById(R.id.myTextView)
TextView textView;

It replaces

EditText myEditText;

TextView textView;
@Override
public void onCreate(Bundle savedInstanceState) {
    [...]
    myEditText = (EditText) findViewById(R.id.myEditText);
    textView = (TextView) findViewById(R.id.myTextView);
}
Sec answered 2/8, 2011 at 19:44 Comment(1)
Looks great, but I'm programming with Xamarin Android, not native Android, and 10 years later it seems not implemented yet :/Lizarraga
P
35

I made a tool to automatically generate the Java code for tying layout XML's and program logic together.

Basically it takes an XML layout, and generates all the necessary Java code for you in an instant. There is support for basic member variables, ViewHolder pattern, ArrayAdapter, CursorAdapter and RoboGuice code types.

You can find it here: Android Layout Finder | Buzzing Android

EDIT: Original site is down, but mirror can be found here: https://dusunboy.github.io/android-layout-finder/

Prosaism answered 15/2, 2013 at 14:17 Comment(6)
Thanks for posting your answer! Please be sure to read the FAQ on Self-Promotion carefully. Also note that it is required that you post a disclaimer every time you link to your own site/product.Confess
Great tool. How about combining your answer with Andy's answer and generate java code with @ViewById annotations ? Could be an option in your tool to choose from the 2 waysHachmann
its just amazing . ..... good job I was looking for it from long time :-)Worker
This should be accepted as the answer, as this is what was initially askedTunesmith
very nice tool, thanks for sharing it with us, helps save time without having to use any 3rd party libraries. If you could update it to remove view casting when using SDK 26 it would be really nice.Archeology
Good job brother.Hemp
S
16

Try using Android Annotations. It provides useful annotations to replace boilerplate code.

For instance, see @ViewById documentation: just declare the fields annotated

@ViewById
EditText myEditText;

@ViewById(R.id.myTextView)
TextView textView;

It replaces

EditText myEditText;

TextView textView;
@Override
public void onCreate(Bundle savedInstanceState) {
    [...]
    myEditText = (EditText) findViewById(R.id.myEditText);
    textView = (TextView) findViewById(R.id.myTextView);
}
Sec answered 2/8, 2011 at 19:44 Comment(1)
Looks great, but I'm programming with Xamarin Android, not native Android, and 10 years later it seems not implemented yet :/Lizarraga
B
2

Since version 3.6 of android studio they have officially added the support of autometically view binding that's generates a binding class for each XML layout file. These classes contain direct references to all views that have an ID in the corresponding layout.

you can enable it by modifying your build.gradle file.

android {
  ...
  viewBinding {
      enabled = true
  }
}

If view binding is enabled for a module, a binding class is generated for each XML layout file that the module contains. Each binding class contains references to the root view and all views that have an ID.

For example, given a layout file called result_profile.xml The generated binding class will be called ResultProfileBinding.

Example:

private ResultProfileBinding binding;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = ResultProfileBinding.inflate(getLayoutInflater());
    View view = binding.getRoot();
    setContentView(view);
}

Please check the official documentation here.

Brezin answered 2/3, 2020 at 15:30 Comment(0)
A
0

That's a feature request. It's very good one and I think it would be pretty useful; on the other hand there are cases where it wouldn't work very well, for example if you are inflating views dynamically and don't know, at compile time, which view a particular Activity will inflate. However, I tend to think this case would be the exception rather than the rule.

The easiest way to do that would be to code a script that scans your layout XML files in search for components with ID's and creates .java files with the proper definitions. Then, your activities could derive from those auto-generated classes. Something like this:

When processed by your script, that generates a class:

class FooBarLayoutActivityBase extends Activity ... {
  protected ImageButton myButton;

  FooBarLayoutActivityBase() {
    myButton = (ImageButton)findViewById(R.id.myButton);
  }
}

Then, you can simply inherit from that base class to use the components...

The script approach is simple and doesn't require you to delve into the toolchain's code -- but you could also do it directly in the ADT plugin.

Aime answered 2/8, 2011 at 4:14 Comment(1)
You code will not work, since findViewById() method only works after call to setContentView methodHelaine
A
0

UPDATE : Android View Binding (AVB) Code Generator, this does exactly what i am going to say :|


REGEX!

I had the same problem and i tried to solve it myself so i turned into REGEX inside of search and replace of dear Android Studio. Personally i use ButterKnife for dependency injection with java annotation but the more important part is how to automate the procedure of turning ids in xml layout to java objects. Its kind of like the Android Layout Finder | Buzzing Android (the website has more features but old :( ) answer but with annotation result.

  1. go to your xml and select all of the ids with this regex ( \+id/.* ). To do that first press Ctrl + F to open the search panel, then make sure that the Regex checkbox is checked. then enter the regex ( \+id/.* ) inside the box and then press Ctrl + Alt + Shift + J to select all occurrences. Now Ctrl + C to copy them (u know the shortcut).

for example i had this layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layoutDirection="rtl"
    tools:context=".jobs.return_from_entrance.ReturnFromEntranceActivity"
    tools:ignore="HardcodedText">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <GridLayout
            android:id="@+id/return_entrance_grid_layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:columnCount="2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="شماره برگشت" />

            <TextView
                android:id="@+id/return_entrance_return_entrance_number_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="123123123"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="@string/owner_of_cargo" />

            <TextView
                android:id="@+id/return_entrance_owner_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="الجی"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="تاریخ و زمان" />

            <TextView
                android:id="@+id/return_entrance_time_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="12/12/12/ 12:12"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="نوع حواله" />

            <TextView
                android:id="@+id/return_entrance_kind_of_order_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="حواله"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="خریدار" />


            <TextView
                android:id="@+id/return_entrance_buyer_name_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="علی امیدی"
                android:textColor="@android:color/black"
                android:textSize="18sp" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="مقصد" />

            <TextView
                android:id="@+id/return_entrance_destination_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="آزادی"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="وزن ناخالص" />

            <TextView
                android:id="@+id/return_entrance_gross_weight_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="123"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="شماره جواز" />

            <TextView
                android:id="@+id/return_entrance_permission_number_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="126545643"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="شماره بارنامه" />

            <TextView
                android:id="@+id/return_entrance_waybill_number_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="654"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="زمان ورود" />

            <TextView
                android:id="@+id/return_entrance_enter_time_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="21/12/12 22:22"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="زمان خروج" />

            <TextView
                android:id="@+id/return_entrance_exit_time_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="21/12/12 22:22"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="محوطه بارگیری" />

            <TextView
                android:id="@+id/return_entrance_load_location_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="حیاط"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="نیاز به جرثقیل" />

            <TextView
                android:id="@+id/return_entrance_is_crane_needed_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="ندارد"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="نیاز به لیفتراک" />

            <TextView
                android:id="@+id/return_entrance_is_forklift_needed_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="ندارد"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <CheckBox
                android:id="@+id/return_entrance_internal_return_entrance_checkbox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="@dimen/margin_large"
                android:layout_marginStart="@dimen/margin_medium"
                android:layout_marginTop="@dimen/margin_large"
                android:text="خروج داخلی" />

            <View
                android:layout_width="0dp"
                android:layout_height="0dp" />

            <CheckBox
                android:id="@+id/return_entrance_warehouse_delivery_checkbox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="@dimen/margin_large"
                android:layout_marginStart="@dimen/margin_medium"
                android:layout_marginTop="@dimen/margin_large"
                android:text="تحویل در انبار" />

            <View
                android:layout_width="0dp"
                android:layout_height="0dp" />

            <Button
                android:id="@+id/return_entrance_location_delivery_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/margin_large"
                android:text="تحویل در محل" />

            <View
                android:layout_width="0dp"
                android:layout_height="0dp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="عکس راننده" />

            <ImageView
                android:id="@+id/return_entrance_driver_image_view"
                android:layout_width="120dp"
                android:layout_height="120dp"
                android:layout_gravity="center"
                android:layout_marginTop="@dimen/item_margin"
                android:src="@drawable/ic_account_circle_black_24dp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="@string/name_of_driver" />

            <TextView
                android:id="@+id/return_entrance_name_of_driver_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="علی امیدی"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="@string/kind_of_car" />

            <TextView
                android:id="@+id/return_entrance_kind_of_car_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="وانت مزدا"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="@string/plaque" />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/margin_large"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/return_entrance_plaque_2digit_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/plaque_background"
                    android:padding="10dp"
                    android:text="11"
                    android:textColor="@android:color/black"
                    android:textSize="10pt"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/return_entrance_plaque_6digit_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/plaque_background"
                    android:padding="10dp"
                    android:text="999ج77"
                    android:textColor="@android:color/black"
                    android:textSize="10pt"
                    android:textStyle="bold" />
            </LinearLayout>
        </GridLayout>

        <Button
            android:id="@+id/return_entrance_barcode_scan_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_margin="@dimen/margin_small"
            android:drawableStart="@drawable/ic_barcode"
            android:padding="@dimen/margin_medium"
            android:text="@string/scan_barcode"
            android:textSize="18sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/return_entrance_grid_layout" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/return_entrance_cargo_list_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/return_entrance_barcode_scan_button" />

        <GridLayout
            android:id="@+id/return_entrance_bottom_grid_layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:columnCount="2"
            android:layoutDirection="rtl"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/return_entrance_cargo_list_recycler_view">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="میزان موجودی کالای قابل تحویل" />

            <TextView
                android:id="@+id/return_entrance_deliverable_availability_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin"
                android:text="50"
                android:textColor="@android:color/black"
                android:textSize="18sp" />

        </GridLayout>

        <LinearLayout
            android:id="@+id/return_entrance_bottom_linear_2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="vertical"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/return_entrance_bottom_grid_layout">

            <Button
                android:id="@+id/return_entrance_cost_report_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/margin_medium"
                android:text="گزارش هزینه" />

            <Button
                android:id="@+id/return_entrance_confirm_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/margin_medium"
                android:text="تایید برگشت" />

        </LinearLayout>

    </android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>

a lot of text views to fill, huh?

  1. go to your java class and paste the copied ids(Ctrl + V). so we have bunch of ids which we want to change them into java objects. in our example, my ids would be like this :

    +id/return_entrance_grid_layout"
    +id/return_entrance_return_entrance_number_text_view"
    +id/return_entrance_owner_text_view"
    +id/return_entrance_time_text_view"
    ...
    

Its time to find and replace! so first we hit Ctrl + R to open the find and replace panel. (make sure the REGEX checkbox is checked) now im going to do some find and replaces to get the ideal result:

  1. Find : \+id/(.*)" Replace with: @BindView(R.id.$1) so we will have this:

    @BindView(R.id.return_entrance_grid_layout)
    @BindView(R.id.return_entrance_return_entrance_number_text_view)
    @BindView(R.id.return_entrance_owner_text_view)
    @BindView(R.id.return_entrance_time_text_view)
    ...
    

now its time to define each variable type and name them. my xml naming has WHERE_DESCRIPTION_WHAT pattern, ( something like this ). so for the variable name i want to remove the WHERE part. and then define the object type. so here we go:

  1. Find: (@BindView\(R\.id\.return_entrance_(.*)_text_view\)) Replace with: $1 TextView $2TextView; the result will be:

    @BindView(R.id.return_entrance_grid_layout)
    @BindView(R.id.return_entrance_return_entrance_number_text_view) TextView return_entrance_numberTextView;
    @BindView(R.id.return_entrance_owner_text_view) TextView ownerTextView;
    @BindView(R.id.return_entrance_time_text_view) TextView timeTextView;
    @BindView(R.id.return_entrance_kind_of_order_text_view) TextView kind_of_orderTextView;
    ...
    

(just hit a Ctrl + Alt + L to reformat your code) the names are ulgy :( . so we do this to camelCase! :

  1. Find: TextView \b(.*)_(.*) Replace With: TextView $1\u$2 and the result will be:

    @BindView(R.id.return_entrance_owner_text_view)
    TextView ownerTextView;
    @BindView(R.id.return_entrance_time_text_view)
    TextView timeTextView;
    @BindView(R.id.return_entrance_kind_of_order_text_view)
    TextView kind_ofOrderTextView;
    @BindView(R.id.return_entrance_buyer_name_text_view)
    TextView buyerNameTextView;
    @BindView(R.id.return_entrance_destination_text_view)
    TextView destinationTextView;
    

if you repeat the last part, any name that has more than one underline, each _ will be replaced with the Uppercase of the next character. so in this example if i do the Find: TextView \b(.*)_(.*) Replace With: TextView $1\u$2 again, my TextView kind_ofOrderTextView; will be TextView kindOfOrderTextView;

It may seem a bit complicated but when u get used to it, it becomes so fast and it becomes so more useful! for example imagine in an MVP, u have a Model with the same String names of the TextViews, so u can do this to set all of their texts' from the Model with similar approach...

Acetone answered 30/7, 2018 at 11:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.