how do I change the android:layout_marginTop of a button? - android-layout

I need to change the property android:layout_marginTop of a button programmatically. But the code below does not produce the same result as changing on the xml. I wonder if anyone can spot the issue, here's my button:
<Button
android:id="#+id/cta_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="0dp"
android:background="#color/cta_button_background"
android:text="CTA"
android:textColor="#color/cta_button_foreground"
android:textSize="18sp"
android:visibility="visible" />
now I need to change the "marginTop" programmatically based on some logic. Here is what I have tired but does not work properly.
// Adjust button to float above the image
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
int marginTop = Pixel.convertPxToDp(someNumber);
params.setMargins(0, marginTop, 0, 0);
mCallToActionButton.setLayoutParams(params);
mCallToActionButton.invalidate();
"mCallToActionButton" has a valid pointer to the button and 'someNumber' can be anything value.
I used this thread but the button is moving somewhere else, not just changing its topMargin
How to set a button's parameters programatically
thank you.

This way works:
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mCallToActionButton.getLayoutParams();
params.topMargin = Pixel.convertDpToPx(newImageMargin);
mCallToActionButton.setLayoutParams(params);

Try to set gravity to your LayoutParams
params.gravity = Gravity.CENTER_HORIZONTAL;

Related

Why doesn't textView21.SetLeftTopRightBottom(1,200,45, 275) change the size of a textview?

Why doesn't textView21.SetLeftTopRightBottom(1,200,45, 275) change the size of a textview?
<TextView
android:id="#+id/textView21_id"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_x="22dp"
android:layout_y="105dp"
android:height="50dp"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text=""
android:textSize="30sp"
android:textColor="#000000"
android:background="#9999cc"
android:singleLine="false"/>
There's the activity_main.xml snippet. Is there something there which overrides the SetLeftTopRightBottom?
I am still trying to get two different but ordinary mobile phones (cell phones) to display a view the same.
pic of same app in two phones
You can see the left hand pic shows to below the grey '6:' textview and includes the 'Go' textview and all the right hand 5th-letter-in-the-word textview areas whereas the other pic doesn't.
I've figured out how to get each phone's display metrics
var metrics = Resources.DisplayMetrics;
gnumWidthDp = ConvertPixelsToDp(metrics.WidthPixels);
gnumHeightDp = ConvertPixelsToDp(metrics.HeightPixels);
I thought it would be easy to do the SetLeftTopRightBottom thing and set each textview in the right place.
Please can you tell me what I have missed? Thank you all.
In the official document, SetLeftTopRightBottom method is meant to be used in animations only as it applies this position and size for the view only temporary and it can be changed back at any time by the layout.
More information: https://developer.android.com/reference/android/view/View#setLeftTopRightBottom(int,%20int,%20int,%20int)
In addition, the size of the textview21 had been ensured in the xml. If you want to set the size of it dynamically, you need to use the LayoutParams. Such as:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(300, 200);
//300 is width and 200 is height
textView.LayoutParameters = layoutParams;

Handling GONE views puzzle in ConstraintLayout

