'onTap in GestureDetector is taking a value less, but Text is taking correct, both used in the same loop
In the following code, Text(subjects[address])
is printing the correct value, but GestureDetector( onTap:
is taking the same value for the whole Row
, and incrementing the values of subject
and address
directly by 2 and 6 respectively, at exit from inner loop,
Column(
children: [
for (int i = 0, address = 0, subject = 0; i < 3; i++)
Row(
children: [
for (int j = 0; j < 2; address += 3, subject++, j++)
GestureDetector(
child: Text(subjects[address]),
onTap: () {.........},
),
],
),
],
),
so when i tap 'Second', onTap
should execute the code of 'Second', which is subject
('1' at Second), but it is taking '2', for both First and Second, and '4' for Third, and Fourth, and '6' for Fifth and Sixth,
and as subject
is being incremented by 2, address
is being incremented by 6,
Thanking you...
Solution 1:[1]
Nearest Solution
GridView.count
, with physics: const NeverScrollableScrollPhysics()
, and shrinkWrap: true
, and crossAxisCount: 2
.
Reason (behind code failure)
The correct (intended) behavior is shown by the outer loop ( inside Column( children: [..],),
) as given in the official language-tour,
While the behavior shown by the inner loop ( inside Row( children: [..],),
, is incorrect and wrong, possibly a bug,
Official Quotation
Code:
var callbacks = [];
for (var i = 0; i < 3; i++) {
callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
Correct (intended) Output:
0
1
2
Incorrect (wrong) Output:
2
2
2
Solution 2:[2]
While rendering the UI, it takes the current value of "subject" variable, so the UI part is correct.
OnTap does not work correctly because the value of subject variables gets changed after each iteration in the for loop, so when the ontap is called it just takes the last value of "subject" variable which is the 2,4,6 that you get for each ROW.
Solution:
- Hard Code: If you are sure there are only 6 buttons on the screen then you could just hard code it.
- Use ListView Builder: If the for loops condition is not constant then better use listview.builder (for row) within another listview.builder (for column).
The solution I have given is very short and abstract. Do comment if you need further explanation.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Nagulan S |