Android: View.setID(int id) programmatically - how to avoid ID conflicts?

前端 未结 15 2513
眼角桃花
眼角桃花 2020-11-21 22:53

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

相关标签:
15条回答
  • 2020-11-21 23:32

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

    0 讨论(0)
  • 2020-11-21 23:36

    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.

    0 讨论(0)
  • 2020-11-21 23:38

    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
    
    0 讨论(0)
  • 2020-11-21 23:38

    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 !

    0 讨论(0)
  • 2020-11-21 23:40

    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();
            }
    
        }
    }
    
    0 讨论(0)
  • 2020-11-21 23:41

    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.

    0 讨论(0)
提交回复
热议问题