I have a simple enough looking layout with what turns out to be quite a tricky behaviour to accomplish using xml alone i.e. using only the features of ConstraintLayout and not having to do anything programmatically.
I have considered Barriers & Guidlines and many scenarios and trials with no success; so this is my last hope that maybe someone else knows something I don't.
Here is my puzzle:
If 3 lines visible -> image should be centred between line 1 and line
2
If 2 lines visible -> image should be centred between line 1 and
line 2
If 1 line visible (label_text) -> image should be centred in parent, or
centre aligned with line 1 (label_text)
Here are some images to illustrate:
3 Lines - correct
2 Lines - correct
1 Line incorrect but best I can get so far [when only Label is visible]
1 Line correct the way I want it to be [when only Label is visible]
Code:
<androidx.constraintlayout.widget.ConstraintLayout
style="#style/V2.ItemList.Background"
android:minHeight="#dimen/item_minimum_height"
android:paddingVertical="#dimen/=margin_vertical">
<ImageView
android:id="#+id/icon"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
tools:src="#drawable/ic_img"
tools:visibility="visible" />
<TextView
android:id="#+id/label_text"
app:layout_constraintBottom_toTopOf="#id/line1_text"
app:layout_constraintEnd_toStartOf="#id/right_content"
app:layout_constraintStart_toEndOf="#id/icon_start"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Label" />
<TextView
android:id="#+id/line1_text"
android:layout_marginTop="4dp"
app:layout_constraintBottom_toTopOf="#id/line2_text"
app:layout_constraintEnd_toStartOf="#id/right_content"
app:layout_constraintStart_toEndOf="#id/icon"
app:layout_constraintTop_toBottomOf="#id/label_text"
tools:text="Line 1"
tools:visibility="gone" />
<TextView
android:id="#+id/line2_text"
android:layout_marginTop="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/right_content"
app:layout_constraintStart_toEndOf="#id/icon"
app:layout_constraintTop_toBottomOf="#id/line1_text"
tools:text="Line 2"
tools:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
Any help is much appreciated!
UPDATE
See Cheticamp's answer below which is best solution but in case it's useful for anyone else here's the way I was going to do it programmatically if I couldn't find an xml only solution:
private fun adjustConstraints() {
if(binding.line1Text.isGone && binding.line1Text.isGone) {
ConstraintSet().apply {
clone(binding.itemListLayout)
// Adjust left/start content for single line
connect(
R.id.icon,
ConstraintSet.TOP,
R.id.item_list_layout,
ConstraintSet.TOP
)
connect(
R.id.icon,
ConstraintSet.BOTTOM,
R.id.item_list_layout,
ConstraintSet.BOTTOM
)
// Adjust right/end content for single line
connect(
R.id.right_content,
ConstraintSet.TOP,
R.id.item_list_layout,
ConstraintSet.TOP
)
connect(
R.id.right_content,
ConstraintSet.BOTTOM,
R.id.item_list_layout,
ConstraintSet.BOTTOM
)
}.also {
it.applyTo(binding.itemListLayout)
}
}
}
Constrain the ImageView to the top of label_text and to the bottom of line_1_text.
<ImageView
android:id="#+id/icon"
app:layout_constraintTop_toTopOf="#id/label_text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="#id/line1_text"
tools:src="#drawable/ic_img"
tools:visibility="visible" />

What is equivalent of "toStartOf" and "toTopOf" in ConstraintSet?

How is it possible to set correctly layout_constraintStart_toStartOf and layout_constraintTop_toTopOf programmaticly?
<ImageView
android:id="#+id/firstButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/alarm"
app:layout_constraintStart_toStartOf="#+id/guideline4"
app:layout_constraintTop_toTopOf="#+id/guideline" />
So far, I can't find toStartOf and toTopOf properties of ConstraintSet, what is the equivalent of it?
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(main_layout);
constraintSet.connect(R.id.firstButton, ConstraintSet.START, R.id.guideline4, ConstraintSet.END);
constraintSet.connect(R.id.firstButton, ConstraintSet.TOP, R.id.guideline, ConstraintSet.BOTTOM);
constraintSet.applyTo(main_layout);
I guess that if you want start to start and top to top, it is more like
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(main_layout);
constraintSet
.connect(R.id.firstButton, ConstraintSet.START, R.id.guideline4, ConstraintSet.START);
constraintSet
.connect(R.id.firstButton, ConstraintSet.TOP, R.id.guideline, ConstraintSet.TOP);
constraintSet.applyTo(main_layout);
?

Android TextView Programmatically following XML

