How to set Id of dynamic created layout?

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.

107476 次浏览

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);

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);

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.

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.

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>)

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());

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!

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.

For compatibility purposes use: ViewCompat.generateViewId()

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()