Programmatic Views how to set unique id's? Programmatic Views how to set unique id's? android android

Programmatic Views how to set unique id's?


Just want to add to Kaj's answer, from API level 17, you can call

View.generateViewId()

then use the View.setId(int) method.

In case you need it for targets lower than level 17, here is its internal implementation in View.java you can use directly in your project:

private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);/** * Generate a value suitable for use in {@link #setId(int)}. * This value will not collide with ID values generated at build time by aapt for R.id. * * @return a generated ID value */public static int generateViewId() {    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;        }    }}

ID number larger than 0x00FFFFFF is reserved for static views defined in the /res xml files. (Most likely 0x7f****** from the R.java in my projects.)

From the code, somehow Android doesn't want you to use 0 as a view's id, and it needs to be flipped before 0x01000000 to avoid the conflits with static resource IDs.


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


Since support library 27.1.0 there's generateViewId() in ViewCompat

ViewCompat.generateViewId()