I currently have this xml:
<TextView android:id="#+id/dummy"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="#string/test"
android:textStyle="bold" />
And im trying to convert it to a java version so that I can set a typeface:
setContentView(R.layout.activity_main);
// the get the activity_main layout (getContentView method does not exist?)
FrameLayout layout = (FrameLayout) findViewById(android.R.id.content);
final TextView textView = new TextView(context);
textView.setId(R.id.dummy);
FrameLayout.LayoutParams contentLayout = new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
contentLayout.gravity = Gravity.CENTER;
textView.setText(R.string.test);
Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/arial.ttf");
textView.setTypeface(tf);
layout.addView(textView, contentLayout);
The problem I'm having is that either does not gravity work or match_parent. The texts ends up in the upper right corner and not in the center as it does on the xml version.
In the XML you're setting the gravity of the text inside the TextView. In the code you are setting the TextView's layout gravity.
To replicate what you've done in the XML, change the line:
contentLayout.gravity = Gravity.CENTER;
to:
textView.setGravity(Gravity.CENTER);
If your XML had android:layout_gravity="center" instead of android:gravity="center" then your code would match as it is.

TextView gravity="top" but changing font size dynamically doesn't keep text align to the top

I have an app that needs to dynamically align text views over certain locations on an image. The image is scaled to fit the view. Text entries are added by the user. I'm using a RelativeLayout and margins to properly position the text. All is good.
When the user rotates the screen, I save the text locations and bitmap using onRetainNonConfigurationInstance(). When the view is recreated, I add the views back into the RelativeLayout. Now, because the view is a different size, the scale of the image is different. To keep the text boxes in the same location, I have to account for that. I have all that code working except for one issue....
If I create a TextView and set the fontSize to a small size (e.g. <11px), the top of the text box is positioned where I want it to be but the text is aligned with a baseline as if it were 11px font. I don't know the scale factor in the onCreate method so I can't change the font size until after onMeasure and onLayout are called. I've tried forceLayout() and requestLayout() but nothing seems to fix the alignment problem.
Here is the layout:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="0dp"
>
<com.xyx.ScalableLayout
android:id="#+id/layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="0dp"
android:clickable="true"
android:gravity="top"
>
<com.xyx.ScaledImageView
android:id="#+id/formView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="0dp"
/>
<com.xyx.ScalableLayout>
</ScrollView>
A textView is added with the following code:
textView = new TextView(getContext());
textView.setPadding(0, 0, 0, 0);
textView.setSingleLine();
textView.setFocusableInTouchMode(false);
textView.setClickable(false);
textView.setGravity(Gravity.TOP);
textView.setText(entry.mText);
float fontSize = mImageView.mapSizeToView(entry.mPointSize);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PT, fontSize);
params = new RelativeLayout.LayoutParams(
ViewGroup.MarginLayoutParams.WRAP_CONTENT,
ViewGroup.MarginLayoutParams.WRAP_CONTENT);
params.leftMargin = Math.round(viewLoc.x);
params.topMargin = Math.round(viewLoc.y);
addView(textView, params);
When ScaledImageView gets an onSizeChanged() callback, it sets the scale value and updates the font size and location of TextViews with the following code:
float fontSize = mImageView.mapSizeToView(entry.mPointSize);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PT, fontSize);
PointF viewLoc = computeTopLeft(entry, entry.mTextView.getPaint());
params = (RelativeLayout.LayoutParams) textView.getLayoutParams();
params.leftMargin = Math.round(viewLoc.x);
params.topMargin = Math.round(viewLoc.y);
textView.setLayoutParams(params);
textView.forceLayout();
And finally, I do a
requestLayout() on the ScalableLayout
I know that's a lot of code but my problem is this. If I know the proper scale factor (used in mapSizeToView()) when I am creating the TextView and adding it to the screen everything works fine. If the value is incorrect, then nothing I can find will do a full recalculate that will get the TextView to be the same as if it were created with that font size. I believe it is tied to Android Layout structure which I generally understand. However, I don't understand why I can't get it to recompute from scratch (short of tearing down all the views and recreating them).

Resources