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

前端 未结 15 2484
眼角桃花
眼角桃花 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:23
    int fID;
    do {
        fID = Tools.generateViewId();
    } while (findViewById(fID) != null);
    view.setId(fID);
    

    ...

    public class Tools {
        private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
        public static int generateViewId() {
            if (Build.VERSION.SDK_INT < 17) {
                for (;;) {
                    final int result = sNextGeneratedId.get();
                    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:24
    public String TAG() {
        return this.getClass().getSimpleName();
    }
    
    private AtomicInteger lastFldId = null;
    
    public int generateViewId(){
    
        if(lastFldId == null) {
            int maxFld = 0;
            String fldName = "";
            Field[] flds = R.id.class.getDeclaredFields();
            R.id inst = new R.id();
    
            for (int i = 0; i < flds.length; i++) {
                Field fld = flds[i];
    
                try {
                    int value = fld.getInt(inst);
    
                    if (value > maxFld) {
                        maxFld = value;
                        fldName = fld.getName();
                    }
                } catch (IllegalAccessException e) {
                    Log.e(TAG(), "error getting value for \'"+ fld.getName() + "\' " + e.toString());
                }
            }
            Log.d(TAG(), "maxId="+maxFld +"  name="+fldName);
            lastFldId = new AtomicInteger(maxFld);
        }
    
        return lastFldId.addAndGet(1);
    }
    
    0 讨论(0)
  • 2020-11-21 23:25

    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.

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

    inspired by @dilettante answer, here's my solution as an extension function in kotlin:

    /* sets a valid id that isn't in use */
    fun View.findAndSetFirstValidId() {
        var i: Int
        do {
            i = Random.nextInt()
        } while (findViewById<View>(i) != null)
        id = i
    }
    
    0 讨论(0)
  • 2020-11-21 23:29

    This works for me:

    static int id = 1;
    
    // Returns a valid id that isn't in use
    public int findId(){  
        View v = findViewById(id);  
        while (v != null){  
            v = findViewById(++id);  
        }  
        return id++;  
    }
    
    0 讨论(0)
  • 2020-11-21 23:30

    Since API 17, the View class has a static method generateViewId() that will

    generate a value suitable for use in setId(int)

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