I am trying to listen for GlobalLayout
using
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
int c=0;
@Override
public void onGlobalLayout() {
c++; //without removing the listener c will grow for ever even though there is no GlobalLayout events
view.setText(""+c);
}
});
but it's called endlessly.
I know I should remove the listener like this: view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
But I want to keep the listener alive for the next GlobalLayout
events.
Currently I am just trying to listen for view position changing using this question
I tried onPreDraw
but it is the same.
GlobalLayout
events?
Thanks in advance.
The code you posted as an example shouldn't compile because of issues with accessing the variable c
from the listener. If you try it, you should get the following error in Android Studio:
Variable 'c' is accessed from within inner class, needs to be final or effectively final
We can take the suggestion that error check suggests and create a one-element array as follows:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final int[] c = {0};
final View[] view = {findViewById(R.id.textView)};
view[0].getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
c[0]++;
}
});
}
}
If you run this code against the following layout, you will see that the listener is called twice which I think corresponds to two layout passes:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
If the layout is somehow modified within the global layout listener, then it will trigger another layout and another call to the the listener. If the listener again makes a change, the listener will be called yet again and so on forever.
It would be helpful if you would post the actual code you are having trouble with or a simple project that demonstrates the problem. Is the layout somehow modified within the listener?
Update: As you say in one of your comments on this answer, your issue was that you made a change to a view in the global layout listener which triggered another layout and another call to the listener ad infinitum. Once you removed the code that made the layout change, that particular issue was resolved.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With