ConstraintSet doesn't work with nested ConstraintLayouts - android

I have two activities, activity_main.xml and activity_main_details.xml and I want the elements from the first activity to transition to the second one.
First activity:
This activity is made up of two separate constraint layouts which are included in another layout. Code below:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/root">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/background_color"
android:transitionName="firstHalf"
app:layout_constraintBottom_toTopOf="#+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/photo"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginTop="64dp"
android:src="#drawable/ic_add"
android:transitionName="photo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="#string/add_log_here"
android:textColor="#color/white"
android:textSize="18sp"
android:transitionName="title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/photo" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.35" />
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:transitionName="secondHalf"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/guideline">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintLayout2"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/guideline">
<-- more code here -->>
Second activity is:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/root"
tools:context=".authenthicaton.joinUs.add_company_logo_animation">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/background_color"
android:transitionName="firstHalf"
app:layout_constraintBottom_toTopOf="#+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/photo"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="32dp"
android:layout_marginTop="8dp"
android:src="#drawable/ic_add"
android:transitionName="photo"
app:layout_constraintStart_toEndOf="#+id/textView4"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="16dp"
android:text="#string/add_log_here"
android:textColor="#color/white"
android:textSize="18sp"
android:transitionName="title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.08" />
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:transitionName="secondHalf"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/guideline">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/constraintLayout2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/guideline">
<-- more code here -->
The issue is that there should be a transition for the elements:
photo #+id/photo
textView #+id/textView4
They should change the position from the first activity to the second one. In other words the second activity should be the result after the animation.
Here is the actual kotlin code:
val root = findViewById<ConstraintLayout>(R.id.root)
var set = false
val constraint1 = ConstraintSet()
constraint1.clone(root)
val constraint2 = ConstraintSet()
constraint2.clone(this, R.layout.activity_main_details)
val floatingActionButton = findViewById<FloatingActionButton>(R.id.floatingActionButton)
floatingActionButton.setOnClickListener{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val transition = ChangeBounds()
transition.duration = 300
TransitionManager.beginDelayedTransition(root, transition)
val constraint = if(set) constraint1 else constraint2
constraint.applyTo(root)
set = !set
}
}
My result (after the animation) :
As you can see the photo and the textview haven't changed their first position. This being the reason to why they are not there.
I have also tried to use ActivityOptions.makeSceneTransitionAnimation but this complicated my code a lot because of the focus(related to edittext boxes) issues I had.
Does anyone know why the photo and the textview havent changed like they should've done? Is constrainSet having issues with nested Constrained layouts?

I haven't been successful with ConstrainSet so I ended up using scene which really worked in my case.
Due to the fact that I have multiple nested ConstrainedLayouts , ConstrainedSet is not going to work as #Pawel pointed out. Declaring ConstrainedSet for each of the subchildren didn't worked either.
Anyway, this is my solution using scene.
val transition = ChangeBounds()
transition.duration = 800
val scene = Scene.getSceneForLayout(findViewById<ConstraintLayout>(R.id.root),
R.layout.activity_main_details,
this)
findViewById<FloatingActionButton>(R.id.floatingActionButton).setOnClickListener {
TransitionManager.go(scene, transition)
// more code here
}

Related

RecyclerView's last item is cut off when TextView Error Banner is visible. I'm using Constraint Layout with Barrier

