Issue
View
contains a method setId(int)
. My question is, how to programatically supply the object an Id that does not overlap any resource id's in R
?
Solution
According to the documentation, View.generateViewId()
added in API level 17 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
.
I experimented with View.generateViewId()
to find out how it behaves. Here are my findings.
- Generated ID will begin from 1 and will be incremented by each time it is called (1, 2 , 3...)
generateViewId()
will maintain the last ID returned and will continue from there throughout app life cycle. For example if last ID before device rotation was 4, next ID after rotation will 5.
It is important to note that, for instance, if you are setting up views at runtime in your app's onCreate()
method by calling generateViewId()
every time, after your device rotates, by default onCreate()
is called again and your views will receive a different ID than before rotation.
Android has a feature to automatically restore your views state – for instance, text you enter into an EditText view, checked state of a CheckBox – after device rotation, but it only works if the views' have persistent IDs. So in the above example, this state restoration will not work – your EditText view will lose input and you have to type whatever you need to type in again – as views will receive a different ID every time they are generated. To work around this problem, you need to maintain IDs through activity life cycle.
I found out that Android assigns IDs for objects defined in XML in the magnitude of billions. This is a real life ID taken from my app having only a few predefined IDs: 2131427423. So it seems to be pretty safe to use low IDs on your own discretion without ever calling generateViewId()
. In my simple app I mimicked it by assigning IDs beginning from 1, increasing by one, and it worked. Here is an example, extracted from my app:
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);
}
}
}
Answered By - Balázs Lengyák
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.