diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 08f34528d..36a5faceb 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -70,8 +70,7 @@ + android:name=".activities.editor.EditorActivityKt"/> diff --git a/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt index 6ea9f43ac..dde8eeae9 100755 --- a/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/AboutActivity.kt @@ -18,7 +18,6 @@ package com.itsaky.androidide.activities import android.content.Context import android.content.Intent -import android.graphics.Rect import android.os.Bundle import android.text.SpannableStringBuilder import android.text.style.ForegroundColorSpan @@ -27,6 +26,7 @@ import androidx.annotation.ColorInt import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.content.ContextCompat +import androidx.core.graphics.Insets import androidx.core.view.updatePaddingRelative import com.blankj.utilcode.util.ClipboardUtils import com.blankj.utilcode.util.SizeUtils @@ -101,8 +101,7 @@ class AboutActivity : EdgeToEdgeIDEActivity() { } } - override fun onInsetsUpdated(insets: Rect) { - super.onInsetsUpdated(insets) + override fun onApplySystemBarInsets(insets: Insets) { binding.toolbar.apply { setPaddingRelative( paddingStart + insets.left, @@ -126,53 +125,65 @@ class AboutActivity : EdgeToEdgeIDEActivity() { private fun createSocialItems(): List { return mutableListOf().apply { - add(createSimpleIconTextItem( - this@AboutActivity, - ACTION_WEBSITE, - R.drawable.ic_website, - R.string.about_option_website, - BuildInfo.PROJECT_SITE - )) - add(createSimpleIconTextItem( - this@AboutActivity, - ACTION_EMAIL, - R.drawable.ic_email, - R.string.about_option_email, - BaseApplication.EMAIL - )) - add(createSimpleIconTextItem( - this@AboutActivity, - ACTION_TG_GROUP, - R.drawable.ic_telegram, - R.string.discussions_on_telegram, - BaseApplication.TELEGRAM_GROUP_URL - )) - add(createSimpleIconTextItem( - this@AboutActivity, - ACTION_TG_CHANNEL, - R.drawable.ic_telegram, - R.string.official_tg_channel, - BaseApplication.TELEGRAM_CHANNEL_URL - )) + add( + createSimpleIconTextItem( + this@AboutActivity, + ACTION_WEBSITE, + R.drawable.ic_website, + R.string.about_option_website, + BuildInfo.PROJECT_SITE + ) + ) + add( + createSimpleIconTextItem( + this@AboutActivity, + ACTION_EMAIL, + R.drawable.ic_email, + R.string.about_option_email, + BaseApplication.EMAIL + ) + ) + add( + createSimpleIconTextItem( + this@AboutActivity, + ACTION_TG_GROUP, + R.drawable.ic_telegram, + R.string.discussions_on_telegram, + BaseApplication.TELEGRAM_GROUP_URL + ) + ) + add( + createSimpleIconTextItem( + this@AboutActivity, + ACTION_TG_CHANNEL, + R.drawable.ic_telegram, + R.string.official_tg_channel, + BaseApplication.TELEGRAM_CHANNEL_URL + ) + ) } } private fun createMiscItems(): List { return mutableListOf().apply { - add(SimpleIconTitleDescriptionItem.create( - this@AboutActivity, - ACTION_CONTRIBUTE, - R.drawable.ic_code, - R.string.title_contribute, - R.string.summary_contribute - )) - add(SimpleIconTitleDescriptionItem.create( - this@AboutActivity, - ACTION_CONTRIBUTORS, - R.drawable.ic_heart_outline, - R.string.title_contributors, - R.string.summary_contributors - )) + add( + SimpleIconTitleDescriptionItem.create( + this@AboutActivity, + ACTION_CONTRIBUTE, + R.drawable.ic_code, + R.string.title_contribute, + R.string.summary_contribute + ) + ) + add( + SimpleIconTitleDescriptionItem.create( + this@AboutActivity, + ACTION_CONTRIBUTORS, + R.drawable.ic_heart_outline, + R.string.title_contributors, + R.string.summary_contributors + ) + ) } } @@ -244,7 +255,8 @@ class AboutActivity : EdgeToEdgeIDEActivity() { appendForegroundSpan( builder, BuildInfoUtils.getBuildType(this).lowercase(), - color) + color + ) builder.append(")") } @@ -254,7 +266,8 @@ class AboutActivity : EdgeToEdgeIDEActivity() { text: CharSequence, color: Int ) { - builder.append(text, + builder.append( + text, ForegroundColorSpan(color), SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE ) diff --git a/app/src/main/java/com/itsaky/androidide/activities/ContributorsActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/ContributorsActivity.kt index f0c82b5a8..60847f214 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/ContributorsActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/ContributorsActivity.kt @@ -17,10 +17,10 @@ package com.itsaky.androidide.activities -import android.graphics.Rect import android.os.Bundle import android.view.View import androidx.activity.viewModels +import androidx.core.graphics.Insets import androidx.core.view.isVisible import com.itsaky.androidide.R import com.itsaky.androidide.adapters.ContributorsGridAdapter @@ -92,8 +92,8 @@ class ContributorsActivity : EdgeToEdgeIDEActivity() { } } - override fun onInsetsUpdated(insets: Rect) { - super.onInsetsUpdated(insets) + override fun onApplySystemBarInsets(insets: Insets) { + super.onApplySystemBarInsets(insets) binding.toolbar.apply { setPaddingRelative( paddingStart + insets.left, diff --git a/app/src/main/java/com/itsaky/androidide/activities/MainActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/MainActivity.kt index a8bdcd26c..172190092 100755 --- a/app/src/main/java/com/itsaky/androidide/activities/MainActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/MainActivity.kt @@ -18,12 +18,12 @@ package com.itsaky.androidide.activities import android.content.Intent -import android.graphics.Rect import android.os.Bundle import android.text.TextUtils import android.view.View import androidx.activity.OnBackPressedCallback import androidx.activity.viewModels +import androidx.core.graphics.Insets import androidx.core.view.isVisible import androidx.transition.TransitionManager import androidx.transition.doOnEnd @@ -98,9 +98,13 @@ class MainActivity : EdgeToEdgeIDEActivity() { onBackPressedDispatcher.addCallback(this, onBackPressedCallback) } - override fun onInsetsUpdated(insets: Rect) { - super.onInsetsUpdated(insets) - binding.fragmentContainersParent.setPadding(insets.left, 0, insets.right, insets.bottom) + override fun onApplySystemBarInsets(insets: Insets) { + binding.fragmentContainersParent.setPadding( + insets.left, + 0, + insets.right, + insets.bottom + ) } private fun onScreenChanged(screen: Int?) { @@ -109,7 +113,8 @@ class MainActivity : EdgeToEdgeIDEActivity() { // template list -> template details // ------- OR ------- // template details -> template list - val setAxisToX = (previous == SCREEN_TEMPLATE_LIST || previous == SCREEN_TEMPLATE_DETAILS) && (screen == SCREEN_TEMPLATE_LIST || screen == SCREEN_TEMPLATE_DETAILS) + val setAxisToX = + (previous == SCREEN_TEMPLATE_LIST || previous == SCREEN_TEMPLATE_DETAILS) && (screen == SCREEN_TEMPLATE_LIST || screen == SCREEN_TEMPLATE_DETAILS) val axis = if (setAxisToX) { MaterialSharedAxis.X diff --git a/app/src/main/java/com/itsaky/androidide/activities/PreferencesActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/PreferencesActivity.kt index de3c019a1..2880ce810 100755 --- a/app/src/main/java/com/itsaky/androidide/activities/PreferencesActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/PreferencesActivity.kt @@ -16,9 +16,9 @@ */ package com.itsaky.androidide.activities -import android.graphics.Rect import android.os.Bundle import android.view.View +import androidx.core.graphics.Insets import androidx.fragment.app.Fragment import com.itsaky.androidide.R import com.itsaky.androidide.app.EdgeToEdgeIDEActivity @@ -64,9 +64,7 @@ class PreferencesActivity : EdgeToEdgeIDEActivity() { loadFragment(rootFragment) } - override fun onInsetsUpdated(insets: Rect) { - super.onInsetsUpdated(insets) - + override fun onApplySystemBarInsets(insets: Insets) { val toolbar: View = binding.toolbar toolbar.setPadding( toolbar.paddingLeft + insets.left, @@ -86,7 +84,8 @@ class PreferencesActivity : EdgeToEdgeIDEActivity() { override fun bindLayout(): View { _binding = ActivityPreferencesBinding.inflate( - layoutInflater) + layoutInflater + ) return binding.root } diff --git a/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt index 787a508bd..c2de14cf4 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt @@ -20,7 +20,6 @@ package com.itsaky.androidide.activities.editor import android.content.Intent import android.content.pm.PackageInstaller.SessionCallback import android.graphics.Color -import android.graphics.Rect import android.graphics.drawable.GradientDrawable import android.os.Bundle import android.os.Process @@ -41,7 +40,9 @@ import androidx.annotation.GravityInt import androidx.annotation.StringRes import androidx.appcompat.app.ActionBarDrawerToggle import androidx.collection.MutableIntIntMap +import androidx.core.graphics.Insets import androidx.core.view.GravityCompat +import androidx.core.view.WindowInsetsCompat import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding import androidx.core.view.updatePaddingRelative @@ -186,6 +187,7 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele } } + private var contentCardRealHeight: Int? = null private val editorSurfaceContainerBackground by lazy { resolveAttr(R.attr.colorSurfaceDim) } @@ -262,8 +264,18 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele return this.binding.root } - override fun onInsetsUpdated(insets: Rect) { - super.onInsetsUpdated(insets) + override fun onApplyWindowInsets(insets: WindowInsetsCompat) { + super.onApplyWindowInsets(insets) + val height = contentCardRealHeight ?: return + val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime()) + _binding?.content?.bottomSheet?.setImeVisible(imeInsets.bottom > 0) + _binding?.contentCard?.updateLayoutParams { + this.height = height - imeInsets.bottom + } + } + + override fun onApplySystemBarInsets(insets: Insets) { + super.onApplySystemBarInsets(insets) this._binding?.apply { drawerSidebar.getFragment() .onApplyWindowInsets(insets) @@ -307,7 +319,8 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele if (savedInstanceState != null && savedInstanceState.containsKey(KEY_PROJECT_PATH)) { ProjectManagerImpl.getInstance().projectPath = savedInstanceState.getString( - KEY_PROJECT_PATH)!! + KEY_PROJECT_PATH + )!! } onBackPressedDispatcher.addCallback(this, onBackPressedCallback) @@ -324,8 +337,10 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele setupContainers() setupDiagnosticInfo() - uiDesignerResultLauncher = registerForActivityResult(StartActivityForResult(), - this::handleUiDesignerResult) + uiDesignerResultLauncher = registerForActivityResult( + StartActivityForResult(), + this::handleUiDesignerResult + ) setupMemUsageChart() watchMemory() @@ -334,7 +349,7 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele private fun onSwipeRevealDragProgress(progress: Float) { _binding?.apply { contentCard.progress = progress - val insetsTop = lastWindowInsets?.top ?: 0 + val insetsTop = systemBarInsets?.top ?: 0 content.editorAppBarLayout.updatePadding( top = (insetsTop * (1f - progress)).roundToInt() ) @@ -377,8 +392,10 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele protected fun resetMemUsageChart() { val processes = memoryUsageWatcher.getMemoryUsages() val datasets = Array(processes.size) { index -> - LineDataSet(List(MemoryUsageWatcher.MAX_USAGE_ENTRIES) { Entry(it.toFloat(), 0f) }, - processes[index].pname) + LineDataSet( + List(MemoryUsageWatcher.MAX_USAGE_ENTRIES) { Entry(it.toFloat(), 0f) }, + processes[index].pname + ) } val bgColor = editorSurfaceContainerBackground @@ -535,7 +552,8 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele } val index = content.bottomSheet.pagerAdapter.findIndexOfFragmentByClass( - SearchResultFragment::class.java) + SearchResultFragment::class.java + ) if (index >= 0 && index < content.bottomSheet.binding.tabs.tabCount) { content.bottomSheet.binding.tabs.getTabAt(index)?.select() @@ -559,7 +577,8 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele open fun getFileTreeFragment(): FileTreeFragment? { if (filesTreeFragment == null) { filesTreeFragment = supportFragmentManager.findFragmentByTag( - FileTreeFragment.TAG) as FileTreeFragment? + FileTreeFragment.TAG + ) as FileTreeFragment? } return filesTreeFragment } @@ -585,8 +604,10 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele private fun handleUiDesignerResult(result: ActivityResult) { if (result.resultCode != RESULT_OK || result.data == null) { - log.warn("UI Designer returned invalid result: resultCode={}, data={}", result.resultCode, - result.data) + log.warn( + "UI Designer returned invalid result: resultCode={}, data={}", result.resultCode, + result.data + ) return } val generated = result.data!!.getStringExtra(UIDesignerActivity.RESULT_GENERATED_XML) @@ -604,8 +625,10 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele } private fun setupDrawers() { - val toggle = ActionBarDrawerToggle(this, binding.editorDrawerLayout, content.editorToolbar, - string.app_name, string.app_name) + val toggle = ActionBarDrawerToggle( + this, binding.editorDrawerLayout, content.editorToolbar, + string.app_name, string.app_name + ) binding.editorDrawerLayout.addDrawerListener(toggle) toggle.syncState() @@ -621,7 +644,8 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele private fun onBuildStatusChanged() { log.debug( - "onBuildStatusChanged: isInitializing: ${editorViewModel.isInitializing}, isBuildInProgress: ${editorViewModel.isBuildInProgress}") + "onBuildStatusChanged: isInitializing: ${editorViewModel.isInitializing}, isBuildInProgress: ${editorViewModel.isBuildInProgress}" + ) val visible = editorViewModel.isBuildInProgress || editorViewModel.isInitializing content.progressIndicator.visibility = if (visible) View.VISIBLE else View.GONE invalidateOptionsMenu() @@ -650,7 +674,8 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele setupBottomSheet() if (!app.prefManager.getBoolean( - KEY_BOTTOM_SHEET_SHOWN) && editorBottomSheet?.state != BottomSheetBehavior.STATE_EXPANDED + KEY_BOTTOM_SHEET_SHOWN + ) && editorBottomSheet?.state != BottomSheetBehavior.STATE_EXPANDED ) { editorBottomSheet?.state = BottomSheetBehavior.STATE_EXPANDED ThreadUtils.runOnUiThreadDelayed({ @@ -727,10 +752,12 @@ abstract class BaseEditorActivity : EdgeToEdgeIDEActivity(), TabLayout.OnTabSele val observer: OnGlobalLayoutListener = object : OnGlobalLayoutListener { override fun onGlobalLayout() { + contentCardRealHeight = binding.contentCard.height content.also { it.realContainer.pivotX = it.realContainer.width.toFloat() / 2f - it.realContainer.pivotY = (it.realContainer.height.toFloat() / 2f) + (lastWindowInsets?.height() - ?: 0) + it.realContainer.pivotY = + (it.realContainer.height.toFloat() / 2f) + (systemBarInsets?.run { bottom - top } + ?: 0) it.viewContainer.viewTreeObserver.removeOnGlobalLayoutListener(this) } } diff --git a/app/src/main/java/com/itsaky/androidide/app/EdgeToEdgeIDEActivity.kt b/app/src/main/java/com/itsaky/androidide/app/EdgeToEdgeIDEActivity.kt index 80c951d5d..1dc2ad8ea 100644 --- a/app/src/main/java/com/itsaky/androidide/app/EdgeToEdgeIDEActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/app/EdgeToEdgeIDEActivity.kt @@ -26,8 +26,10 @@ import android.os.PersistableBundle import android.view.WindowInsets import android.view.WindowManager import androidx.annotation.CallSuper +import androidx.core.graphics.Insets import androidx.core.view.OnApplyWindowInsetsListener import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import androidx.core.view.doOnAttach import com.itsaky.androidide.utils.EdgeToEdgeUtils import com.itsaky.androidide.utils.getSystemBarInsets @@ -70,7 +72,7 @@ abstract class EdgeToEdgeIDEActivity : IDEActivity() { /** * Last window insets. */ - protected open var lastWindowInsets: Rect? = null + protected open var systemBarInsets: Insets? = null override var enableSystemBarTheming: Boolean get() = false @@ -82,9 +84,10 @@ abstract class EdgeToEdgeIDEActivity : IDEActivity() { @SuppressLint("WrongConstant") private val onApplyWindowInsetsListener = OnApplyWindowInsetsListener { v, insets -> + onApplyWindowInsets(insets) if (!eteUpdateDecorViewPaddingInLandscape || - v.resources.configuration.orientation != Configuration.ORIENTATION_LANDSCAPE - ) { + v.resources.configuration.orientation != Configuration.ORIENTATION_LANDSCAPE + ) { decorViewPadding?.also { p -> // when switching from landscape to portrait, restore the original padding v.setPadding(p.left, p.top, p.right, p.bottom) @@ -104,18 +107,21 @@ abstract class EdgeToEdgeIDEActivity : IDEActivity() { } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val systemBarInsets = insets.getInsets(WindowInsets.Type.systemBars()) v.setPadding( - insets.getInsets(WindowInsets.Type.systemBars()).left, + systemBarInsets.left, 0, - insets.getInsets(WindowInsets.Type.systemBars()).right, - insets.getInsets(WindowInsets.Type.systemBars()).bottom) + systemBarInsets.right, + systemBarInsets.bottom + ) } else { @Suppress("DEPRECATION") v.setPadding( insets.stableInsetLeft, 0, insets.stableInsetRight, - insets.stableInsetBottom) + insets.stableInsetBottom + ) } insets @@ -146,12 +152,21 @@ abstract class EdgeToEdgeIDEActivity : IDEActivity() { this.onApplyWindowInsetsListener ) - this.window.decorView.doOnAttach { decorView -> onInsetsUpdated(getSystemBarInsets(decorView)) } + this.window.decorView.doOnAttach { onApplySystemBarInsets(getSystemBarInsets(it)) } } - /** Called whenever insets are updated */ + /** + * Called when the window insets change. + * + * @param insets The window insets. These insets are not expected to be consumed. + */ @CallSuper - protected open fun onInsetsUpdated(insets: Rect) { - this.lastWindowInsets = insets + protected open fun onApplyWindowInsets(insets: WindowInsetsCompat) { + this.systemBarInsets = getSystemBarInsets(insets) } + + /** + * Called with the system bar insets when the decor view is attached to the window. + */ + protected open fun onApplySystemBarInsets(insets: Insets) {} } diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sidebar/EditorSidebarFragment.kt b/app/src/main/java/com/itsaky/androidide/fragments/sidebar/EditorSidebarFragment.kt index 5fa152fd6..a54592dc0 100644 --- a/app/src/main/java/com/itsaky/androidide/fragments/sidebar/EditorSidebarFragment.kt +++ b/app/src/main/java/com/itsaky/androidide/fragments/sidebar/EditorSidebarFragment.kt @@ -17,16 +17,15 @@ package com.itsaky.androidide.fragments.sidebar -import android.graphics.Rect import android.os.Bundle import android.view.View import android.view.ViewGroup.MarginLayoutParams +import androidx.core.graphics.Insets import androidx.core.view.marginBottom import androidx.core.view.marginTop import androidx.core.view.updateLayoutParams import androidx.core.view.updateMarginsRelative import androidx.core.view.updatePadding -import androidx.core.view.updatePaddingRelative import com.itsaky.androidide.databinding.FragmentEditorSidebarBinding import com.itsaky.androidide.fragments.FragmentWithBinding import com.itsaky.androidide.utils.EditorSidebarActions @@ -40,7 +39,7 @@ class EditorSidebarFragment : FragmentWithBinding( FragmentEditorSidebarBinding::inflate ) { - internal fun onApplyWindowInsets(insets: Rect) { + internal fun onApplyWindowInsets(insets: Insets) { _binding?.apply { title.updateLayoutParams { updateMarginsRelative( diff --git a/app/src/main/java/com/itsaky/androidide/ui/EditorBottomSheet.kt b/app/src/main/java/com/itsaky/androidide/ui/EditorBottomSheet.kt index f6c726547..3f641205f 100644 --- a/app/src/main/java/com/itsaky/androidide/ui/EditorBottomSheet.kt +++ b/app/src/main/java/com/itsaky/androidide/ui/EditorBottomSheet.kt @@ -19,7 +19,6 @@ package com.itsaky.androidide.ui import android.app.Activity import android.content.Context -import android.graphics.Color import android.text.TextUtils import android.util.AttributeSet import android.view.LayoutInflater @@ -60,7 +59,6 @@ import com.itsaky.androidide.tasks.TaskExecutor.executeAsyncProvideError import com.itsaky.androidide.utils.IntentUtils.shareFile import com.itsaky.androidide.utils.Symbols.forFile import com.itsaky.androidide.utils.flashError -import com.itsaky.androidide.utils.resolveAttr import org.slf4j.LoggerFactory import java.io.File import java.io.IOException @@ -89,13 +87,24 @@ constructor( val localContext = getContext() ?: return@lazy 0f localContext.resources.getDimension(R.dimen.editor_sheet_collapsed_height) } + private val behavior: BottomSheetBehavior by lazy { + BottomSheetBehavior.from(this).apply { + isFitToContents = false + skipCollapsed = true + } + } @JvmField var binding: LayoutEditorBottomSheetBinding val pagerAdapter: EditorBottomSheetTabAdapter + private var anchorOffset = 0 + private var isImeVisible = false private var windowInsets: Insets? = null + private val insetBottom: Int + get() = if (isImeVisible) 0 else windowInsets?.bottom ?: 0 + companion object { private val log = LoggerFactory.getLogger(EditorBottomSheet::class.java) @@ -165,9 +174,8 @@ constructor( } binding.headerContainer.setOnClickListener { - val sheet = BottomSheetBehavior.from(this) - if (sheet.state != BottomSheetBehavior.STATE_EXPANDED) { - sheet.state = BottomSheetBehavior.STATE_EXPANDED + if (behavior.state != BottomSheetBehavior.STATE_EXPANDED) { + behavior.state = BottomSheetBehavior.STATE_EXPANDED } } @@ -193,23 +201,26 @@ constructor( initialize(context) } + /** + * Set whether the input method is visible. + */ + fun setImeVisible(isVisible: Boolean) { + isImeVisible = isVisible + behavior.isGestureInsetBottomIgnored = isVisible + } + fun setOffsetAnchor(view: View) { val listener = object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { - val sheet = BottomSheetBehavior.from(this@EditorBottomSheet) - val offset = view.height + SizeUtils.dp2px(1f) - val collapsedHeight = collapsedHeight - - sheet.isFitToContents = false - sheet.skipCollapsed = true - sheet.isGestureInsetBottomIgnored = false - sheet.peekHeight = collapsedHeight.roundToInt() - sheet.expandedOffset = offset view.viewTreeObserver.removeOnGlobalLayoutListener(this) + anchorOffset = view.height + SizeUtils.dp2px(1f) - val insetBottom = windowInsets?.bottom ?: 0 - binding.root.updatePadding(bottom = offset + insetBottom) + behavior.peekHeight = collapsedHeight.roundToInt() + behavior.expandedOffset = anchorOffset + behavior.isGestureInsetBottomIgnored = isImeVisible + + binding.root.updatePadding(bottom = anchorOffset + insetBottom) binding.headerContainer.apply { updatePaddingRelative(bottom = paddingBottom + insetBottom) updateLayoutParams { @@ -229,19 +240,14 @@ constructor( 1f } - val paddingScale = if (sheetOffset <= COLLAPSE_HEADER_AT_OFFSET) { + val paddingScale = if (!isImeVisible && sheetOffset <= COLLAPSE_HEADER_AT_OFFSET) { ((1f - sheetOffset) * 2f) - 1f } else { 0f } - - val insetBottom = windowInsets?.bottom ?: 0 + val padding = insetBottom * paddingScale binding.headerContainer.apply { - var color = Color.valueOf(context.resolveAttr(R.attr.colorSurface)) - color = Color.valueOf(color.red(), color.green(), color.blue(), (1f - paddingScale)) - setBackgroundColor(color.toArgb()) - updateLayoutParams { height = ((collapsedHeight + padding) * heightScale).roundToInt() } diff --git a/app/src/main/res/layout/layout_editor_bottom_sheet.xml b/app/src/main/res/layout/layout_editor_bottom_sheet.xml index 4dd0c6ade..32dae572b 100644 --- a/app/src/main/res/layout/layout_editor_bottom_sheet.xml +++ b/app/src/main/res/layout/layout_editor_bottom_sheet.xml @@ -36,7 +36,8 @@ android:id="@+id/header_container" android:layout_width="match_parent" android:layout_below="@id/border" - android:layout_height="@dimen/editor_sheet_collapsed_height"> + android:layout_height="@dimen/editor_sheet_collapsed_height" + android:background="?attr/colorSurface"> = Build.VERSION_CODES.Q) { - - val receivedInsets: Insets = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - val typeMask = WindowInsets.Type.systemBars() or WindowInsets.Type.displayCutout() - rootWindowInsets.getInsetsIgnoringVisibility(typeMask) - } else { - @Suppress("DEPRECATION") - view.rootWindowInsets.stableInsets - } - - insets = Rect( - receivedInsets.left, - receivedInsets.top, - receivedInsets.right, - receivedInsets.bottom - ) - } else { +/** + * Acquires system bar and display cutout insets. + * + * @param insets The window insets. + * @return [Insets] containing acquired insets. + */ +fun getSystemBarInsets(insets: WindowInsetsCompat): Insets { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { @Suppress("DEPRECATION") - insets = Rect( - rootWindowInsets.stableInsetLeft, - rootWindowInsets.stableInsetTop, - rootWindowInsets.stableInsetRight, - rootWindowInsets.stableInsetBottom - ) + return insets.stableInsets } - return insets + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + @Suppress("DEPRECATION") + return insets.stableInsets + } + + val typeMask = WindowInsets.Type.systemBars() or WindowInsets.Type.displayCutout() + + // noinspection WrongConstant + return insets.getInsetsIgnoringVisibility(typeMask) }