I'm not sure how to ask this question. It seems easy to do but I'm not sure why it's not working. Anyways, here goes. I have this Error Banner that should be visible only if the total "Weight" for the Categories is less than or greater than 100. However my issue is that when the error banner is visible, my RecyclerView's last item is cut off, I think by the height of the error banner.
It will only be fixed if I edit it once again and the keyboard is shown, the recyclerview's height is refreshed (probably).
Here's my Layout XML:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".presentation.screens.gradesetup.gradingcategories.GradingCategoriesFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/layoutParent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/layoutGradeCategoryList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constrainedHeight="true" >
<TextView
android:id="#+id/tvInvalidGradeWeightLayout"
style="#style/Default_Text_Error_Banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/default_margin_size_16dp"
android:text="#string/error_invalid_grade_category_weight"
android:visibility="gone" />
<!-- Constraint layout_constraintHeight_max dynamically to 24% -->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvGradingCategories"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tvInfoNoData"
style="#style/Default_Text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/text_no_data_display"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="layoutGradeCategoryList" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/layout_adjust_weight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/default_margin_size_16dp"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="#+id/buttonSave"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/barrier"
app:layout_constraintVertical_bias="0.01">
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="#+id/switchViewAdjustWeight"
style="#style/Default_Text_Bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="#dimen/screen_padding_size"
android:text="#string/text_adjust_weight"
android:theme="#style/Theme.LMS"
android:visibility="gone" />
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/default_margin_size_30dp"
android:src="#drawable/ic_plus"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:tint="#color/white" />
<androidx.appcompat.widget.AppCompatButton
android:id="#+id/buttonSave"
style="#style/Primary_Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/default_margin_size_30dp"
android:enabled="false"
android:text="#string/text_save"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
As you can see I also have this Constraint Barrier, so whenever the height of the RecyclerView is longer, the SwitchMaterial("switchViewAdjustWeight") is also adjusted. I set the android:layout_constraintHeight_max dynamically based on device height.
// Dynamically set constraintMaxHeight
var constraintMaxHeight = 0
constraintMaxHeight =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowMetrics = activity!!.windowManager.currentWindowMetrics
val insets: Insets = windowMetrics.windowInsets
.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())
val height = windowMetrics.bounds.height() - insets.top - insets.bottom
(height * 0.7).toInt()
} else {
val displayMetrics = DisplayMetrics()
activity!!.windowManager.defaultDisplay.getMetrics(displayMetrics)
(displayMetrics.heightPixels * 0.7).toInt()
}
val constraintSet = ConstraintSet()
constraintSet.clone(layoutParent)
constraintSet.constrainMaxHeight(R.id.layoutGradeCategoryList, constraintMaxHeight)
constraintSet.applyTo(layoutParent)
In my code (kotlin): the error banner is toggled to visible if sum != 100
val result = sum == 100
binding.apply {
buttonSave.isEnabled = result
tvInvalidGradeWeightLayout.isVisible = !result
}
Target UI:
I also did change LinearLayout to ConstraintLayout However it didn't work, the Banner overlaps with the RecyclerView list :
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/layoutParent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/layoutGradeCategoryList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constrainedHeight="true" >
<TextView
android:id="#+id/tvInvalidGradeWeightLayout"
style="#style/Default_Text_Error_Banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/default_margin_size_16dp"
android:text="#string/error_invalid_grade_category_weight"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"/>
<!-- Constraint layout_constraintHeight_max dynamically to 24% -->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvGradingCategories"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constraintTop_toBottomOf="#+id/tvInvalidGradeWeightLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tvInfoNoData"
style="#style/Default_Text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/text_no_data_display"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="layoutGradeCategoryList" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/layout_adjust_weight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/default_margin_size_16dp"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="#+id/buttonSave"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/barrier"
app:layout_constraintVertical_bias="0.01">
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="#+id/switchViewAdjustWeight"
style="#style/Default_Text_Bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="#dimen/screen_padding_size"
android:text="#string/text_adjust_weight"
android:theme="#style/Theme.LMS"
android:visibility="gone" />
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/default_margin_size_30dp"
android:src="#drawable/ic_plus"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:tint="#color/white" />
<androidx.appcompat.widget.AppCompatButton
android:id="#+id/buttonSave"
style="#style/Primary_Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/default_margin_size_30dp"
android:enabled="false"
android:text="#string/text_save"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
This worked for me, I added getViewTreeObserver().addOnGlobalLayoutListener for layoutGradeCategoryList and trigger the request layout there.
layoutGradeCategoryList.getViewTreeObserver().addOnGlobalLayoutListener(OnGlobalLayoutListener {
layoutGradeCategoryList.requestLayout();
})
This helped me understand more on requestLayout/forceLayout/invalidate view.
https://stackoverflow.com/a/42430695/3777452
Hope this helps someone else.

Custom Android CardView Dialog Preview different

