72

I have 24 buttons in my layout, all these buttons do something similar so I want to create a generic function. But first I need to know the name (xml id) of he button.

This the XML code of the button:

  <Button
      android:id="@+id/add_04"
      android:layout_width="42dp"
      android:layout_height="wrap_content"
      android:layout_gravity="center"
      android:layout_marginLeft="15dp"
      android:background="@xml/zbuttonshape"
      android:onClick="onClick"
      android:text="@string/mas" />

I set android:onClick="onClick" for all the buttons.

In my activity I've create a new function onClick:

This the code I've tried:

public void onClick(View v) {
        String name = v.getContext().getString(v.getId());
        String name2 = context.getString(v.getId());
        String name3 = getString(v.getId());
        String name4 = getResources().getString(v.getId()); 
}

But when I try to get the name (in this case "add_04") I always get "false".

Finally I've found a solution with the following code:

import java.lang.reflect.Field;

String name5 = null;
Field[] campos = R.id.class.getFields();
for(Field f:campos){
     try{
        if(v.getId()==f.getInt(null)){
            name5 = f.getName();
            break;
        }
       }
       catch(Exception e){
        e.printStackTrace();
    }
}

Is there an easier way to get this ID?

starball
  • 20,030
  • 7
  • 43
  • 238
Richal
  • 843
  • 1
  • 6
  • 9

9 Answers9

165

like this:

/**
 * @return "[package]:id/[xml-id]"
 * where [package] is your package and [xml-id] is id of view
 * or "no-id" if there is no id
 */
public static String getId(View view) {
    if (view.getId() == View.NO_ID) return "no-id";
    else return view.getResources().getResourceName(view.getId());
}

I use this in view constructors to make more meaningful TAGs

Ωmega
  • 42,614
  • 34
  • 134
  • 203
gadget
  • 2,082
  • 2
  • 14
  • 11
43

The approach is misguided to begin with. If you want to associate a piece of arbitrary data (e. g. a string) with a view, that's what tag is for. The ID is numeric and it better stay that way. A word of caution though, tags are not unique in Android, watch for accidental tag collisions within the same view tree.

EDIT much later: the OP's issue was a case of an XY problem. That said, the question title alone is a legitimate question in its own right.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • Thanks, that what I need. With the property tag I can do it. String name = v.getTag().toString(); – Richal Feb 02 '13 at 10:44
  • 1
    Android Docs: Unlike IDs, tags are not used to identify views. Tags are essentially an extra piece of information that can be associated with a view. They are most often used as a convenience to store data related to views in the views themselves rather than by putting them in a separate structure. – Jeffrey Nov 06 '18 at 23:04
  • 6
    view.getResources().getResourceName(view.getId()); Return the full name for a given resource identifier. This name is a single string of the form package:type/id". – Jeffrey Nov 06 '18 at 23:12
  • 1
    getResources().getResourceEntryName(view.getId()); Returns the string representation of the view id only. – Jeffrey Nov 06 '18 at 23:16
32

Edit:

You have to use

getResources().getResourceEntryName(int resid);

If you want to retrieve the entry name associated to a resId

or

You can use getIdentifier() to retriece a resource identifier for the given resource name.

For instance:

int id = this.getResources().getIdentifier("yourtext", "string", this.getPackageName());
Blackbelt
  • 156,034
  • 29
  • 297
  • 305
  • 1
    Doesn't work for me - I get 'NullPointerException' is it always the same package name? – GyRo Mar 01 '15 at 13:34
  • 1
    @GyRo where do you get a `NPE`? Where are you executing that line of code? Are you trying to retrieve a `String` id ? – Blackbelt Mar 01 '15 at 13:44
  • The case can be found in the answer here: http://stackoverflow.com/questions/28729067/android-increment-button-in-loop-to-setvisibility/28729614#28729614 – GyRo Mar 02 '15 at 07:20
  • 1
    You are looking in the wrong class. Use "id" in place of "string" – Blackbelt Mar 02 '15 at 07:31
  • What is `yourtext` supposed to be? – IgorGanapolsky Sep 15 '15 at 17:15
  • @Ganapolsky is the value of the field "name", for which you want to retrieve the id – Blackbelt Sep 15 '15 at 17:18
  • I think you misunderstood the question. It is the other way around. OP has the id, and wants to get the field name – BeniBela Sep 11 '16 at 11:20
  • 5
    This should be the accepted answer, why? if I have 50 buttons in my application, then I have to set tag for each one and this is not the best approach. However, I can use `getResources().getResourceEntryName(int resid);` to easily get view entry id. +1 for providing this solution – blueware Nov 23 '16 at 10:08
19

You can check id of each button such way:

public void onClick(View v) {
    switch (v.getId()) {
    case R.id.add_04:
        Toast.makeText(MainActivity.this, "1", Toast.LENGTH_LONG).show();
        break;
    case R.id.add_05:
        Toast.makeText(MainActivity.this, "2", Toast.LENGTH_LONG).show();
        break;
    }
}
dilix
  • 3,761
  • 3
  • 31
  • 55
10
   Use this Approach to get View Id by Programming .
  <TextView
    android:id="@+id/tv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"
    />


    String id=getResources().getResourceEntryName(textView.getId());
    Toast.makeText(this,id,Toast.LENGTH_LONG).show();

You will get Result ; tv

Zafar Hussain
  • 264
  • 2
  • 10
7

You can put this toString() inside an Android View, it will return the String resource Id.

@Override
public String toString() {

    Context context;
    Resources r = null;

    context = getContext();

    if (context != null) {
        r = context.getResources();
    }

    String entryName = null;

    if (r != null)
        entryName = r.getResourceEntryName(getId());

    return entryName;
}
tausiq
  • 937
  • 1
  • 13
  • 23
3

Kotlin version (from @gadget) as view extension:

val View.stringId: String
    get() {
        return if (this.id == -0x1)
            "no-id"
        else
            this.resources.getResourceName(this.id)
    }
Gabriel
  • 237
  • 2
  • 5
  • Nice. It's even terser if you use assignment syntax and omit 'this' and 'return'. `val View.name: String get() = if (this.id == -0x1) "no-id" else resources.getResourceEntryName(id) ?: "error-getting-name"` – Patrick Steiger Jun 26 '18 at 17:14
2

It's a late answer but may useful someone looking out for a way to get the resource id (int) for any view / drawable / String programmatic.

image from res/drawable

int resID = getResources().getIdentifier("my_image", 
            "drawable", getPackageName());

view based on resource name

int resID = getResources().getIdentifier("my_resource", 
            "id", getPackageName());

string

int resID = getResources().getIdentifier("my_string", 
            "string", getPackageName()); 
King of Masses
  • 18,405
  • 4
  • 60
  • 77
0

The answer by @King of Masses is great. Here is my in Kotlin:

image from res/drawable

val viewId = context.resources.getIdentifier("my_image", "drawable", context.packageName)

view based on resource name

val viewId = context.resources.getIdentifier("my_textview_id", "id", context.packageName)

string

val viewId = context.resources.getIdentifier("my_string", "string", context.packageName)

Layout

val viewId = context.resources.getIdentifier("my_custom_layout", "layout", context.packageName)
Thiago
  • 12,778
  • 14
  • 93
  • 110