I\'m adding TextViews programmatically in a for-loop and add them to an ArrayList.
How do I use TextView.setId(int id)
? What Integer ID do I come up wit
From API level 17 and above, you can call: View.generateViewId()
Then use View.setId(int).
If your app is targeted lower than API level 17, use ViewCompat.generateViewId()
In order to dynamically generate View Id form API 17 use
generateViewId()
Which will generate a value suitable for use in setId(int)
. This value will not collide with ID values generated at build time by aapt for R.id
.
Also you can define ids.xml
in res/values
. You can see an exact example in android's sample code.
samples/ApiDemos/src/com/example/android/apis/RadioGroup1.java
samples/ApiDemp/res/values/ids.xml
The 'Compat' library now also supports the generateViewId()
method for API levels prior 17.
Just make sure to use a version of the Compat
library that is 27.1.0+
For example, in your build.gradle
file, put :
implementation 'com.android.support:appcompat-v7:27.1.1
Then you can simply use the generateViewId()
from the ViewCompat
class instead of the View
class as follow:
//Will assign a unique ID
myView.id = ViewCompat.generateViewId()
Happy coding !
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();
}
}
}
I use:
public synchronized int generateViewId() {
Random rand = new Random();
int id;
while (findViewById(id = rand.nextInt(Integer.MAX_VALUE) + 1) != null);
return id;
}
By using a random number I always have a huge chance of getting the unique id in first attempt.