I want to display a custom dialog using a cardView to display some information. The preview looks exactly like it should and is previewed in Android Studio the following:
The quick_preview.xml xml for this is
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/SensorOverView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:minWidth="300dp"
android:minHeight="300dp"
android:visibility="visible"
app:cardCornerRadius="20dp"
app:cardElevation="10dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/parentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="160dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/scrollView2">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/subTitleLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toTopOf="#+id/titleLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="#+id/btnClose"
android:layout_width="72dp"
android:layout_height="24dp"
android:layout_weight="1"
android:background="#color/background_light_elevation_1"
android:text="Button"
android:textColor="#78909C"
app:icon="#drawable/ic_baseline_close_24"
app:iconTint="#color/app_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txtSubtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="Lorem Ipsum"
android:textSize="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btnClose"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/titleLayout"
android:layout_width="0dp"
android:layout_height="45dp"
app:layout_constraintBottom_toTopOf="#+id/viewContent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/subTitleLayout">
<TextView
android:id="#+id/txtTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="Lorem ipsum"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/rejectOrAddLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/viewContent">
<Button
android:id="#+id/btnReject"
android:layout_width="72dp"
android:layout_height="56dp"
android:background="#FF5454"
android:text="Button"
app:icon="#drawable/ic_baseline_close_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btnAdd"
app:layout_constraintStart_toEndOf="#+id/txtInfo"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btnAdd"
android:layout_width="72dp"
android:layout_height="56dp"
android:layout_weight="1"
android:background="#00D7A0"
android:text="Button"
app:icon="#drawable/ic_baseline_check_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/btnReject"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txtInfo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:maxHeight="56dp"
android:text="Select to delete/add"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btnReject"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/viewContent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toTopOf="#+id/rejectOrAddLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/titleLayout"
tools:listitem="#layout/sensor_content_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
The dialog uses a custom class QuickPreviewDialog.kt
class QuickPreviewDialog(context: Context) : Dialog(context) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.requestWindowFeature(Window.FEATURE_NO_TITLE)
this.setCancelable(false);
this.setContentView(R.layout.sensor_quick_preview);
this.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
}
and is invoked by:
val dialog = QuickPreviewDialog(this)
dialog.show()
But the result is the following and I don't know what's wrong:
To achieve what you want without changing too much code,a simple solution i would suggest you to use is putting a LinearLayout as your cardView's parent
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content">
<androidx.cardview.widget.CardView
android:id="#+id/SensorOverView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:minWidth="300dp"
android:minHeight="300dp"
android:visibility="visible"
app:cardCornerRadius="20dp"
app:cardElevation="10dp">
//Rest of your view
</androidx.cardview.widget.CardView>
</LinearLayout>
And just like that you see your dialog's size as same as you want it to be
Android dialogs tend to have their own ideas about how large they should be. We will address the dialog size, but first you will need to change how the minimum height and width is specified in the CardView.
Change
android:minWidth="300dp"
android:minHeight="300dp"
to
app:minWidth="300dp"
app:minHeight="300dp"
If you just make this change, you should see your entire layout crammed into the small dialog window. This is the correct way to specify minimum sizes for CardViews.
You will have to programmatically adjust the dialog window's size by doing something like the following to override the defaults:
val padding = 160
val dialog = QuickPreviewDialog(this)
dialog.show()
// Set the window's size only after dialog.show()
val widthHeight = getScreenSize()
dialog.window?.setLayout(widthHeight.first - padding, widthHeight.second - padding)
private fun getScreenSize() =
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
Pair(
displayMetrics.widthPixels,
displayMetrics.heightPixels
)
} else {
val bounds = windowManager.currentWindowMetrics.bounds
Pair(bounds.width(), bounds.height())
}

Problem setting color in toolbar (android-kotlin)

