Comments (25)
Thanks for the project. I finally managed to reproduce this (note to self: change the emulator to use 1 CPU core). Now to work out what's happening....
from accompanist.
I just come up with a bit of a hack which fixes this. It's safe to use, but I don't want to ship it in the library until I speak to some of the team: https://gist.github.com/chrisbanes/bd9aa241dbab971c23433aaff8104d38, but it should unblock you all.
from accompanist.
Worked this out. So using ProvideWindowInsets
in fragments can result in the following:
- Fragment is added.
onCreateView
is called.- Fragment's
ComposeView
is added to the hierarchy. - Some time later (after initial view layout pass AFAICT), the first composition happens.
ProvideWindowInsets
is called which sets listeners and requests an insets pass.
- Compose content is laid out using
0
sized insets. - In the next view layout pass, insets are dispatched and the Compose
WindowInsets
are updated. - Compose content is laid out using correct insets.
The visual flicker is caused by steps 5 & 7 happening quickly after each other.
Using observeFromView()
from #158 instead results in the following:
- Fragment is added
onCreateView
is calledobserveFromView()
is called fromonCreateView()
which sets listeners and requests an insets pass.
- Fragment's
ComposeView
is added to the hierarchy. - In the first layout of
ComposeView
insets are dispatched, and this library'sWindowInsets
are updated. - Compose content is composed using correct insets from first layout.
No flicker! 😅
from accompanist.
BTW do you think that the Jetpack Compose team can do something about this? Maybe something needs to be changed in ComposeView?
Yeah I've reached out and hoping we can come up with something.
I'm still investigating why the WindowInsets
aren't dispatched in the first measure pass. If we could fix that, we wouldn't have any isseues.
from accompanist.
Thanks! Works like a charm :)
from accompanist.
Is there any better solution for this issue?
We are migrating to Compose and as a first step we want to migrate from xmls
to Composable
, so we can't easily get rid of fragments therefore we have to deal with the issue.
The workaround #155 (comment) works, but is it reliable? If so, can we have it in the library?
from accompanist.
Some experimental insets APIs have been merged into androidx
, available in the latest snapshots (if you're feeling adventurous, feel free to try it out and report issues or feedback!)
The mechanism behind the implementation is a little bit different than accompanist
, and in my initial testing the approach seems to be more reliable around flickering and in fragments.
from accompanist.
Just to confirm, the app I'm working on does use Fragments, each one provides its UI using Compose, we still use the existing Jetpack Navigation via Fragments for navigating between Fragments in a single Activity app.
from accompanist.
#shipit!
from accompanist.
@apkelly @chrisbanes I still got flicker when applying observeFromView
. I am using fragments with navigation.
from accompanist.
@Nghicv do you have an example of this? Does it happen on specific devices? I'm not sure there's much else we can do.
from accompanist.
@chrisbanes I have just tested TV app from the google play store, it got flicker too
this is my device
from accompanist.
have you managed to make it work with FragmentContainerView
and the Navigation Library (multiple fragments with composable UI) ?
I have one Activity
class HomeActivity : FragmentActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
and fragments like:
class MyFragment: BaseFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = ComposeView(requireContext()).apply {
layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
val windowInsets = ViewWindowInsetObserver(this).start(consumeWindowInsets = false)
setContent {
Providers(
LocalWindowInsets provides windowInsets
) {
// composable UI
}
}
}
my UI is flickering on Pixel 2 Emulator API 30 and OnePlus 8T API 30
from accompanist.
@radzio if you have a simple project, would you mind uploading it? (zip is fine). I've got a few apps which use fragments and I haven't seen any flickers.
from accompanist.
Maybe we are talking about different bug/feature but check this video:
WCel6GbbrZ.mp4
"Hi there text" evidently starts without inset padding (just play it in slow-mo). Maybe I'm doing something wrong but I have no idea what :(.
When I'm not using insets and statusBarsPadding
modifier there is no jumping at all. TextField is, as expected, in wrong place ,under status bar):
Example app:
Flickering.zip
from accompanist.
OK, got a little further with this. This is what happens internally:
D/ComposeView Parent: Attached to window
D/ViewWindowInsetObserver: requestApplyInsets() called
D/ComposeView: Attached to window
D/ComposeView Parent: onMeasure
# First measure/layout of Composables. WindowInsets are empty
D/InsetsPaddingModifier: measure(): Insets(left=0, top=0, right=0, bottom=0)
D/ComposeView Parent: onMeasure
D/ViewWindowInsetObserver: WindowInsets dispatched and received
D/ComposeView Parent: onMeasure
D/ComposeView Parent: onMeasure
D/ComposeView Parent: onLayout
D/ComposeView: First layout
# Second measure/layout of Composables. WindowInsets are now filled
D/InsetsPaddingModifier: measure(): Insets(left=0, top=48, right=0, bottom=0)
As a summary: the composables are laid out once before the WindowInsets
are dispatched. I'm not sure there's much we can do here.
from accompanist.
@chrisbanes thanks for the investigation. It's sad that we can't do more here.
However, at least in my case, I think that I can use activity.window.decorView.rootWindowInsets
On the first fragment, it will not work because it's null, but it's ok for me because the first fragment is not inset-dependent. But on the subsequent fragments, I get this value immediately. However, I don't know how to use this rootWindowInsets
because I can't set anything (setters are internal :) )
BTW do you think that the Jetpack Compose team can do something about this? Maybe something needs to be changed in ComposeView?
from accompanist.
@chrisbanes @radzio the hack worked but I got a white screen before the destination screen is shown. seem to Time to showing white screen equal to the time to wait MAXIMUM_ONMEASURE_IGNORED
from accompanist.
@Nghicv that would make sense, as that is what the hack is doing.
from accompanist.
@chrisbanes should we come up with a better solution?
from accompanist.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
from accompanist.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.
from accompanist.
Is this related to fragments only? We're seeing the same jump in an app without fragments, not sure if I should open a separate issue or investigate more.
from accompanist.
I just come up with a bit of a hack which fixes this. It's safe to use, but I don't want to ship it in the library until I speak to some of the team: https://gist.github.com/chrisbanes/bd9aa241dbab971c23433aaff8104d38, but it should unblock you all.
Thanks! This hack works for me (with a slight modification: Providers
-> CompositionLocalProvider
), however is there now a more reliable and stable solution?
from accompanist.
So, seems like I found how to fix this: https://stackoverflow.com/q/77807932/12544067
from accompanist.
Related Issues (20)
- [WebView] Question about backwards writes HOT 5
- Vector animation is broken with newer libraries HOT 5
- False positive deprecation message on pagerTabIndicatorOffset variant HOT 2
- onPermissionsResult isn't triggered on POST_NOTIFICATIONS permission request (API 33). HOT 2
- [Test Harness] Deprecate with replacement of `DeviceConfigurationOverride`
- Incorrect deprecation of pagerTabIndicatorOffset HOT 2
- [Permissions] Gradle update crashing permission request and the app HOT 8
- Crash when using ProgressIndicator with `accompanist-permissions` 0.34.0 HOT 1
- [Navigation Material] Crash in BottomSheetNavigator when user goes back HOT 3
- [Navigation Material] Status bar not scrimmed when bottom sheet is shown HOT 1
- [LazyColumn] scroll observation scope does not exist HOT 3
- [Feature request] LazyTable with nested scrolling support HOT 1
- [Navigation Material] Edge to edge jumping bug when migrating from 1.1.2 to 1.2.0. HOT 1
- [Navigation Material] BackHandler is not triggered after Activity stop+start HOT 1
- [Navigation Material] DisposableEffect onDispose is not called at the right time for bottom sheet HOT 1
- [Navigation Material] Add deprecated to main README
- [Adaptive]
- accompanist-drawablepainter: PictureDrawable doesn't scale HOT 1
- BottomSheetNavigator#NullPointerException HOT 1
- [Webview] fit parent width issue HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from accompanist.