chrisbanes / insetter Goto Github PK
View Code? Open in Web Editor NEWInsetter is a library to help apps handle WindowInsets more easily
Home Page: https://chrisbanes.github.io/insetter
License: Apache License 2.0
Insetter is a library to help apps handle WindowInsets more easily
Home Page: https://chrisbanes.github.io/insetter
License: Apache License 2.0
@chrisbanes hi!
A strange situation occurred while working with keyboard insets
If you install paddings from the keyboard for NestedScrollView
, the view in focus does not remain visible, hiding behind the keyboard
How can you handle this scenario so that the EditText
respects the keyboard that appears? Only by setting margins for NestedScrollView
?
Activity and layout code is below
class MainActivity : AppCompatActivity(R.layout.activity_main) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val rootView = findViewById<LinearLayout>(R.id.root_view)
val nestedScroll = findViewById<NestedScrollView>(R.id.nested_scroll)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
WindowCompat.setDecorFitsSystemWindows(window, false)
Insetter.builder().setOnApplyInsetsListener { _, insets, _ ->
toolbar.updatePadding(
top = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top
)
nestedScroll.updatePadding(
bottom = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom + insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom
)
}.applyToView(rootView)
}
}
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/app_name" />
<androidx.core.widget.NestedScrollView
android:id="@+id/nested_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="750dp"
android:layout_marginBottom="120dp"
android:hint="This will be hide by the keyboard" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
I am facing a few issues with using the animated ime support in my app. As you can see the edittext's animate upwards and drop back again behind the keyboard
Went through a few issues and i think the issue is similar to #93. Hence, i tried applying the padding to the linearlayout as recommended there but the issue persists as shown in the attached video.
I have attached my project along with relevant commit https://github.com/kriticalflare/SocietyApp/tree/84088adbab5e7dae533ae5dc443aaa2c3c0c38be
Margin seems not working for Insetter Builder and InsetterConstraintHelper but Padding is totally fine
Both of that code not working
Insetter Builder
binding.textView.applyInsetter { type(statusBars = true) { margin() } }
InsetterConstraintHelper
<dev.chrisbanes.insetter.widgets.constraintlayout.InsetterConstraintHelper
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_marginSystemWindowInsets="top" />
I also tried InsetterConstraintLayout but not work either
I'm using version 0.5.0
This library doesn't appear to be working.
After just adding the library to the project:
implementation "dev.chrisbanes:insetter-dbx:0.2.0"
And then syncing Gradle files + rebuilding the project, we get the following errors:
Duplicate class dev.chrisbanes.insetter.DataBinderMapperImpl found in modules jetified-insetter-dbx-0.2.0-runtime.jar (dev.chrisbanes.insetter:insetter-dbx:0.2.0) and jetified-insetter-dbx-0.2.0-runtime.jar (dev.chrisbanes:insetter-dbx:0.2.0)
Duplicate class dev.chrisbanes.insetter.DataBinderMapperImpl$InnerBrLookup found in modules jetified-insetter-dbx-0.2.0-runtime.jar (dev.chrisbanes.insetter:insetter-dbx:0.2.0) and jetified-insetter-dbx-0.2.0-runtime.jar (dev.chrisbanes:insetter-dbx:0.2.0)
Duplicate class dev.chrisbanes.insetter.DataBinderMapperImpl$InnerLayoutIdLookup found in modules jetified-insetter-dbx-0.2.0-runtime.jar (dev.chrisbanes.insetter:insetter-dbx:0.2.0) and jetified-insetter-dbx-0.2.0-runtime.jar (dev.chrisbanes:insetter-dbx:0.2.0)
Duplicate class dev.chrisbanes.insetter.InsetterBindingAdapters found in modules jetified-insetter-dbx-0.2.0-runtime.jar (dev.chrisbanes.insetter:insetter-dbx:0.2.0) and jetified-insetter-dbx-0.2.0-runtime.jar (dev.chrisbanes:insetter-dbx:0.2.0)
Duplicate class dev.chrisbanes.insetter.InsetterBindingAdapters$1 found in modules jetified-insetter-dbx-0.2.0-runtime.jar (dev.chrisbanes.insetter:insetter-dbx:0.2.0) and jetified-insetter-dbx-0.2.0-runtime.jar (dev.chrisbanes:insetter-dbx:0.2.0)
The external libraries being fetched are the following:
Gradle: dev.chrisbanes.insetter:insetter:0.2.0@aar
Gradle: dev.chrisbanes.insetter:insetter-dbx:0.2.0@aar
Gradle: dev.chrisbanes.insetter:insetter-ktx:0.2.0@aar
Gradle: dev.chrisbanes.insetter:insetter-widgets:0.2.0@aar
Gradle: dev.chrisbanes:insetter:0.2.0@jar
Gradle: dev.chrisbanes:insetter-dbx:0.2.0@aar
Currently all we have is
fun consume(consume: Boolean) { builder = builder.consume(if (consume) Insetter.CONSUME_ALL else Insetter.CONSUME_NONE) }
And if I want to use Insetter.CONSUME_AUTO
then I have to use builder.
Can we get this option via dsl pls?
Currently there is no way we can set onApplyInsetsListener
via the kotlin dsl
When using this library with a CollapsingToolbarLayout
, the insets on the bottom (the top works) are not set or are overwritten. When I comment out the CollapsingToolbarLayout
, the problem goes away. Please see the sample project I created: https://github.com/percula/CollapsingToolbarInsets
In the following screenshot, the FAB and the padding of the text should be above the nav bar.
java.lang.NoClassDefFoundError: Could not initialize class dev.chrisbanes.insetter.widgets.constraintlayout.InsetterConstraintLayout$LayoutParams
at dev.chrisbanes.insetter.widgets.constraintlayout.InsetterConstraintLayout.generateLayoutParams(InsetterConstraintLayout.kt:99)
at dev.chrisbanes.insetter.widgets.constraintlayout.InsetterConstraintLayout.generateLayoutParams(InsetterConstraintLayout.kt:61)
at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:1125)
at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1097)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084)
at android.view.LayoutInflater.inflate(LayoutInflater.java:682)
at android.view.LayoutInflater.inflate(LayoutInflater.java:501)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:328)
at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:373)
at com.android.tools.idea.layoutlib.LayoutLibrary.createSession(LayoutLibrary.java:141)
at com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:713)
at com.android.tools.idea.rendering.RenderTask.lambda$inflate$6(RenderTask.java:844)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1604)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
I can't see preview
Inside my XML
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rootFull">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/topAppBarLayout">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="300sp"
android:id="@+id/topAppBar"
app:title="HIEUTHUHAI"
app:expandedTitleTextAppearance="@style/artist_name"
app:expandedTitleTextColor="@android:color/white"
app:collapsedTitleTextAppearance="@style/TextAppearance.Material3.TitleMedium"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:contentScrim="?attr/colorSurface">
<ImageView
android:id="@+id/ivArtistImage"
android:layout_width="match_parent"
android:layout_height="300dp"
android:scaleType="centerCrop"
android:src="@drawable/artist_thumbail"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.7" />
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:navigationIcon="@drawable/baseline_arrow_back_ios_24"
app:layout_collapseMode="pin"
app:popupTheme="@style/Widget.Material3.PopupMenu.Overflow">
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
......
In my fragment onCreateView
:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentArtistBinding.inflate(inflater, container, false)
binding.toolBar.applyInsetter {
type(statusBars = true) {
padding()
}
}
return binding.root
}
Toolbar still be overlap
How to fix it? Thanks for make a best library
Hello,
Insets are not applied when the device's screen is rotated and new activity is created.
What can be the cause?
My activity is fullscreen.
Using v0.5
The dev.chrisbanes.insetter.widgets.constraintlayout.InsetterConstraintLayout does not show any preview in Android studio, but runs and renders fine on a device.
The library will provide InsetterConstraintLayout
. It would be nice to have also ConstraintHelper
that does the same thing. It's a pluggable mechanism of ConstraintLayout
so the users of this library will be able to use Insetter with normal ConstraintLayout
.
I have a button which has layout_constraintTop_toTopOf="parent"
then I will apply inset status bar to its but not work; neither Insetter Builder nor data binding worked.
My solution: the button will be bottom of Guildline then I will setGuidelineBegin = inset.systemWindowInsetTop
to the Guideline now it works.
Just created functions with annotation @Deprecated
and replaceWith
expressions to make migration easier in simple cases.
@file:Suppress("PackageDirectoryMismatch", "unused")
package dev.chrisbanes.insetter
import android.view.View
@Deprecated(
level = DeprecationLevel.ERROR,
message = "Use applyInsetter instead",
replaceWith = ReplaceWith(
"this.applyInsetter { type(statusBars = top, navigationBars = bottom) { padding() } }",
"dev.chrisbanes.insetter.applyInsetter"
)
)
fun View.applySystemWindowInsetsToPadding(top: Boolean = false, bottom: Boolean = false) {
error("should not be used")
}
@Deprecated(
level = DeprecationLevel.ERROR,
message = "Use applyInsetter instead",
replaceWith = ReplaceWith(
"this.applyInsetter { type(statusBars = top, navigationBars = bottom) { margin() } }",
"dev.chrisbanes.insetter.applyInsetter"
)
)
fun View.applySystemWindowInsetsToMargin(top: Boolean = false, bottom: Boolean = false) {
error("should not be used")
}
object Insetter {
@Deprecated(
level = DeprecationLevel.ERROR,
message = "Use WindowCompat.setDecorFitsSystemWindows() instead",
replaceWith = ReplaceWith(
"WindowCompat.setDecorFitsSystemWindows(window, !enabled)",
"androidx.core.view.WindowCompat"
)
)
fun setEdgeToEdgeSystemUiFlags(view: View, enabled: Boolean = true) {
error("should not be used")
}
}
> Task :app:processDebugManifest
[dev.chrisbanes:insetter-ktx:0.2.0] /Users/coltonidle/.gradle/caches/transforms-2/files-2.1/9ee7ca0ad1b0e0be19f2cbb93fe9a9b4/jetified-insetter-ktx-0.2.0/AndroidManifest.xml Warning:
Package name 'dev.chrisbanes.insetter' used in: dev.chrisbanes:insetter-ktx:0.2.0, dev.chrisbanes:insetter:0.2.0.
[androidx.navigation:navigation-runtime-ktx:2.2.0-rc03] /Users/coltonidle/.gradle/caches/transforms-2/files-2.1/e682aca97378e5c9a1eb9b8882f83385/navigation-runtime-ktx-2.2.0-rc03/AndroidManifest.xml Warning:
Package name 'androidx.navigation.ktx' used in: androidx.navigation:navigation-runtime-ktx:2.2.0-rc03, androidx.navigation:navigation-common-ktx:2.2.0-rc03.
Noticed a bunch of these warnings in my build output and wanted to let you know.
Hi,
I'd be nice to have an example featuring a BottomSheetDialog
, which would have views at the top of the layout, a RecyclerView with more items than can fit in the screen, and views in the bottom as well.
This would be very helpful to not just me as I failed to find how to do it right on the public web (and failed to do it right on my own, having views behind the SystemUI).
As specified in doc, setMargins() requires to call requestLayout
after that.
Currently, it works "almost" without it, just on older LG devices (Android 5.1 and 6) views are not updated until I call this manually.
This is the only thing I can see about it:
https://github.com/chrisbanes/insetter/blob/master/dbx/README.md#edge-to-edge-attributes
"
There is currently just one edge-to-edge attribute:
app:layout_edgeToEdge: Set this view's system-ui visibility with the flags required to be laid out 'edge-to-edge', or not.
"
But what does it do? When to use it? When is it useful?
Is it for Edge display? How is it related to insets?
Please explain.
Currently, requestApplyInsets
is called once when the view is attached to a window, via doOnAttach
(either immediately or the next time the view is attached):
insetter/library/src/main/java/dev/chrisbanes/insetter/Insetter.kt
Lines 394 to 396 in 9b1eed5
This works well for most cases, but there are corner cases where this isn't enough.
For instance, suppose a view within a ViewHolder
within a RecyclerView
is has left/right insets applied to it from the systemBars
insets. The consider the following sequence of events:
RecyclerView
, so that some ViewHolder
s that have insets applied are detached from the windowRecyclerView
so that the previously detached ViewHolder
s are reattached to the window.Since the new insets were dispatched while the ViewHolder
s were detached, these ViewHolder
s will now be incorrectly displaying the old insets, and since they were already attached once, requestApplyInsets
won't be called again.
The following video shows an example of that case:
My proposed fix is to replace doOnAttach
with doOnEveryAttach
, which will run the action immediately if the view is already attached, and then will run the action again upon every subsequent attach.
I am using this library for a form which uses fullscreen mode for drawing the form behind statusBar
. I am very delighted to have found this amazing library which helps in calculating the insets rather than calculating it manually, for that, I thank you.
As for the issue, forms would normally has EditText
s and mine have several.
I was only using app:paddingTopSystemWindowInsets="@{true}"
for the layout as I only need the top padding. But this causes problem as my Activity doesn't respect adjustResize
anymore, unelss I add app:paddingBottomSystemWindowInsets="@{true}"
.
Is this an intended behavior?
Or is it actually an issue?
Hi,
I'm really really sorry to ask here but it's the easiest way to reach the proper people with issue tracker being changed to prevent posting in many sections to force external triage :(
With AndroidX core 1.2.0 I'm facing a very very strange issue on some devices in some cases that I don't understand and it was quite hard to figure out:
ViewCompat.setOnApplyWindowInsetsListener(button) { _, insets ->
filler.layoutParams = filler.layoutParams.apply { this.height = insets.systemWindowInsetBottom }
insets
}
In this piece of code insets.systemWindowInsetBottom value is -1 this is not documented anywhere and as unexpected have the effect of setting the view height to match parent and as you can imagine fill the whole screen and hide all the content instead of moving a filler view above the navigation bar.
Is this something known or already seen? Should I report to AndroidX or it can be a specific device issue (OnePlus 6T/ Samsung S10 and Mi 9t pro are the devices that randomly does that and users reported to me) or it's a documentation issue ?
By randomly I means that it happens on very rare instance of those devices but is constant on those
devices.
Seeing one screenshot of a user it's maybe related to some settings those devices have to completely hide the navigation bar as I don't see any on it.
Insetter version: 0.1.0 with ktx
I start use insetter and catch this exception:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: ru.desk.gesture_view, PID: 4053
java.lang.IllegalAccessError: Interface dev.chrisbanes.insetter.OnApplyInsetsListener implemented by class ru.desk.gesture_view.ImageViewerActivity$onCreate$$inlined$doOnApplyWindowInsets$1 is inaccessible (declaration of 'ru.desk.gesture_view.ImageViewerActivity$onCreate$$inlined$doOnApplyWindowInsets$1' appears in /data/app/ru.desk.gesture_view-u1iHhsBDTS7EvCxxHDbseQ==/base.apk!classes2.dex)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1216)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2864)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6806)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
I think problem is that OnApplyInsetsListener is not public...
In method applyToView
and checking for custom listener, there's probably a bug with checking if insets should be consumed.
The problem is in the if condition - it should be reverted and therefore if(consume == CONSUME_NONE) insets else WindowInsetsCompat.CONSUMED
because when none consumed, then we should return the initial insets, right?
This breaks insetter when custom listener is applied somewhere in the view hierarchy.
It would be great if you could add a CHANGELOG file, so we can see what changes have been made.
Upgraded to the 0.5.0 from 0.3.1
Code was this
recycler.applySystemWindowInsetsToMargin(top = true)
recycler.applySystemGestureInsetsToPadding(bottom = true)
and is now this
recycler.applyInsetter {
type(systemGestures = true) {
padding(bottom = true)
}
type(statusBars = true) {
margin(top = true)
}
}
I have to apply the statusbars to margin top or else it fails
View's LayoutParams do not extend MarginLayoutParams errors since updating
java.lang.IllegalArgumentException: Margin window insets handling requested but View's LayoutParams do not extend MarginLayoutParams
Desired feature
Whenever new insets are applied I want to be able to adjust them. That's especially useful if insets do depend on user settings, e.g. I may change paddings/margins of a view if the user changes a setting and in such cases, I can't use insetter.
Example
Consider a list that always expands behind the navigation bar and an optional "dock" above the navigation bar. If the dock is visible, the content list needs more bottom padding than if the dock is not visible to allow that all items can be scrolled up to the interactable region...
Currently I have to do everything fully manually like following:
Insetter.builder()
.padding(windowInsetTypesOf(navigationBars = true))
.setOnApplyInsetsListener { view, insets, initialState ->
val extraPadding = if (Prefs.desktopDock.value) { 48.dpToPx } else 0
view.updatePadding(bottom = insets.getInsets(WindowInsets.Type.navigationBars()).bottom + initialState.paddings.bottom + extraPadding)
L.tag("DESKTOP").d { "LISTENER: Padding Bottom: ${view.paddingBottom}" }
}
.applyToView(binding.rvData)
Suggestion
Maybe you can add an optional hook that can adjust paddings/margins before applying them. Something that can adjust the values before applying them in following 2 places:
When I switch on/off paddingTop in dbx example then there is flickering visible on the bottom of the screen. Seems like the padding is applied on the bottom too for a brief moment.
You can see it on attached video.
Device info: Pixel 3 running Android 10
https://drive.google.com/open?id=1tGvSH9X5d0ZxnHJbK8oXcn-vX0qpM-0n
Would be awesome to have an ability to define insets in motion scene.
Not just padding.
Right now using Kotlin DSL possible only if I use consume with boolean arg, like this:
view.applyInsetter {
consume(false)
}
witch equals CONSUME_ALL or CONSUME_NONE, but in some cases I need CONSUME_AUTO, like this:
Insetter.builder()
.applySystemWindowInsetsToPadding(Side.RIGHT or Side.LEFT)
.consumeSystemWindowInsets(Insetter.CONSUME_AUTO)
.applyToView(view)
and is impossible with Kotlin DSL :(
inline fun View.setEdgeToEdgeContent() {
if (ViewCompat.getFitsSystemWindows(this)) {
systemUiVisibility =
// Tells the system that you wish to be laid out
// as if the navigation bar was hidden
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
// Optional, if we want you be laid out fullscreen,
// behind the status bar
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
// Tells the system that you wish to be laid out at
// the most extreme scenario of any other flags
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
}
}
Also it would be nice make constructors in ViewState and ViewDimensions public to allow usage in customs options, like where need return consumed or modified insets.
And also it would be nice provide opportunities to return modified insets, like this usecase:
https://github.com/google/iosched/blob/4054aa3f8934b8b1208d5823fdbf531a8eb367af/mobile/src/main/java/com/google/samples/apps/iosched/ui/MainActivity.kt#L154
ConstraintLayout 2.1.0-alpha2 introduced the following change:
ConstraintLayout.LayoutParams
now inherits directly fromViewGroup.LayoutParams
, notViewGroup.MarginLayoutParams
.
This causes the following exception to be thrown when trying to use InsetterConstraintLayout
with something like app:layout_marginSystemWindowInsets
:
java.lang.IllegalArgumentException: Margin inset handling requested but view LayoutParams do not extend MarginLayoutParams
at dev.chrisbanes.insetter.Insetter.applyInsetsToView(Insetter.java:459)
at dev.chrisbanes.insetter.widgets.constraintlayout.InsetterConstraintLayout.onApplyWindowInsets(InsetterConstraintLayout.java:94)
at android.view.View.dispatchApplyWindowInsets(View.java:9801)
at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:7076)
at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:7080)
at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:7080)
at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:7080)
at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:7080)
at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:7080)
at android.view.ViewRootImpl.dispatchApplyInsets(ViewRootImpl.java:1664)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1766)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1463)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7190)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer.doFrame(Choreographer.java:696)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I am using https://github.com/cashapp/contour in a project and it would be nice to have something like
val actualStatusBarsSize = Insetter.builder().valueTop(statusBars =true).build().value
There are probably other uses cases outside of using contour where this could be helpful like
val navBarSize = Insetter.builder().valueTop(navigationBars =true).build().value
view1.updatePadding(0,navBarSize,0,0)
view2.updatePadding(0,navBarSize,0,0)
Use case: Workaround for a FAB is to use both right and left with the same value.
Hello!
Do you think it makes sense to add support for other popular view groups to the insetter-widgets module: FrameLayout, LinearLayout, etc.?
When I try to use the Insetter with margins on a view with layout_marginEnd, no horizontal margins are applied.
This is caused by the method "setMargins" used in ViewGroup.MarginLayoutParams.updateMargins, which internally sets the
NEED_RESOLUTION_MASK layout flag, which causes the specified rightMargin to be ignored.
To reproduce, use this code:
Insetter.builder()
.margin(
WindowInsetsCompat.Type.systemBars()
| WindowInsetsCompat.Type.displayCutout()
| WindowInsetsCompat.Type.ime(),
Side.BOTTOM | Side.RIGHT | Side.LEFT
)
.applyToView(binding.addButton);
with a FAB that is defined like this:
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/addButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
See FR 2 & 3 in #16
Builds using the version 0.5.0
are broken since today.
Looks like something has broken the jitpack.io package structure.
See the error message at jitpack.io
Build failed. See the log at jitpack.io
Hello
Are you planning to add support to this library of api inserts from Android 11? Or will it all be implemented in another library?
Thanks you
Hello, I see that setOnApplyWindowInsetsListener()
method was added in API level 20, so does this library work on KitKat and below?
For each of those :
https://github.com/chrisbanes/insetter/blob/master/dbx/README.md
For example, we have paddingBottomSystemWindowInsets as attribute of data-binding.
I suggest we have it in code too.
Maybe like this in this case:
view.setPaddingSystemWindowInsets(bottom=true)
Or even better: handle both padding and margins together:
view.setPaddingAndMarginsSystemWindowInsets(Type.MARGIN_BOTTOM,Type.PADDING_LEFT,TYPE.PADDING_RIGHT...)
This will add the insets to the original padding and margins that were set before.
This way, in a single line we could handle an entire view's insets related stuff...
What:
Ability to remove insets on views.
Why
With some complex views sometimes we have to play with insets in order to match a specific design.
With Insetter it makes it super easy and clean to add insets, but we don't have the opportunity yet to remove an inset that was previously applied.
Would it make sense to have a feature like this?
Thanks a lot in advance!
I had the issue that the listener received window insets always with 0px
My layout looks like this and I applied the doOnApplyWindowInsets
to BottomNavigationView
.
I fixed it for me by waiting until it is attached and then listen for insets on the top most parent view.
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:fitsSystemWindows="false"
...>
<com.google.android.material.bottomnavigation.BottomNavigationView
... />
Fixed code in kotlin...
/**
* A wrapper around [ViewCompat.setOnApplyWindowInsetsListener] which stores the initial view state, and provides them whenever a
* [android.view.WindowInsets] instance is dispatched to the listener provided.
*
*
* This allows the listener to be able to append inset values to any existing view state
* properties, rather than overwriting them.
*/
fun setOnApplyInsetsListener(view: View, listener: OnApplyInsetsListener) {
val tagState = view.getTag(R.id.insetter_initial_state) as ViewState?
val initialState: ViewState
if (tagState != null) {
initialState = tagState
} else {
initialState = ViewState(view)
view.setTag(R.id.insetter_initial_state, initialState)
}
if (ViewCompat.isAttachedToWindow(view)) {
registerForWindowInsets(view, getMostParentView(view), initialState, listener)
} else {
view.addOnAttachStateChangeListener(
object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
v.removeOnAttachStateChangeListener(this)
registerForWindowInsets(v, getMostParentView(v), initialState, listener)
}
override fun onViewDetachedFromWindow(v: View) {
// no-op
}
})
}
}
/**
* Register for window insets.
* Commits result through wrapper.
*/
private fun registerForWindowInsets(
view: View,
mostParent: View,
initialState: ViewState,
listener: OnApplyInsetsListener
) {
ViewCompat.setOnApplyWindowInsetsListener(
mostParent
) { v, insets ->
listener.onApplyInsets(view, insets, initialState)
// Always return the initial insets instance
insets
}
ViewCompat.requestApplyInsets(mostParent)
}
/**
* Returns the most parent view in its hierarchy
*/
private fun getMostParentView(view: View): View =
view.parent.run {
if (this != null && this is View && this.id != android.R.id.content) {
getMostParentView(this)
} else view
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.