83

I want to give ID to some views (textview ,imageview etc) in a layout that is programmetically created. So what is the best way to set ID.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
abhishek ameta
  • 2,326
  • 7
  • 28
  • 35

10 Answers10

134

You create an ids.xml file and place all your required ids in it as below

<?xml version="1.0" encoding="utf-8"?>
<resources>
        <item type="id" name="layout1" />
        <item type="id" name="layout2" />
        <item type="id" name="layout3" />
</resources>

Now for your dynamically created layouts or views you can use these ids as below

new_layout1.setId(R.id.layout1);
new_view2.setId(R.id.layout2);
new_layout3.setId(R.id.layout3);

I hope it may help you.

Brigham
  • 14,395
  • 3
  • 38
  • 48
Yugandhar Babu
  • 10,311
  • 9
  • 42
  • 67
  • My bad, it does work. But still, it's never good not to omit encoding and xml version declarations. – Arnthor May 20 '12 at 11:45
  • 19
    @Nordvind I given an idea to abhishek ameta not complete solution. He didn't mentioned any android version requirements. declaration is basic thing, so any android developer will write in *.xml file. **Am I told it will work in all versions of android??** What is wrong with my code ? If you have same requirement, you are using my answer and got any problem ask me, don't comment like this. – Yugandhar Babu May 21 '12 at 10:21
  • 1
    @Nordvind with another example of how useless SO's voting system is. Too bad there's no way to downvote comments. – Glenn Maynard Apr 18 '13 at 23:12
  • Hey, its good piece of code but when I tried its giving me resource not found exception. – Tombeau Sep 17 '13 at 07:51
  • Zaps: I'm having the same problem in my emulator. Where you able to figure out what the problem was? – IcedDante Nov 02 '13 at 15:15
  • @Nordvind maybe it's time to reconsider that vote :-) As you can see, answer has been fixed since. – Sampo Sarrala - codidact.org Mar 15 '14 at 22:04
  • @SampoSarrala it is indeed, so I removed my downvote. – Arnthor Mar 17 '14 at 07:34
  • 11
    this still doesn't explain how to have a dynamically made id set – Eggcellentos Mar 11 '18 at 20:49
  • 3
    The point of having dynamically created views is you might not know how many/much of those you'll need or when you'll need them. Presetting the ID's in resources wouldn't help much. – landrykapela May 01 '20 at 08:58
77

Google finally realized the need of generating unique IDs for programmatically created views...

From API level 17 and above, one can use View.generateViewId() like this:

view.setId(View.generateViewId());

For apps targeting API level 16 or lower, use ViewCompat.generateViewId() instead:

view.setId(ViewCompat.generateViewId());
JensV
  • 3,997
  • 2
  • 19
  • 43
Varun Bhatia
  • 4,326
  • 32
  • 46
20

create folder res/values/ids.xmland

<?xml version="1.0" encoding="utf-8"?>

<resources>   
   <item name="refresh" type="id"/>   
   <item name="settings" type="id"/>        
</resources>

in Activity class call like this

ImageView refreshImg = new ImageView(activity);
ImageView settingsImg = new ImageView(activity); 

     refreshImg.setId(R.id.refresh);
     settingsImg .setId(R.id.settings);
NagarjunaReddy
  • 8,621
  • 10
  • 63
  • 98
15

This wont work:

layout.setId(100);

But, this will:

int id=100;
layout.setId(id);

also, this one too (credit: Aaron Dougherty):

layout.setId(100+1);
Krishna Raj Salim
  • 7,331
  • 5
  • 34
  • 66