I'm having a problem with my toolbar.
I want the device app and toolbar to be the same color, but don't use findviewbyid. (I'm migrating the entire project just to view binding
)
OK behavior (using findviewbyid).
NOK behavior (using view binding), is giving a little misalignment of the textView, it seems to receive a margin that was not placed.
But if I declare different in onWindowsInsetsChanged method or don't use it, I get another problem, the color is not correct.
Using findviewbyid:
override fun onWindowsInsetsChanged(view: View, insets: WindowInsets, padding: InitialPadding) {
with(binding) {
val toolbar = fragmentEditObjectiveNameRoot.findViewById<View>(R.id.toolbar)
toolbar.updatePadding(top = topInset)
editObjectiveNameRoot.updatePadding(
bottom = insets.systemWindowInsetBottom
)
}
}
Using view binding:
override fun onWindowsInsetsChanged(view: View, insets: WindowInsets, padding: InitialPadding) {
with(binding) {
//calling the include toolbar and the root of the toolbar fragment
toolbar.viewImageToolbar.updatePadding(
top = topInset
)
editObjectiveNameRoot.updatePadding(
bottom = insets.systemWindowInsetBottom
)
}
}
Different declaration in onWindowsInsetsChanged:
override fun onWindowsInsetsChanged(view: View, insets: WindowInsets, padding: InitialPadding) {
with(binding) {
//calling root from fragment and instead of calling the include toolbar and its root
fragmentEditObjectiveNameRoot.updatePadding(
top = topInset
)
editObjectiveNameRoot.updatePadding(
bottom = insets.systemWindowInsetBottom
)
}
}
I would like to leave the same color behavior when using findviewbyid, but with view binding, but without losing textView alignment.
Here is the xml that receives the toolbar include:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/fragmentEditObjectiveNameRoot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/editObjectiveNameRoot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="#+id/bgColorFrameLayout"
android:layout_width="match_parent"
android:layout_height="#dimen/color_frame_layout_height"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/toolbar" />
<androidx.core.widget.NestedScrollView
android:id="#+id/scrollView"
android:layout_width="0dp"
android:layout_height="0dp"
android:fillViewport="true"
android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/toolbar">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="#dimen/screen_margin_horizontal"
android:layout_marginTop="18dp"
android:layout_marginEnd="#dimen/screen_margin_horizontal"
android:paddingBottom="16dp">
<com.google.android.material.card.MaterialCardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#color/bari_white"
app:cardCornerRadius="#dimen/card_corner_radius"
app:cardElevation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/card_padding">
<TextView
android:id="#+id/titleSubAccount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/sub_account_control_settings_edit_name"
android:textAlignment="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<br.com.bancobari.core_ui.views.text_input.BariTextInputLayout
android:id="#+id/nameInputLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:helperIconEnabled="true"
app:helperStart_enabled="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/titleSubAccount">
<br.com.bancobari.core_ui.views.text_input.BariTextInputEditText
android:id="#+id/nameEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName|textCapWords"
android:maxLength="16"
android:textAlignment="center"
android:textSize="16sp" />
</br.com.bancobari.core_ui.views.text_input.BariTextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<br.com.bancobari.core_ui.views.SubmitButton
android:id="#+id/saveButton"
style="#style/DefaultButton.Icon.Arrow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="18dp"
android:text="#string/objective_settings_save"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/cardView"
app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<include
android:id="#+id/toolbar"
layout="#layout/view_image_toolbar" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Here the toolbar xml
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="#+id/viewImageToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:minHeight="#dimen/custom_toolbar_height"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<View
android:layout_width="0dp"
android:layout_height="#dimen/custom_toolbar_height" />
</androidx.appcompat.widget.Toolbar>
<TextView
android:id="#+id/iconEmojiView"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="10dp"
android:gravity="bottom"
android:textSize="22.5sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="#id/toolbarTitleTextView"
app:layout_constraintEnd_toStartOf="#+id/toolbarTitleTextView"
tools:visibility="visible" />
<TextView
android:id="#+id/toolbarTitleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:ellipsize="end"
android:fontFamily="#font/nunito_bold"
android:gravity="center"
android:lines="1"
android:textColor="#color/text_neutral_gray_800"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="#id/viewImageToolbar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Teste" />
<ImageView
android:id="#+id/toolbarRightIconImageView"
style="#style/Widget.AppCompat.ActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_settings"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="#id/toolbarTitleTextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#id/toolbarTitleTextView" />
</androidx.constraintlayout.widget.ConstraintLayout>
In your first block of code with findViewById, this
val toolbar = fragmentEditObjectiveNameRoot.findViewById<View>(R.id.toolbar)
returns the ConstraintLayout at the root of your included layout with the ID toolbar.
The property toolbar in your binding is another binding for the included layout rather than the root view of that layout. The root property of that included binding in this case is the same ConstraintLayout from above, so you should use instead:
toolbar.root.updatePadding(
top = topInset
)
What you were doing was changing the padding of an inner view of your complete Toolbar layout, the viewImageToolbar element.

How to fix a NestedScrollView when click on editText with Kotlin

