Reputation: 67
I have a custom tab view derived from LinearLayout
which inflates an xml layout.
Inside it I have a view (llIndicator
) which is used as an indicator bar and I achive this with animating the translationX
property of the view like this:
val offset = llIndicator.width * activeTabIndex
llIndicator.animate().translationX(offset.toFloat())
It all works fine, the only problem is when I am trying to restore the state of the view after activity is destroyed and re-created. Most of the properties does not even need to be saved because the setup code in the fragment is called again, but i would like to save the selected tab and restore the translationX property and restore it without animation.
But I cannot seem to find the correct solution. I save the selected tab to a bundle, successfully restore it, calculate the correct position, but when I set the translationX
property, it does not do anything...
It does not work if I do it in the onRestoreInstanceState()
method because it happens before the layout, so I tried to set an isInstanceBeingRestored
variable to true
in the onRestoreInstanceState()
and set translationX
in the onLayout()
method, but with no success.
So i tried using an OnGlobalLayoutListner()
as well by placing the following code in the init{ }
of the view.
viewTreeObserver.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener{
override fun onGlobalLayout() {
viewTreeObserver.removeOnGlobalLayoutListener(this)
// Restore view if needed
if(isInstanceBeingRestored){
llIndicator.translationX = offset
}
}
})
It still does nothing... offset
is correctly calculated, I checked by using Log.d()
, and also replacing it with by any number has no effect.
So I tried using the post() method, as following:
llIndicator.post({
llIndicator.translationX = offset
})
I tried placing it in the onLayout()
method (of course checking the isInstanceBeingRestored
variable first) and also to the OnGlobalLayoutListener()
but no effect.
But what is interesting, if I use postDelayed() with a large enough delay, it works.
llIndicator.postDelayed({
llIndicator.translationX = offset
}, 1500)
But obviously, this solution cannot remain, I just tried it out... So I am confused... This sounds quite a simple thing to solve but after hours of Googling and trying different codes, and scratching my head, I still couldn't solve it. Surely it cannot be so difficult, can it?
What am I doing wrong? Can anyone point me in the right direction?
Thank's very much in advance for any help.
Edit:
I found something interesting...
If I use marginStart
instead of translationX
as below to set the position it works. What would be the reason for that? I don't get it...
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
if(isInstanceBeingRestored){
val p = llIndicator.layoutParams as MarginLayoutParams
p.marginStart = offset.toInt()
llIndicator.layoutParams = p
//llIndicator.translationX = offset
}
}
Edit 2:
Well it only works with marginStart
if the margin start was 0 before activity gets destroyed... So if I set offset
to a random value, independent from its previous position, it displays the indicator at the correct position, if marginStart
was 0 before...
Otherwise the indicator bar appears at the left side of the screen.
Now I am getting really lost...
I double-checked the calculations but they give the correct offset...
Best wishes, Agoston
Upvotes: 1
Views: 196