以编程方式为视图创建资源 ID

sty*_*972 5 android view android-resources

View包含一个方法setId(int)。我的问题是,如何以编程方式为对象提供一个不与任何资源 ID 重叠的 ID R

Bal*_*yák 5

根据文档View.generateViewId()在 API 级别 17 中添加将生成适合在setId(int). 此值不会与 aapt 在构建时生成的 ID 值冲突R.id

我进行了试验以View.generateViewId()了解它的行为方式。这是我的发现。

  • 生成的 ID 将从 1 开始,每次调用时都会递增 (1, 2 , 3...)
  • generateViewId() 将保留返回的最后一个 ID,并将在整个应用程序生命周期中从那里继续。例如,如果设备旋转前的最后一个 ID 为 4,则旋转后的下一个 ID 为 5。

重要的是要注意,例如,如果您在应用程序的onCreate()方法中通过generateViewId()每次调用在运行时设置视图,则在您的设备旋转后,默认情况下onCreate()会再次调用并且您的视图将收到与旋转前不同的 ID

Android 有一项功能可以在设备旋转后自动恢复您的视图状态 - 例如,您输入到 EditText 视图中的文本,CheckBox 的选中状态 - 但它仅在视图具有持久 ID 时才有效。所以在上面的例子中,这种状态恢复是行不通的——你的 EditText 视图将丢失输入,你必须再次输入你需要输入的任何内容——因为视图每次生成时都会收到不同的 ID。要解决此问题,您需要在活动生命周期中维护 ID。

我发现 Android 为 XML 中定义的对象分配了数十亿的 ID。这是只有我的应用程序的几个预定义的标识采取了现实生活中的ID:2131427423.所以它看起来是相当安全的,以你自己的自由裁量权使用低标识而没有调用generateViewId()。在我的简单应用程序中,我通过从 1 开始分配 ID 来模仿它,增加 1,并且它起作用了。这是从我的应用程序中提取的示例:

public class MainActivity extends AppCompatActivity {
    // since our lastAllocatedViewId will reset on device rotation
    // regenerated views will receive the same ID
    private int lastAllocatedViewId = 0;

    private ArrayList<QuizQuestions> quizQuestions;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // read quizQuestions from xml at runtime;
        quizQuestions = parseQuizQuestionsXml();

        // we will dynamically add quiz question views to this view
        // depending on how many quizQuestions are in the XML config
        LinearLayout container = (LinearLayout) findViewById(R.id.quiz_questions_container);

        // generate a view for each quiz question
        for (int i = 0; i < quizQuestions.size(); i++) {
            LinearLayout quizQuestionView = (LinearLayout) inflater.inflate(R.layout.quiz_question_template, parent, false);

            quizQuestionView.setId(lastAllocatedViewId++);

            (...) // do some work on our newly generated view

            // then add it to the quiz questions container
            container.addView(quizQuestionView);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)