I have a NestedScrollView that contains a lot of components like a recyclerview, viewPager ...
I have an editText, for search.Also, an AppBar that contains a search icon.When I click on search icon the editText slideDown, and when I click a second time on in it slideUP.
My problem is when I scrolling the activity down for example, and when I click on search editText, the activity is not fixed, move up and out of the screen.
Here's main_activity.xml code :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/grey"
android:fitsSystemWindows="false"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/whiteFour"
android:paddingTop="#dimen/spacing_medium"
android:paddingBottom="#dimen/spacing_medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/searchButtonMain"
android:layout_width="30dp"
android:layout_height="28dp"
android:layout_marginEnd="#dimen/spacing_middle"
android:adjustViewBounds="true"
android:tint="#color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/Chart"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_search" />
<.....>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:id="#+id/lytSearchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/whiteFour"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/searchFields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="10dp"
android:background="#drawable/border"
android:drawableStart="#drawable/icn_search_x"
android:drawablePadding="#dimen/spacing_large"
android:fontFamily="#font/cairo"
android:gravity="left"
android:hint="#string/search_product"
android:inputType="text"
android:lineHeight="18dp"
android:maxLines="1"
android:paddingStart="15dp"
android:paddingTop="5dp"
android:paddingEnd="15dp"
android:paddingBottom="5dp"
android:textColorHint="#color/greyish"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
</LinearLayout>
<androidx.core.widget.NestedScrollView
android:id="#+id/nestedScrollView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/grey"
android:clipToPadding="true"
android:fillViewport="true"
android:scrollbars="none"
android:scrollingCache="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/appBarLayout">
<................>
When I click on search button :
searchButtonMain.setOnClickListener {
if (firstClickSearch) {
val animation = AnimationUtils.loadAnimation(
this, R.anim.slide_up
)
//appending animation to textView
lytSearchView.startAnimation(animation)
lytSearchView.visibility = View.GONE
firstClickSearch = false
} else {
val animation = AnimationUtils.loadAnimation(
this, R.anim.slide_down
)
//appending animation to textView
lytSearchView.startAnimation(animation)
lytSearchView.visibility = View.VISIBLE
firstClickSearch = true
}
}
So, what should I do to fix the NestedScrollView when click on search editText with Kotlin

Android motion layout not working accordingly

