Programmatic Views how to set unique id's?
Just an addition to the answer of @phantomlimb,
while View.generateViewId()
require API Level >= 17,
this tool is compatibe with all API.
according to current API Level,
it decide weather using system API or not.
so you can use ViewIdGenerator.generateViewId()
and View.generateViewId()
in the
same time and don't worry about getting same id
import java.util.concurrent.atomic.AtomicInteger;
import android.annotation.SuppressLint;
import android.os.Build;
import android.view.View;
/**
* {@link View#generateViewId()}要求API Level >= 17,而本工具类可兼容所有API Level
* <p>
* 自动判断当前API Level,并优先调用{@link View#generateViewId()},即使本工具类与{@link View#generateViewId()}
* 混用,也能保证生成的Id唯一
* <p>
* =============
* <p>
* while {@link View#generateViewId()} require API Level >= 17, this tool is compatibe with all API.
* <p>
* according to current API Level, it decide weather using system API or not.<br>
* so you can use {@link ViewIdGenerator#generateViewId()} and {@link View#generateViewId()} in the
* same time and don't worry about getting same id
*
* @author fantouchx@gmail.com
*/
public class ViewIdGenerator {
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
@SuppressLint("NewApi")
public static int generateViewId() {
if (Build.VERSION.SDK_INT < 17) {
for (;;) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF)
newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
} else {
return View.generateViewId();
}
}
}
Android: View.setID(int id) programmatically - how to avoid ID conflicts?
According to View
documentation
The identifier does not have to be unique in this view's hierarchy. The identifier should be a positive number.
So you can use any positive integer you like, but in this case there can be some views with equivalent id's. If you want to search for some view in hierarchy calling to setTag
with some key objects may be handy.
How to assign unique ids to dynamically created Views?
Assign id
via code (programmatically)
- Manually set
id
s usingsomeView.setId(
int);
- The
int
must be positive, but is otherwise arbitrary- it can be whatever you want (keep reading if this is frightful.) - For example, if creating and numbering several views representing items, you could use their item number.
Normally we do:
To assign id -
for(int i =0 ; i < yourIDcount ; i++){
yourView.setId(i);
}
To get id -
View.findViewById(yourView.getId());
Also,
API 17
introduced View.generateViewId()
which generates a unique ID.
Check:
how-can-i-assign-an-id-to-a-view-programmatically and android-assign-and-retrieve-ids-dynamically.
How to set a unique id to dynamically generated views in Kotlin for Android?
You can generate unique id dynamically for your views using View.generateViewId()
function.
For you programmatically created layout or view, you can set id like this
container_overall.id = View.generateViewId()
How can I assign an ID to a view programmatically?
Android id
overview
An Android id
is an integer commonly used to identify views; this id
can be assigned via XML (when possible) and via code (programmatically.) The id
is most useful for getting references for XML-defined View
s generated by an Inflater
(such as by using setContentView
.)
Assign id
via XML
- Add an attribute of
android:id="@+id/
somename"
to your view. - When your application is built, the
android:id
will be assigned a uniqueint
for use in code. - Reference your
android:id
'sint
value in code using "R.id.
somename" (effectively a constant.) - this
int
can change from build to build so never copy an id fromgen/
package.name/R.java
, just use "R.id.
somename". - (Also, an
id
assigned to aPreference
in XML is not used when thePreference
generates itsView
.)
Assign id
via code (programmatically)
- Manually set
id
s usingsomeView.setId(
int);
- The
int
must be positive, but is otherwise arbitrary- it can be whatever you want (keep reading if this is frightful.) - For example, if creating and numbering several views representing items, you could use their item number.
Uniqueness of id
s
XML
-assignedid
s will be unique.- Code-assigned
id
s do not have to be unique - Code-assigned
id
s can (theoretically) conflict withXML
-assignedid
s. - These conflicting
id
s won't matter if queried correctly (keep reading).
When (and why) conflicting id
s don't matter
findViewById(int)
will iterate depth-first recursively through the view hierarchy from the View you specify and return the firstView
it finds with a matchingid
.- As long as there are no code-assigned
id
s assigned before an XML-definedid
in the hierarchy,findViewById(R.id.somename)
will always return the XML-defined View soid
'd.
Dynamically Creating Views and Assigning ID
s
- In layout XML, define an empty
ViewGroup
withid
. - Such as a
LinearLayout
withandroid:id="@+id/placeholder"
. - Use code to populate the placeholder
ViewGroup
withView
s. - If you need or want, assign any
id
s that are convenient to each view. Query these child views using placeholder.findViewById(convenientInt);
API 17 introduced
View.generateViewId()
which allows you to generate a unique ID.
If you choose to keep references to your views around, be sure to instantiate them with getApplicationContext()
and be sure to set each reference to null in onDestroy
. Apparently leaking the Activity
(hanging onto it after is is destroyed) is wasteful.. :)
Reserve an XML android:id
for use in code
API 17 introduced View.generateViewId()
which generates a unique ID. (Thanks to take-chances-make-changes for pointing this out.)*
If your ViewGroup
cannot be defined via XML (or you don't want it to be) you can reserve the id via XML to ensure it remains unique:
Here, values/ids.xml defines a custom id
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="reservedNamedId" type="id"/>
</resources>
Then once the ViewGroup or View has been created, you can attach the custom id
myViewGroup.setId(R.id.reservedNamedId);
Conflicting id
example
For clarity by way of obfuscating example, lets examine what happens when there is an id
conflict behind the scenes.
layout/mylayout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/placeholder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
To simulate a conflict, lets say our latest build assigned R.id.placeholder
(@+id/placeholder
) an int
value of 12
..
Next, MyActivity.java defines some adds views programmatically (via code):
int placeholderId = R.id.placeholder; // placeholderId==12
// returns *placeholder* which has id==12:
ViewGroup placeholder = (ViewGroup)this.findViewById(placeholderId);
for (int i=0; i<20; i++){
TextView tv = new TextView(this.getApplicationContext());
// One new TextView will also be assigned an id==12:
tv.setId(i);
placeholder.addView(tv);
}
So placeholder
and one of our new TextView
s both have an id
of 12! But this isn't really a problem if we query placeholder's child views:
// Will return a generated TextView:
placeholder.findViewById(12);
// Whereas this will return the ViewGroup *placeholder*;
// as long as its R.id remains 12:
Activity.this.findViewById(12);
*Not so bad
Android - Set my own unique integer id (not in resources) to many views created programmatically
As you are creating RadioGroups
and RadioButtons
from java, I suggest to create a map and use radiobutton reference as key and instance-color combination as value. assign a single checkChangedListener to all your radioButtons and process the event as follows
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
colorInstanceCombo = map.get(buttonView);
//use colorInstanceCombo to do your work
}
assigning ids dynamically can cause problems as id is an integer and your assigned ids may cause conflict with system assigned ids to other components.
android - set ID to the view programmatically
According to the API it's not forbidden or deprecated. Here is the best way of using it.
Create
res/values/ids.xml
and define<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="button1" />
<item type="id" name="button2" />
</resources>once you have that, you can than use
setId
button1.setId(R.id.button1);
button2.setId(R.id.button2);
Dynamically set id of a view
You can just use the View.setId(int)
for this. According to documentation id
need not to be unique in a tree heirarchy, you can use any (positive) Integer for the Views
you add programmatically.
Doc says
The identifier does not have to be unique in this view's hierarchy. The identifier should be a positive number.
if you want some other info attached with the View
you can tag objects to view using setTag()
, and look by findViewWithTag("obj");
see more about creating ids here https://stackoverflow.com/a/13241629/5235032
Related Topics
Import .CSV File to SQLite in Android
What Is the Benefit of Viewholder Pattern in Android
Android Remove Space Between Tabs in Tabwidget
When to Register/Unregister Broadcast Receivers Created in an Activity
Failed to Resolve Com.Android.Support:Appcompat-V7:22 and Com.Android.Support:Recyclerview-V7:21.1.2
How to Use Setarguments() and Getarguments() Methods in Fragments
Sliding Drawer Appear in All Activities
Delete Alarm from Alarmmanager Using Cancel() - Android
Android Setonclicklistener Method - How Does It Work
Resizing Layouts Programmatically (As Animation)
Ontaskremoved() Not Getting Called in Huawei and Xiaomi Devices
Popupwindow - Dismiss When Clicked Outside
Android - Save/Restore Fragment State
Activenetworkinfo.Type Is Deprecated in API Level 28
How to Store Images Using Sharedpreference in Android
Proguard Hell - Can't Find Referenced Class
Compile with Proguard Gives Simexception: "Local Variable Type Mismatch"
Show Download Progress Inside Activity Using Downloadmanager