How to set Id of dynamic created layout?
Asked Answered
E

10

85

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.

Egidio answered 20/1, 2012 at 6:4 Comment(0)
R
136

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.

Ruyle answered 20/1, 2012 at 6:15 Comment(9)
My bad, it does work. But still, it's never good not to omit encoding and xml version declarations.Graham
@Nordvind I given an idea to abhishek ameta not complete solution. He didn't mentioned any android version requirements. <?xml ... > 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.Ruyle
@Nordvind with another example of how useless SO's voting system is. Too bad there's no way to downvote comments.Misstate
Hey, its good piece of code but when I tried its giving me resource not found exception.Sluggish
Zaps: I'm having the same problem in my emulator. Where you able to figure out what the problem was?Trustee
@Nordvind maybe it's time to reconsider that vote :-) As you can see, answer has been fixed since.Haimes
@SampoSarrala it is indeed, so I removed my downvote.Graham
this still doesn't explain how to have a dynamically made id setMandymandych
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.Nock
A
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());
Angeles answered 22/2, 2016 at 10:29 Comment(3)
Also you can use ViewCompat.generateViewId() if you are targeting a lower API levelHarriettharrietta
This is the correct answer and the only dynamic way of creating an id.Deuno
How would i access that very id that i've just generated?Vicechancellor
C
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);
Caeoma answered 20/1, 2012 at 6:9 Comment(2)
It was asked about dynamically created layout.Graham
that's how ---> create folder res/values/ids.xmlCalculating
F
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);
Faulk answered 20/1, 2012 at 6:6 Comment(4)
As mentioned here, this solution will generate an editor validation error (Expected resource of type id), but it will compile just fine.Confuse
actually it doesn't If you do int id=100.apparently if you add up numbers it works fine. Don't get that xDUnlace
/thank you @MateuszWinnicki, Oddly enough adding made the difference. setId(100) does not work, but setId(99+1) does workObscure
@Faulk is it possible the id 100 collides with another one automatically set to 100 by the system ?Rachellrachelle
P
9

For compatibility purposes use: ViewCompat.generateViewId()

Pretty answered 16/11, 2018 at 4:16 Comment(0)
H
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.

Harmonium answered 20/1, 2012 at 6:26 Comment(1)
how to fetch values of textview and all other components ? Please elaborate more.Insolent
C
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.

Contiguous answered 15/11, 2018 at 14:32 Comment(0)
J
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!

Javed answered 19/12, 2016 at 6:34 Comment(0)
N
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()
Neoteny answered 3/2, 2019 at 18:56 Comment(0)
S
-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>)
Silas answered 20/1, 2012 at 6:38 Comment(1)
resource items that refers to id's must have a name param and must have an empty bodyTollbooth

© 2022 - 2024 — McMap. All rights reserved.