I am new to motionlayout and been following various tutorials online like this to get an understanding of how it works. From a nutshell I have come to know it basically animates constraintSets, you have a start and end constraintSet which you can further customize with KeyFrameSets. I have this layout
I want to mimic Lyft's bottom sheet
With my layout the Where are you going button is suppose to slowly fade out as the search destination textInputs fade in. The recyclerview at the bottom is suppose to hold saved addresses, it will not be affected. I tried this implementation using a standard bottomsheet but had challenges with the animation, it had this weird flickering so I decided to use a MotionLayout with a normal view.
My bottomsheet layout is as follows
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/cardChooseAddressBottomSheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
app:shapeAppearance="#style/ShapeAppearanceRoundedLargeTopCorners">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/bottomSheetConstraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/swipeUpHandle"
android:layout_width="50dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:background="#drawable/ic_swipe_up_handle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/hiThere"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/medium_margin"
android:text="#string/hi_there"
android:textAppearance="#style/h6_headline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/swipeUpHandle"
/>
<com.google.android.material.button.MaterialButton
android:id="#+id/btnSearch"
style="#style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginTop="#dimen/medium_margin"
android:gravity="start|center_vertical"
android:letterSpacing="0.0"
android:text="#string/where_are_you_going"
android:textAllCaps="false"
android:textAppearance="#style/subtitle1"
android:textColor="#android:color/darker_gray"
app:backgroundTint="#android:color/white"
app:icon="#drawable/ic_search"
app:iconTint="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/hiThere"
app:shapeAppearanceOverlay="#style/ShapeAppearanceRoundedMediumAllCorners" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/addressViews"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/btnSearch">
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/inputOrigin"
style="#style/textInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/medium_margin"
android:hint="#string/search_destination"
android:textColorHint="#android:color/darker_gray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/edtOrigin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:textAppearance="#style/subtitle1"
android:textColor="#android:color/white" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/inputDestination"
style="#style/textInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/medium_margin"
android:hint="#string/search_destination"
android:textColorHint="#android:color/darker_gray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/inputOrigin">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/edtDestination"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:textAppearance="#style/subtitle1"
android:textColor="#android:color/white" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/recyclerAddresses"
android:layout_marginTop="#dimen/medium_margin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/addressViews"
tools:listitem="#layout/recycler_view_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
And my parent layout where I include the bottomsheet is as follows
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/motionLayout"
app:layoutDescription="#xml/taxi_bottomsheet_scene"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
layout="#layout/choose_destination_bottom_sheet_layout"/>
</androidx.constraintlayout.motion.widget.MotionLayout>
And finally my taxi_bottomsheet_scene motion scene is
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
app:constraintSetEnd="#+id/expanded"
app:constraintSetStart="#+id/collapsed"
app:duration="1000">
<OnSwipe
app:touchAnchorId="#+id/btnSearch"
app:touchAnchorSide="top"
app:dragDirection="dragUp"/>
</Transition>
<ConstraintSet android:id="#+id/expanded">
<Constraint
android:id="#+id/cardChooseAddressBottomSheet"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHeight_percent="1"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0" />
<Constraint
android:id="#+id/addressViews"
app:layout_constraintHeight_percent="1"/>
<Constraint
android:id="#+id/btnSearch"
app:layout_constraintHeight_percent="0"/>
</ConstraintSet>
<ConstraintSet android:id="#+id/collapsed">
<Constraint
android:id="#+id/cardChooseAddressBottomSheet"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHeight_percent="0.4"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<Constraint
android:id="#+id/addressViews"
app:layout_constraintHeight_percent="0.0"/>
<Constraint
android:id="#+id/btnSearch"
app:layout_constraintHeight_percent="0.0"/>
</ConstraintSet>
</MotionScene>
When I launch this app I cannot get the bottomsheet to slide up, it simply does not respond in any way. One thing I noticed though is after adding the app:layoutDescription="#xml/taxi_bottomsheet_scene"attribute, the bottom sheet size changed to what I had specified in the constraintSetStart but the addressViews view did not.
So my layout looks like
So my question is, where I am going wrong for my bottomsheet not to respond to my swipes and addressViews to disappear in the initial state?
I finally managed to make it work, both with MotionLayout and CoordinatorLayout. I will only post the Coordinator solution as it is long and I do not have the time, if someone needs it, comment and I will post.
I created 3 layouts, 1. The main layout with the map, 2. Top bar with the to and from address EditTexts and 3. The bottom layout that slides up and reveals the top bar.
Solution 1 using CoordinatorLayout
The topbar
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:layout_marginBottom="#dimen/medium_margin"
app:layout_scrollFlags="noScroll">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/topToolBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="#drawable/ic_arrow_back_black_24dp" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/addressViews"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginEnd="#dimen/activity_horizontal_margin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/topToolBar">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/imgOrigin"
android:layout_width="#dimen/activity_horizontal_margin"
android:layout_height="#dimen/activity_horizontal_margin"
android:layout_marginStart="#dimen/medium_margin"
android:layout_marginEnd="#dimen/medium_margin"
app:layout_constraintBottom_toBottomOf="#+id/inputOrigin"
app:layout_constraintEnd_toStartOf="#+id/inputOrigin"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/inputOrigin"
app:srcCompat="#drawable/ic_origin"
app:tint="#color/colorAccent" />
<View
android:layout_width="2dp"
android:layout_height="0dp"
android:layout_marginTop="#dimen/xsmall_margin"
android:layout_marginBottom="#dimen/xsmall_margin"
android:background="#drawable/accent_to_color_primary_dark__negative_90_gradient"
app:layout_constraintBottom_toTopOf="#+id/imgDestination"
app:layout_constraintEnd_toEndOf="#+id/imgOrigin"
app:layout_constraintStart_toStartOf="#+id/imgOrigin"
app:layout_constraintTop_toBottomOf="#+id/imgOrigin" />
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/inputOrigin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/medium_margin"
android:hint="#string/pick_up_location"
android:marqueeRepeatLimit="marquee_forever"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imgOrigin"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/edtOrigin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:inputType="textPostalAddress"
android:singleLine="true"
android:textAppearance="#style/subtitle1" />
</com.google.android.material.textfield.TextInputLayout>
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/imgDestination"
android:layout_width="#dimen/activity_horizontal_margin"
android:layout_height="#dimen/activity_horizontal_margin"
android:layout_marginStart="#dimen/medium_margin"
android:layout_marginEnd="#dimen/medium_margin"
app:layout_constraintBottom_toBottomOf="#+id/inputDestination"
app:layout_constraintEnd_toStartOf="#+id/inputDestination"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/inputDestination"
app:srcCompat="#drawable/ic_destination"
app:tint="#color/colorPrimaryDark" />
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/inputDestination"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/medium_margin"
android:hint="#string/search_destination"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imgDestination"
app:layout_constraintTop_toBottomOf="#id/inputOrigin">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/edtDestination"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:inputType="textPostalAddress"
android:singleLine="true"
android:textAppearance="#style/subtitle1" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
The bottom layout that acts like a bottom sheet
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/cardChooseAddressBottomSheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardBackgroundColor="#color/white"
app:behavior_hideable="false"
app:layout_behavior="#string/bottom_sheet_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/swipeUpHandle"
android:layout_width="35dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
android:background="#drawable/ic_swipe_up_handle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/hiThere"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hi_there"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
android:textAppearance="#style/h6_headline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/swipeUpHandle" />
<com.google.android.material.button.MaterialButton
android:id="#+id/btnSearch"
style="#style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
android:gravity="start|center_vertical"
android:letterSpacing="0.0"
android:text="#string/where_are_you_going"
android:textAllCaps="false"
android:textAppearance="#style/subtitle1"
android:textColor="#android:color/darker_gray"
app:backgroundTint="#android:color/white"
app:icon="#drawable/ic_search"
app:iconSize="#dimen/medium_icon"
app:iconTint="#color/colorAccent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/hiThere"
app:shapeAppearanceOverlay="#style/ShapeAppearanceRoundedMediumAllCorners" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerAddresses"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/btnSearch" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerSearchAddresses"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/white"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/btnSearch" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
And finally the two layouts included in my map layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:id="#+id/coordinator"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.67"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imgMapCenter"
android:layout_marginBottom="#dimen/xlarge_margin"
android:visibility="invisible"
android:tint="#color/colorAccent"
app:layout_constraintBottom_toBottomOf="#id/map"
app:layout_constraintEnd_toEndOf="#id/map"
app:layout_constraintStart_toStartOf="#id/map"
app:layout_constraintTop_toTopOf="#id/map"
app:srcCompat="#drawable/ic_destination" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fabMyLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/activity_horizontal_margin"
app:backgroundTint="#color/white"
app:fabSize="mini"
app:layout_anchor="#id/cardChooseAddressBottomSheet"
app:layout_anchorGravity="top|right"
app:srcCompat="#drawable/ic_origin"
app:tint="#color/colorAccent" />
<include layout="#layout/taxi_fragment_set_destination_top_bar" />
<include layout="#layout/taxi_fragment_bottom_sheet_addresses_layout" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And my fragment
final private BottomSheetBehavior.BottomSheetCallback addressBottomSheetCallBack = new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_HIDDEN:
break;
case BottomSheetBehavior.STATE_SETTLING:
break;
case BottomSheetBehavior.STATE_EXPANDED:
if (!allPermissionsGranted())
requestForLocationPermissions();
topAddressBar.setVisibility(Visibility.VISIBLE);
fabMyLocation.hide();
break;
case BottomSheetBehavior.STATE_COLLAPSED:
if (!allPermissionsGranted())
requestForLocationPermissions();
topAddressBar.setVisibility(Visibility.INVISIBLE);
fabMyLocation.show();
break;
case BottomSheetBehavior.STATE_DRAGGING:
break;
case BottomSheetBehavior.STATE_HALF_EXPANDED:
break;
}
}
BottomSheetBehavior addressBottomSheetBehavior = BottomSheetBehavior.from(cardChooseAddressBottomSheet);
topAddressBar.post(() -> {
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) cardChooseAddressBottomSheet.getLayoutParams();
layoutParams.height = ((Resources.getSystem().getDisplayMetrics().heightPixels + (int) utils.percentageOf(62, btnSearch.getMeasuredHeight())) - topAddressBar.getMeasuredHeight());
});
addressBottomSheetBehavior.setPeekHeight((int) utils.percentageOf(29, Resources.getSystem().getDisplayMetrics().heightPixels), true);
addressBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
topToolBar.setNavigationOnClickListener(view12 -> {
if (addressBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
utopAddressBar.setVisibility(INVISIBLE);
addressBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else
Navigation.findNavController(view12).navigateUp();
});
addressBottomSheetBehavior.addBottomSheetCallback(addressBottomSheetCallBack);
Notice am using INVISIBLE instead of GONE on the topAddressBar? that is because everytime I called GONE the layout would ideally recalculate according to my assumption and the map would flicker, to stop that I had to use invisible as the layout does not shrink instead it still takes up the same space but just not visible.
Also notice I am adding padding cardChooseAddressBottomSheet.getLayoutParams() this is because I need the Sheet not to go too deep underneath the topAddressBar as not to hide my recyclerview content. The current padding makes sure the recyclerview is fully visible and everything else on top of it is underneath the topAddressBar

Categories

Resources