View
包含一个方法setId(int)
。我的问题是,如何以编程方式为对象提供一个不与任何资源 ID 重叠的 ID R
?
1 回答
根据文档,View.generateViewId()
在 API 级别 17 中添加会生成一个适合在setId(int)
. 此值不会与 aapt for 在构建时生成的 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,只有几个预定义的 ID:2131427423。因此,您可以自行决定使用低 ID 而无需调用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);
}
}
}