jeet
  • 29,001
  • 6
  • 52
  • 53
  • [As mentioned here](http://stackoverflow.com/a/24721203/1221537), this solution will generate an editor validation error (Expected resource of type id), but it will compile just fine. – adamdport Oct 16 '14 at 21:23
  • 4
    actually it doesn't If you do int id=100.apparently if you add up numbers it works fine. Don't get that xD – Mateusz Winnicki Nov 12 '14 at 23:46
  • 3
    /thank you @MateuszWinnicki, Oddly enough adding made the difference. setId(100) does not work, but setId(99+1) does work – Aaron Dougherty Mar 21 '16 at 23:09
  • @jeet is it possible the id 100 collides with another one automatically set to 100 by the system ? – YoussefDir Apr 15 '20 at 03:36
9

For compatibility purposes use: ViewCompat.generateViewId()

Sanf0rd
  • 3,644
  • 2
  • 20
  • 29
2

If you are putting a group of components repeatedly into a layout programmatically like below:

<LinearLayout>

      <ImageView>
      <TextView>
      <Button>

      <ImageView>
      <TextView>
      <Button>

      <ImageView>
      <TextView>
      <Button>

      ...
</LinearLayout>

then,you can use for loop and give ids accordingly:

for(int i=0;i<totalGroups;i++)
{
    ImageView img;
    TextView tv;
    Button b;

    ... // set other properties of above components

    img.setId(i);
    tv.setId(i);
    b.setId(i);

    ... //handle all events on these components here only

    ... //add all components to your main layout
}

Or if just one group of component you want to add,you can use any integer number which is large and don't conflict with other component's ids in Resources.It won't be much conflicting.

Hiral Vadodaria
  • 19,158
  • 5
  • 39
  • 56
1

I went about it in a different way.
Created my own R.id HashMap.
Than used the value for the view.setID() part.
String is the id, Integer its value

Private HashMap<String, Integer> idMap= new HashMap<String, Integer>();
private int getRandomId(){

    boolean notInGeneralResourses = false;
    boolean foundInIdMap = false;

    String packageName = mainActivity.getPackageName();
    Random rnd = new Random();
    String name ="";

    //Repaet loop in case random number already exists
    while(true) {

        // Step 1 - generate a random id
        int generated_id = rnd.nextInt(999999);

        // Step 2 - Check R.id
        try{
            name = mainActivity.getResources().getResourceName(generated_id);
        }catch(Exception e){
            name = null;
        }

        notInGeneralResourses = false;
        if (name == null || !name.startsWith(packageName)) {
            notInGeneralResourses = true;
        }else{
            notInGeneralResourses = false;
            localLog("Found in R.id list.");
        }

        // Step 3 - Check in id HashMap
        if(notInGeneralResourses){
            List<Integer> valueList = new ArrayList<Integer>(idMap.values());

            foundInIdMap = false;
            for (Integer value : valueList) {
                if (generated_id == value) {
                    foundInIdMap = true;
                    localLog("Found in idMAp.");
                }
            }
        }

        // Step 4 - Return ID, or loop again.
        if (!foundInIdMap) {
            localLog("ID clear for use. "+generated_id);
            return generated_id;
        }
    }
}

and to set:

 String idName = "someName";
 int generated_R_id = getRandomId();
 idMap.put(idName,generated_R_id);

 someView.setId(idMap.get(idName));

Now, at any point you can just:

ImageView test = (ImageView) 
mainActivity.findViewById(idMap.get("somName"));

and to test it -

    test.setImageResource(R.drawable.differentPic);

P.S. I've written it like this for ease of explain.
Obviously it can be written better andmore compact.

RazVan
  • 36
  • 7
0

Try this code! This should help give an idea.

activity_prac_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

<TextView
    android:text="@string/edit_message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/display_txt"
    android:textStyle="bold"
    android:textSize="18sp"
    android:textAlignment="center"
    android:layout_gravity="center_horizontal"/>

<GridLayout
    android:id="@+id/my_grid"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:rowCount="4">


<LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/linear_view">

    <Button
        android:text="@string/button_send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/my_btn"
        android:layout_gravity="center_horizontal"/>

    <TextView
        android:text="@string/edit_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/my_txt"
        android:textSize="18sp"
        />

</LinearLayout>
</GridLayout>
</LinearLayout>

here's the rest of code

 public class AnotherActivity extends AppCompatActivity {

private int count = 1;

List<Integer> gridArray;
private TextView myDisplayText;
@Override
protected void onCreate( Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    gridArray = new ArrayList<>();
    gridArray.add(Integer.valueOf(1));
    setContentView(R.layout.activity_prac_main);



    findViews();


}
private void findViews(){

    GridLayout gridLayout = (GridLayout)findViewById(R.id.my_grid);
    gridLayout.setColumnCount(4);
    LinearLayout linearLayout = (LinearLayout) gridLayout.findViewById(R.id.linear_view);
    linearLayout.setTag("1");
    Button myButton = (Button) linearLayout.findViewById(R.id.my_btn);
    myButton.setTag("1");
    TextView myText = (TextView) linearLayout.findViewById(R.id.my_txt);
    myText.setText("1");

    myDisplayText = (TextView) findViewById(R.id.display_txt);


    myButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            TextView txt = (TextView) view;
            myDisplayText.setText("PRESS " + txt.getTag().toString());
            if(count < 24) {

                createView();
            }
            else{
                dialogBox();
            }
        }
    });
}

