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())
}
Related
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.
I want to have a horizontal alignment of four buttons with these conditions:
their texts are 25%, 50%, 75%, 100% (so the last one will be wider)
they should have same width
they should spread the through the remaining space
Is it possible to achieve this using ConstraintLayout?
To demonstrate what I exactly want, take a look at current state of my layout (which is ok):
The buttons currently are set to have a width of 25 percent of the parent and there's a static margin between them (implemented using a LinearLayout). What is the problem? It's possible in small screens that the margin cause the last button to be truncated (like the image below), or in large screens the buttons be so large.
So I want the spread behavior of ConstraintLayout besides width of the last button be wrap_content and width of other buttons be set equal to the last button.
Thanks to #cheticamp and his answer provided here, the best way of achieving the desired behavior would be writing a simple ConstraintHelper which sets width of all the children to the maximum among them.
class MaxWidthConstraint #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintHelper(context, attrs, defStyleAttr) {
override fun updatePostMeasure(container: ConstraintLayout) {
val maxWidth =
referencedIds.asSequence().map { container.getViewById(it) }
.map { container.getViewWidget(it) }
.map { it.width }
.max() ?: 0
referencedIds.asSequence().map { container.getViewById(it) }
.map { container.getViewWidget(it) }
.forEach { it.width = maxWidth }
}
}
So the layout code would be:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="HardcodedText">
<Button
android:id="#+id/btn_25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25%"
android:textAlignment="center"
app:layout_constraintEnd_toStartOf="#id/btn_50"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btn_50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="50%"
app:layout_constraintEnd_toStartOf="#id/btn_75"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="#id/btn_25"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btn_75"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="75%"
app:layout_constraintEnd_toStartOf="#id/btn_100"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="#id/btn_50"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btn_100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="100%"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="#id/btn_75"
app:layout_constraintTop_toTopOf="parent" />
<com.myapplication.widgets.MaxWidthConstraint
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="btn_25,btn_50,btn_75,btn_100"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
So this is what i came up with:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/tv_25"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:text="25%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/tv_50"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/tv_50"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:text="50%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toRightOf="#id/tv_25"
app:layout_constraintRight_toLeftOf="#id/tv_75"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/tv_75"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:text="75%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toRightOf="#id/tv_50"
app:layout_constraintRight_toLeftOf="#id/tv_100"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/tv_100"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:text="100%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toRightOf="#id/tv_75"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Explanation: I've used app:layout_constraintHorizontal_chainStyle="spread".Using chain takes the margin into account while spreading the views evenly.
Using chain style spread might be you got your expected layout.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/btn_25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/entercode_default"
android:text="25%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btn_50"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btn_50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/entercode_default"
android:text="50%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btn_75"
app:layout_constraintStart_toEndOf="#+id/btn_25"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btn_75"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/entercode_default"
android:text="75%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btn_100"
app:layout_constraintStart_toEndOf="#+id/btn_50"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btn_100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/entercode_default"
android:text="100%"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/btn_75"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
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
}
I have a simple DialogFragment which contains 3 EditTexts and a Button. I have set the layout_width of its main layout 350dp but when I run the project it will be shown so slim.
This My DialogFragment XML:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="350dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:animateLayoutChanges="true"
android:background="#AFE6FF"
android:orientation="vertical"
android:padding="24dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.constraint.ConstraintLayout
android:id="#+id/layout_mobile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<EditText
android:id="#+id/et_mobile"
android:layout_width="match_parent"
android:layout_height="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout
android:id="#+id/layout_title"
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">
<EditText
android:id="#+id/et_title"
android:layout_width="match_parent"
android:layout_height="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout
android:id="#+id/layout_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/layout_title">
<EditText
android:id="#+id/et_body"
android:layout_width="match_parent"
android:layout_height="150dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
<Button
android:id="#+id/btn_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/layout_body" />
</LinearLayout>
</ScrollView>
and it will be shown by this code:
MyDialogFragment.newInstance().show(getSupportFragmentManager(), "my_dialog_fragment");
I need it to be shown Wider.
You need to change the LayoutParams of your dialog like the below code. put it in onResume():
Window window = yourDialog.getWindow();
if (window != null) {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(window.getAttributes());
//This makes the dialog take up the full width
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.MATCH_PARENT;
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setAttributes(lp);
}
I think that the default dialog's LayoutParams ( wrap_content,wrap_content ) overriding your definition from XML.
It's better to use it this way and not use a fixed size values (350dp) to keep your layout responsive to all screen sizes.
You want to override onCreateDialog and add your custom layout there instead. Like below. I use ViewBinding to create my views.
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return AlertDialog.Builder(requireContext())
.setView(binding.root)
.setCancelable(false)
.create().apply {
setCanceledOnTouchOutside(false)
}
}
Here is my Code that is used in RecyleViewAdapater!
val yearOfMemory = SimpleDateFormat("yyyy").format(memory.timeOfMemory)
// if year not show before, show it.
if (!yearSet.contains(yearOfMemory)) {
holder.yearOfMemories.visibility = View.VISIBLE
holder.yearOfMemories.text = yearOfMemory
yearSet.add(yearOfMemory)
}
Here is my ReccleView XML.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
tools:layout_editor_absoluteY="81dp">
<TextView
android:id="#+id/month_and_day_of_memory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/content_of_memory"
app:layout_constraintHorizontal_bias="0.8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/content_of_memory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.6"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/year_of_group_memory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:textSize="36sp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="#+id/month_and_day_of_memory"
app:layout_constraintEnd_toStartOf="#+id/month_and_day_of_memory"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Like this, I already have set TextView(#+id/year_of_group_memory) Gone, but it still takes up space at the second item,and it don't take up at the third item.
I have tried all kinds. So, how can I fix it.?
I turn on the layout bounds.
So,how can cut off the below height,now?
Is your code in a RecyclerView adapter? If so, you must explicitly hide it due to the view recycling mechanism. Always have explicit if-else statements when hiding/showing views.
val yearOfMemory = SimpleDateFormat("yyyy").format(memory.timeOfMemory)
if (!yearSet.contains(yearOfMemory)) {
holder.yearOfMemories.visibility = View.VISIBLE
holder.yearOfMemories.text = yearOfMemory
yearSet.add(yearOfMemory)
} else {
holder.yearOfMemories.visibility = View.GONE
}
Also try replacing your viewholder contents with the following xml:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/year_of_group_memory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textSize="36sp"
android:lines="2"
tools:text="2017"
/>
<TextView
android:id="#+id/month_and_day_of_memory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/year_of_group_memory"
android:layout_alignBottom="#id/year_of_group_memory"
android:layout_margin="8dp"
android:textSize="18sp"
tools:text="03-11"
/>
<TextView
android:id="#+id/content_of_memory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/month_and_day_of_memory"
android:layout_alignTop="#id/month_and_day_of_memory"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:textSize="18sp"
tools:text="第一次接吻"
/>
</RelativeLayout>
If you use this, you have to set the height of yearOfMemories to 0 or wrap_content accordingly.
Try this:
<TextView
android:id="#+id/year_of_group_memory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
you hide this TextView but youre putting android:textSize="36sp" that it shouldn't have and other margins and app:layout_constraintBottom_toTopOf=