I wanna achieve the following be behavior for one screen of my app.
I have a fragment's layout with ConstraintLayout as it's parent. Inside ConstraintLayout I have a ScrollView with nested ConstraintLayout (nested ConstraintLayout contains ImageView and TextView) and simple Button below the ScrollView.
I wanna enable button as soon as user reaches to the bottom of ScrollView and disable when user scrolls up.
Layout is below.
<?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"
xmlns:tools="http://schemas.android.com/tools"
>
<ScrollView
android:id="#+id/scrollableView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:fillViewport="true"
app:layout_constraintBottom_toTopOf="#id/elevationShadow"
app:layout_constraintTop_toBottomOf="#id/appbar">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_marginStart="#dimen/spacing_large"
android:layout_marginEnd="#dimen/spacing_large"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/user_image"
android:layout_width="144dp"
android:layout_height="144dp"
android:layout_gravity="center"
android:layout_marginTop="#dimen/spacing_large"
android:src="#drawable/user_image"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/heading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/text_size_xxlarge"
android:textStyle="bold"
android:textAlignment="center"
android:textColor="#color/black_color"
android:layout_marginTop="#dimen/spacing_large"
tools:text="Tools text"
android:textAppearance="?tvptTextAppearanceBody"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/user_image"
/>
<TextView
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/spacing_large"
android:textAlignment="center"
android:textSize="#dimen/user_info_content_text_size"
android:textAppearance="?tvptTextAppearanceBody"
android:textColor="#color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/heading"
tools:text="Tools test content"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<View
android:id="#+id/elevationShadow"
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="#drawable/shadow_elevation"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="#dimen/user_info_activity_confirm_button_margin"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="#id/button_confirm"/>
<com.travelportdigital.android.compasswidget.button.PercentageBasedStateButton
android:id="#+id/button_confirm"
style="#style/PrimaryButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:layout_marginBottom="#dimen/user_info_activity_confirm_button_margin"
android:text="#string/user_info_continueButton_title"
android:textAllCaps="true"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
The problem is that content for TextView which is inside ScrollView can both long and short. That's why I had to add ScrollView if the content is long.
By the small piece of code I was able to achieve the behavior I needed with one small remark.
fun addScrollChangeListener() {
scrollView.viewTreeObserver
.addOnScrollChangedListener {
enableContinueButton(scrollView.getChildAt(0).bottom <= scrollView.height + scrollView.scrollY)
}
}
And the code above works fine for the scenario when content is long (when user arrives to this screen Continue button is disabled and when user scrolls to the bottom of the scroll view it become enabled if user scrolls up it becomes disabled again.
I wanna update this logic to enable button when user arrives to this screen and content of TextView inside ScrollView is short (no need scrolling for this scenario).
I made some researches in Google and could not find the solution which would work for me.
In onViewCreated() method I added logic to disable or enable button when user arrives to this screen.
enableContinueButton(!isScrollingRequired())
I tried this implementation
private fun isScrollingRequired(): Boolean {
val view = scrollView.getChildAt(scrollView.childCount - 1) as View
val diff = view.bottom - (scrollView.height + scrollView.scrollY)
return diff != 0
}
and this
return if (child != null) {
val childHeight = child.height
scrollView.height <= childHeight + scrollView.paddingTop + scrollView.paddingBottom;
} else {
false
}
but it did not work, because ScrollView height and it's child height is always 0
Looking forward your advices.
Regards,
Alex
I dont know is this what you want to do but it should be one of the solution.
I think you can just simply add the button in the "ScrollView" so when user scrolls at the bottom, user will see the button and when user scrolls up, user cannot press the button as well.
Below layout .XML works for me, Using ScrollView with ConstraintLayout:
(you may need extra dependencies)
<ScrollView
android:id="#+id/msg_scroll"
android:layout_width="0dp"
android:layout_height="200dp"
android:fillViewport="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/infoSumm">
<!--Display the <ScrollView> under <TextView>"#+id/infoSumm" -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/inside_scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/infoDetail"
android:text=""
android:layout_marginTop="12dp"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxHeight="240dp"
app:layout_constraintTop_toTopOf="#id/inside_scroll"
app:layout_constraintStart_toStartOf="parent"
tools:text="Info Detail"/>
<com.google.android.material.button.MaterialButton
android:id="#+id/btn_infoClose"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/default_field_spacing"
android:backgroundTint="#color/colorPrimary"
android:textAppearance="#style/TextAppearance.MaterialComponents.Button"
android:textAlignment="center"
android:textStyle="bold"
android:textAllCaps="false"
android:textSize="20sp"
android:textColor="#color/colorWhite"
android:text="#string/btn_Close"
android:paddingTop="10dp"
android:paddingBottom="10dp"
app:cornerRadius="25dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/infoDetail"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
Related
I am new to android studio & have encountered an issue. I have a constraint layout which has an image view & a text view. I have attached the screenshot of the constraint layout.
The text view contains the current climate of a location. For eg , when the climate is "rainy" , it shows rainy in the center. The issue I am encountering it that If the climate is "scattered clouds" or " heavy showers" (Basically if the text's length is relatively bigger) , it's no longer centered. It feels like text view in increasing in width from the left side but I want it to increase from the right side with start letter of text to be in the center position always. How do I Implement it
My code for the constraint layout ->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/ivTemp"
android:layout_width="#dimen/_20sdp"
android:layout_height="#dimen/_20sdp"
android:src="#drawable/te"
android:contentDescription="#string/temperature"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="#id/tvClimate"
app:layout_constraintHorizontal_bias=".96"
android:layout_marginTop="#dimen/_11sdp"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="#+id/tvClimate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="#dimen/_10sdp"
android:fontFamily="#font/aldrich"
android:gravity="center"
android:layout_marginEnd="#dimen/_110sdp"
android:paddingBottom="#dimen/_10sdp"
android:textSize="18sp"
tools:text="Scattered Clouds 20°C" />
</androidx.constraintlayout.widget.ConstraintLayout>
I want it to increase from the right side with start letter of text
to be in the center position always
If I understood correctly, you want your view to look somewhat like this:
That can be achieved using vertical guideline in middle of screen:
<?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">
<androidx.constraintlayout.widget.Guideline
android:id="#+id/vertical_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<ImageView
android:id="#+id/iv_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:src="#android:drawable/ic_lock_lock"
app:layout_constraintEnd_toStartOf="#id/vertical_guideline"
app:layout_constraintTop_toTopOf="parent"
app:tint="#android:color/holo_blue_dark" />
<TextView
android:id="#+id/tv_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="my very very very very very very very very very very very very very long text"
android:textAlignment="textStart"
android:textColor="#000"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/vertical_guideline"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Add an empty <View> in the centre and constrain the <TextView> to that <View>
I have a recyclerview which contains many items.
But the first item is like an intro screen, it has a button on which user can tap to view more, or user can scroll to view more data.
Something like following.
I want this button to be at the bottom of screen, in small devices it is not visible unless user scrolls the view. So basically layout is taking more height, so user has to scroll to view the complete layout.
I am using constraint layout, and connect it to the bottom of the view.
There are only 2 items in the view, 1 is imageView, which does not have any image, I have only added background color to it, and other is a TextView.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/Black_Color"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:gravity="center"
android:layout_marginBottom="50dp"
android:textSize="17dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</
in small devices it is not visible unless user scrolls the view - sounds like your image is taking a lot of screen height in small devices so the user must scroll trow the screen
If you want to "disable" the scrolling behavior of your item and put everything inside a screen (without views gong out of the screen and thus making the user scroll) you can change your layout so your item will only occupy the given screen height and not more, and by doing so you will not have this problem on small devices.
something like this:
<?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="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.9"
android:scaleType="fitXY"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="#tools:sample/backgrounds/scenic" />
<TextView
android:id="#+id/textView"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="TextView"
android:textSize="17sp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
The trick was to simply give the image height in percentage like this
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.9"
And now your image will take 90% height on every screen size.
I am currently using a scroll view inside an Alert Dialog and need the scroll view to grow in height until the dialog reaches its maximum default height. It's a bit tough for me to explain so i have attached an illustration to help. Hope it does.
The issue i'm getting is the scrollview does not grow in height and even if i remove the app:layout_constraintBottom_toTopOf="#id/linearLayout4", it grows however the bottom part will be partially hidden by the button layout. This is my current code :
<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:id="#+id/filter_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/dialog_box"
android:minHeight="300dp"
android:elevation="12dp">
<TextView
android:id="#+id/filter_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="#string/filter"
style="#style/element_header"
android:textColor="#color/textColorDark"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/filter_reset_btn"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:text="#string/reset"
style="#style/text_info_nBold"
android:textSize="14sp"
android:textColor="#color/textColorDark"
app:layout_constraintBottom_toBottomOf="#+id/filter_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/filter_header" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="#id/linearLayout4"
app:layout_constraintTop_toBottomOf="#id/filter_header"
app:layout_constraintVertical_bias="0.0">
<androidx.core.widget.NestedScrollView
android:id="#+id/filter_scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:layout_marginTop="16dp"
android:scrollbarFadeDuration="1000">
<!-- VIEWS INSIDE HERE -->
</androidx.core.widget.NestedScrollView>
</LinearLayout>
<LinearLayout
android:id="#+id/linearLayout4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/dialog_bottombar_layout"
android:orientation="horizontal"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="#+id/dialog_secondary_button"
style="#style/low_emphasis_btn"
android:layout_width="0dp"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:backgroundTint="#color/textColorDark"
android:text="#string/dialog_cancel"
android:textColor="#color/textColorDark"
android:visibility="visible" />
<Button
android:id="#+id/dialog_primary_button"
style="#style/high_emphasis_btn"
android:layout_width="0dp"
android:layout_weight="1"
android:text="#string/apply" />
</LinearLayout>
Any help would be appreciated :)
Alert dialogs tend to wrap their content or can be forced to be full screen. A size in between the optimizes the screen real estate takes a some work, but it is not impossible.
One approach is to let the system lay out the alert dialog but, before it is displayed, use a ViewTreeObserver.OnGlobalLayoutListener to examine the resulting size of the dialog. In the layout listener, the size of the dialog can be adjusted up to fit the contents of the scrolling view or adjusted up to full screen if the scrolling view contents are too large for the screen.
Here is a demo app that shows how this can be done. Comments in the code explain more.
MainActivity.kt
class MainActivity : AppCompatActivity(), View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onClick(v: View) {
val text = when (v.id) {
R.id.customDialogShort -> getString(R.string.short_string)
R.id.customDialogMedium -> getString(R.string.lorem_medium)
else -> getString(R.string.lorem_long)
}
// Specifying the viewGroup as a parent to the inflater makes no difference.
val dialogView = LayoutInflater.from(v.context).inflate(R.layout.con_custom_view, null, false) as ConstraintLayout
(dialogView.findViewById(R.id.textView) as TextView).text = text
val alertDialog = AlertDialog.Builder(this).setView(dialogView).create()
val decorView = alertDialog.window!!.decorView
decorView.setBackgroundResource(R.drawable.alert_dialog_background)
// We need a layout pass to determine how big everything is and needs to be. Place a hook
// at the end of the layout process to examine the layout before display.
decorView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
decorView.viewTreeObserver.removeOnGlobalLayoutListener(this)
// Find out how much of the scrolling view is usable by its child.
val scrollingView: NestedScrollView = decorView.findViewById(R.id.filter_scroll)
val scrollingViewPadding = scrollingView.paddingTop + scrollingView.paddingBottom
val scrollingUsableHeight = scrollingView.height - scrollingViewPadding
// If the child view fits in the scrolling view, then we are done.
val childView = scrollingView.getChildAt(0)
if (childView.height <= scrollingUsableHeight) {
return
}
// Child doesn't currently fit in the scrolling view. Resize the top-level
// view so the child either fits or is forced to scroll because the maximum
// height is reached. First, find out how much space is allowed by the decor view.
val displayRectangle = Rect()
decorView.getWindowVisibleDisplayFrame(displayRectangle)
val decorViewPadding = decorView.paddingTop + decorView.paddingBottom
val decorUsableHeight = displayRectangle.height() - decorViewPadding - scrollingViewPadding
// Compute the height of the dialog that will 100% fit the scrolling content and
// reduce it if it won't fit in the maximum allowed space.
val heightToFit = dialogView.height + childView.height - scrollingUsableHeight
dialogView.minHeight = min(decorUsableHeight, heightToFit)
}
})
var buttonOk: Button = dialogView.findViewById(R.id.dialog_primary_button)
buttonOk.setOnClickListener { alertDialog.dismiss() }
buttonOk = dialogView.findViewById(R.id.dialog_secondary_button)
buttonOk.setOnClickListener { alertDialog.dismiss() }
alertDialog.show()
}
}
activity_main.xml
<LinearLayout
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="#+id/customDialogShort"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Short text" />
<Button
android:id="#+id/customDialogMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Medium text" />
<Button
android:id="#+id/customDialogLong"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Long text" />
</LinearLayout>
con_custom_view
Custom Layout for the AlertDialog.
<TextView
android:id="#+id/filter_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="#string/filter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/filter_reset_btn"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:text="#string/reset"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="#+id/filter_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/filter_header" />
<androidx.core.widget.NestedScrollView
android:id="#+id/filter_scroll"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:padding="16dp"
android:scrollbarFadeDuration="1000"
app:layout_constraintBottom_toTopOf="#id/linearLayout4"
app:layout_constraintTop_toBottomOf="#id/filter_header">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="#string/lorem_long" />
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:id="#+id/linearLayout4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="#+id/dialog_secondary_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:text="#string/dialog_cancel"
android:visibility="visible" />
<Button
android:id="#+id/dialog_primary_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/apply" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I have an arbitrary length textview+icon (icon+text) that needs centering on the screen. On the same row, there is a button aligned to the right side of the screen. (X)
| icon+text | X |
Using a LinearLayout I can center it with the view, but the button on the right shifts it left.
With a relative layout, I can achieve what I want but if the text is too long the button overlaps the text.
What's the right way to do this? I haven't used constraintLayout before, would that solve it?
I suggest you to use a constraint layout,
Example:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".YourActivity">
<TextView
android:id="#+id/my_text_view"
android:text="My Long Text That must not overlap the button"
android:layout_width="0dp"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/my_btn"
app:layout_constraintTop_toTopOf="#+id/my_btn"
app:layout_constraintBottom_toBottomOf="#+id/my_btn"/>
<Button
android:id="#+id/my_btn"
android:layout_marginTop="16dp"
android:text="My Nice Button "
android:layout_marginEnd="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#id/my_text_view"
app:layout_constraintEnd_toEndOf="parent"/>
</android.support.constraint.ConstraintLayout>
Example Output:
You can set it like this,
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:drawableLeft="#mipmap/ic_launcher"
android:text="Click" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="TextView" />
</LinearLayout>
just use a Relative Layout.
Center your Textview
and put toRightOf=txtViewsName on the button.
//UPDATED Forcing Widths in DP to ensure text is always centered and never overlaps button.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="#mipmap/ic_launcher"
android:maxWidth="230dp"
android:layout_centerHorizontal="true"
android:ellipsize="end"
android:text="My text to show test abcdefghyijkldkf here" />
<Button
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Button" />
</RelativeLayout>
You will need to adjust the button width and textview maxwidth to match your design, and confirm on preview all resolutions, but dp should cover you pretty well in this case.
NOTE*
This simply answers your issue, but does not do any funny behavior, i.e. if text grows too much ignore center command and start moving to the left, this does not do that. If that is your desire, please update your question.
//Centering Text in left view and using weight to ensure text area takes proper percentage of the space (based on your comments, not the layout you are looking for, but I'll leave it in case it helps someone else).
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="10">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="7"
android:drawableLeft="#mipmap/ic_launcher"
android:gravity="center"
android:text="My text to show here" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:text="Button" />
</LinearLayout>
for best practice i think ConstraintLayout is the best solution for designing and yes of course it helps you for what are you looking for.
for more info check this Build a Responsive UI with ConstraintLayout and this
ConstraintLayout.
Since your ImageButton on right has a fixed width (let's say 40dp for the purpose of this example) you can achieve the desired result by adding a margin of the same width at the end of your TextView to ensure that they're not overlapping. To keep the TextView centered on the screen you have to add the same margin at the start as well:
<android.support.constraint.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="wrap_content">
<TextView
android:id="#+id/textview"
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="#+id/button"
android:layout_width="40dp"
android:layout_height="40dp"
app:layout_constrainedWidth="true"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/textview"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
If you want to center the text within the TextView use android:gravity="center":
If the ImageButton's width was wrap_content then this approach wouldn't work, because there is no way to constraint the end of the TextView both to the end of the parent (so it's centered on the screen) and to the start of the ImageButton (so they don't overlap if the text gets long) at the same time.
In the end I ended up using RelativeLayout per Sam's suggestion with maxWidth and margin set on the TextView.
<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="match_parent"
tools:context="com.partyspottr.appdir.ui.mainfragments.eventchildfragments.alle_eventer_fragment">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_layout_events"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="#dimen/_8sdp"
android:layout_marginStart="#dimen/_8sdp"
android:layout_marginTop="#dimen/_5sdp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/search_alle_eventer"
app:layout_constraintVertical_bias="0.0">
<ListView
android:id="#+id/lvalle_eventer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#color/transparent"
android:dividerHeight="#dimen/_20sdp"
android:scrollbarSize="#dimen/_3sdp"
android:scrollbarThumbVertical="#color/lightred"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.v4.widget.SwipeRefreshLayout>
<EditText
android:id="#+id/search_alle_eventer"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="#dimen/_8sdp"
android:layout_marginStart="#dimen/_8sdp"
android:layout_marginTop="#dimen/_90sdp"
android:background="#drawable/border_rounded"
android:hint="Search.."
android:inputType="text"
android:paddingEnd="#dimen/_10sdp"
android:paddingStart="#dimen/_10sdp"
android:textColor="#android:color/black"
android:textSize="#dimen/_15ssp"
app:layout_constraintEnd_toEndOf="#+id/swipe_layout_events"
app:layout_constraintStart_toStartOf="#+id/swipe_layout_events"
app:layout_constraintTop_toTopOf="parent" />
This is my layout XML, containing a parent (ConstraintLayout), a SwipeRefreshLayout with a ListView as child, and an EditText which i use to search items inside the ListView.
This layout is used as a fragment, so i have a button outside of this layout, when i press this button, the EditText either shows or doesn't, i do this with this code:
search_alle_eventer.setVisibility(search_alle_eventer.getVisibility() == View.VISIBLE ? View.INVISIBLE : View.VISIBLE);
ViewGroup.LayoutParams params = search_alle_eventer.getLayoutParams();
if(search_alle_eventer.getVisibility() == View.INVISIBLE)
params.height = 0;
else {
params.height = WRAP_CONTENT;
search_alle_eventer.setLayoutParams(params);
Now, the problem im having is when the EditText is showing (WRAP_CONTENT), when i scroll to the bottom of the ListView, the last item is cut off. How can i fix this?
you can set margin from bottom to ListView. android:marginBottom = "50dp"
Or try with relative layout like this
< RelativeLayout
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"
tools:context="com.partyspottr.appdir.ui.mainfragments.eventchildfragments.alle_eventer_fragment">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_layout_events"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="#dimen/_8sdp"
android:layout_marginStart="#dimen/_8sdp"
android:layout_marginTop="#dimen/_5sdp"
>
<ListView
android:id="#+id/lvalle_eventer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#color/transparent"
android:dividerHeight="#dimen/_20sdp"
android:scrollbarSize="#dimen/_3sdp"
android:scrollbarThumbVertical="#color/lightred"
/>
</android.support.v4.widget.SwipeRefreshLayout>
<EditText
android:id="#+id/search_alle_eventer"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="#dimen/_8sdp"
android:layout_marginStart="#dimen/_8sdp"
android:layout_marginTop="#dimen/_90sdp"
android:background="#drawable/border_rounded"
android:hint="Search.."
android:inputType="text"
android:paddingEnd="#dimen/_10sdp"
android:paddingStart="#dimen/_10sdp"
android:textColor="#android:color/black"
android:textSize="#dimen/_15ssp"
/>
</RelativeLayout>
Alright, thanks for you help, but my case is a special needs case, whatever im doing, im sure is not the correct way, but i'll let it be.
Fixed it by adding some more code inside the OnClickListener of the button i mentioned:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if(search_alle_eventer.getVisibility() == View.INVISIBLE)
listView.setPadding(0, 0, 0, 0);
else
listView.setPadding(0, 0, 0, search_alle_eventer.getHeight());
}
}, 100);
Adding some padding on the ListView whenever the EditText is visible did the trick for me.
EDIT: Thank you Mark Keen for pointing out the container for the fragments, I was being retarded not thinking straight. I fixed it by resizing the container.
Tbh, sorry for this question.