private void createView(){

    LinearLayout ll = new LinearLayout(this);
    ll.setId(Integer.valueOf(R.id.new_view_id));
    ll.setTag(String.valueOf(count+1));

    Button newBtn = createButton();
    newBtn.setId(Integer.valueOf(R.id.new_btn_id));
    newBtn.setTag(String.valueOf(count+1));

    TextView txtView = createText();
    txtView.setId(Integer.valueOf(R.id.new_txt_id));
    txtView.setTag(String.valueOf(count+1));
    txtView.setText(String.valueOf(count+1));

    GridLayout gridLayout = (GridLayout)findViewById(R.id.my_grid);


   ll.addView(newBtn);
    ll.addView(txtView);
    ll.setOrientation(LinearLayout.VERTICAL);

    gridLayout.addView(ll);



        count++;

}

private Button createButton(){
    Button myBtn = new Button(this);
    myBtn.setText(R.string.button_send);
    myBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            TextView txt = (TextView) view;
            myDisplayText.setText("PRESS " + txt.getTag().toString());
            if(count < 24) {

                createView();
            }
            else{
                dialogBox();
            }
        }
    });


    return myBtn;
}
public void dialogBox() {
    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
    alertDialogBuilder.setMessage("GRID IS FULL!");
    alertDialogBuilder.setPositiveButton("DELETE",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface arg0, int arg1) {
                    GridLayout gridLayout = (GridLayout)findViewById(R.id.my_grid);
                    gridLayout.removeAllViews();
                    count = 0;
                    createView();

                }
            });

    alertDialogBuilder.setNegativeButton("CANCEL",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface arg0, int arg1) {

                }
            });

    AlertDialog alertDialog = alertDialogBuilder.create();
    alertDialog.show();
}
private TextView createText(){
    TextView myTxt = new TextView(this);
    myTxt.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);

    return myTxt;
}

}

As you can see ids were created in res -> values -> ids file.

when creating views dynamically id is the same for the views.

Each TextView share same id. Each Button share same id. each layout share same id.

Ids are only important to access the contents of views.

However the Tag is what makes each view unique to each other.

Hope this helps you out!

0

All you need to do is call ViewCompat.generateViewId()

For Example:

val textView = TextView(this)
textView.text = "Hello World"
textView.setLayoutParams(ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT))
textView.id = ViewCompat.generateViewId()
EdgeDev
  • 2,376
  • 2
  • 20
  • 37
-1

You can define your Ids as resources and then use setId() of the view to set it. In a xml file, define the ID's like:

<resources>
  <item type="id">your id name</item>
</resources>

then, use in the java file as..

layout.setId(R.id.<your id name>)
Lavekush Agrawal
  • 6,040
  • 7
  • 52
  • 85
Khawar
  • 5,197
  • 4
  • 28
  • 52