material-components-android-examples
material-components-android-examples copied to clipboard
[Owl] Screen rotation crash
Hi, When the smartphone is rotated, the app crash came with backtrace:
2020-12-19 20:59:43.866 13774-13774/com.materialstudies.owl E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.materialstudies.owl, PID: 13774
java.lang.IllegalArgumentException: width and height must be > 0
at android.graphics.Bitmap.createBitmap(Bitmap.java:1113)
at android.graphics.Bitmap.createBitmap(Bitmap.java:1080)
at android.graphics.Bitmap.createBitmap(Bitmap.java:1030)
at android.graphics.Bitmap.createBitmap(Bitmap.java:991)
at androidx.core.view.ViewKt.drawToBitmap(View.kt:230)
at androidx.core.view.ViewKt.drawToBitmap$default(View.kt:226)
at com.materialstudies.owl.util.ViewExtensionsKt.show(ViewExtensions.kt:194)
at com.materialstudies.owl.ui.MainActivity$onCreate$1$1$1.onDestinationChanged(MainActivity.kt:46)
at androidx.navigation.NavController.addOnDestinationChangedListener(NavController.java:233)
at com.materialstudies.owl.ui.MainActivity$onCreate$1$1.invokeSuspend(MainActivity.kt:44)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at androidx.lifecycle.DispatchQueue.drainQueue(DispatchQueue.kt:76)
at androidx.lifecycle.DispatchQueue.resume(DispatchQueue.kt:55)
at androidx.lifecycle.LifecycleController$observer$1.onStateChanged(LifecycleController.kt:40)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:68)
at androidx.lifecycle.ReportFragment$LifecycleCallbacks.onActivityPostResumed(ReportFragment.java:188)
at android.app.Activity.dispatchActivityPostResumed(Activity.java:1278)
at android.app.Activity.performResume(Activity.java:7970)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4195)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4237)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
2020-12-19 20:59:43.878 13774-13774/com.materialstudies.owl I/Process: Sending signal. PID: 13774 SIG: 9
Run on: Google Pixel and Android 10. App crashes only when the BottomNavigationView is visible.
I just came across with this also. That's because during rotation somehow the width and height are 0. I haven't tried any solution yet, but just in case did you already?
Hi I Have modified the extension functions to use view tree observer to ensure the layout is ready before operating on it try, it out.
fun BottomNavigationView.show() {
if (visibility == VISIBLE) return
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
viewTreeObserver.removeOnGlobalLayoutListener(this)
val parent = parent as ViewGroup
// View needs to be laid out to create a snapshot & know position to animate. If view isn't
// laid out yet, need to do this manually.
if (!isLaidOut) {
measure(
MeasureSpec.makeMeasureSpec(parent.width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(parent.height, MeasureSpec.AT_MOST)
)
layout(parent.left, parent.height - measuredHeight, parent.right, parent.height)
}
val drawable = BitmapDrawable(context.resources, drawToBitmap())
drawable.setBounds(left, parent.height, right, parent.height + height)
parent.overlay.add(drawable)
ValueAnimator.ofInt(parent.height, top).apply {
startDelay = 100L
duration = 300L
interpolator = AnimationUtils.loadInterpolator(
context,
android.R.interpolator.linear_out_slow_in
)
addUpdateListener {
val newTop = it.animatedValue as Int
drawable.setBounds(left, newTop, right, newTop + height)
}
doOnEnd {
parent.overlay.remove(drawable)
visibility = VISIBLE
}
start()
}
}
})
}
fun BottomNavigationView.hide() {
if (visibility == GONE) return
viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
override fun onGlobalLayout() {
viewTreeObserver.removeOnGlobalLayoutListener(this)
val drawable = BitmapDrawable(context.resources, drawToBitmap())
val parent = parent as ViewGroup
drawable.setBounds(left, top, right, bottom)
parent.overlay.add(drawable)
visibility = GONE
ValueAnimator.ofInt(top, parent.height).apply {
startDelay = 100L
duration = 200L
interpolator = AnimationUtils.loadInterpolator(
context,
android.R.interpolator.fast_out_linear_in
)
addUpdateListener {
val newTop = it.animatedValue as Int
drawable.setBounds(left, newTop, right, newTop + height)
}
doOnEnd {
parent.overlay.remove(drawable)
}
start()
}
}
})
}