Change the Right Margin of a View Programmatically?
Can this attribute be changed dyna开发者_高级运维mically in Java code?
android:layout_marginRight
I have a TextView
, that has to change its position some pixels to the left dynamically.
How to do it programmatically?
EDIT: A more generic way of doing this that doesn't rely on the layout type (other than that it is a layout type which supports margins):
public static void setMargins (View v, int l, int t, int r, int b) {
if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
p.setMargins(l, t, r, b);
v.requestLayout();
}
}
You should check the docs for TextView. Basically, you'll want to get the TextView's LayoutParams object, and modify the margins, then set it back to the TextView. Assuming it's in a LinearLayout, try something like this:
TextView tv = (TextView)findViewById(R.id.my_text_view);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)tv.getLayoutParams();
params.setMargins(0, 0, 10, 0); //substitute parameters for left, top, right, bottom
tv.setLayoutParams(params);
I can't test it right now, so my casting may be off by a bit, but the LayoutParams are what need to be modified to change the margin.
NOTE
Don't forget that if your TextView is inside, for example, a RelativeLayout, one should use RelativeLayout.LayoutParams instead of LinearLayout.LayoutParams
Update: Android KTX
The Core KTX module provides extensions for common libraries that are part of the Android framework, androidx.core.view
among them.
dependencies {
implementation "androidx.core:core-ktx:{latest-version}"
}
The following extension functions are handy to deal with margins:
Note: they are all extension functions of
MarginLayoutParams
, so first you need to get and cast thelayoutParams
of your view:val params = (myView.layoutParams as ViewGroup.MarginLayoutParams)
setMargins()
extension function:
Sets the margins of all axes in the ViewGroup
's MarginLayoutParams
. (The dimension has to be provided in pixels, see the last section if you want to work with dp)
inline fun MarginLayoutParams.setMargins(@Px size: Int): Unit
// E.g. 16px margins
params.setMargins(16)
updateMargins()
extension function:
Updates the margins in the ViewGroup
's ViewGroup.MarginLayoutParams
.
inline fun MarginLayoutParams.updateMargins(
@Px left: Int = leftMargin,
@Px top: Int = topMargin,
@Px right: Int = rightMargin,
@Px bottom: Int = bottomMargin
): Unit
// Example: 8px left margin
params.updateMargins(left = 8)
updateMarginsRelative()
extension function:
Updates the relative margins in the ViewGroup
's MarginLayoutParams
(start/end instead of left/right).
inline fun MarginLayoutParams.updateMarginsRelative(
@Px start: Int = marginStart,
@Px top: Int = topMargin,
@Px end: Int = marginEnd,
@Px bottom: Int = bottomMargin
): Unit
// E.g: 8px start margin
params.updateMargins(start = 8)
The following extension properties are handy to get the current margins:
inline val View.marginBottom: Int
inline val View.marginEnd: Int
inline val View.marginLeft: Int
inline val View.marginRight: Int
inline val View.marginStart: Int
inline val View.marginTop: Int
// E.g: get margin bottom
val bottomPx = myView1.marginBottom
- Using
dp
instead ofpx
:
If you want to work with dp
(density-independent pixels) instead of px
, you will need to convert them first. You can easily do that with the following extension property:
val Int.px: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
Then you can call the previous extension functions like:
params.updateMargins(start = 16.px, end = 16.px, top = 8.px, bottom = 8.px)
val bottomDp = myView1.marginBottom.dp
Old answer:
In Kotlin you can declare an extension function like:
fun View.setMargins(
leftMarginDp: Int? = null,
topMarginDp: Int? = null,
rightMarginDp: Int? = null,
bottomMarginDp: Int? = null
) {
if (layoutParams is ViewGroup.MarginLayoutParams) {
val params = layoutParams as ViewGroup.MarginLayoutParams
leftMarginDp?.run { params.leftMargin = this.dpToPx(context) }
topMarginDp?.run { params.topMargin = this.dpToPx(context) }
rightMarginDp?.run { params.rightMargin = this.dpToPx(context) }
bottomMarginDp?.run { params.bottomMargin = this.dpToPx(context) }
requestLayout()
}
}
fun Int.dpToPx(context: Context): Int {
val metrics = context.resources.displayMetrics
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), metrics).toInt()
}
Then you can call it like:
myView1.setMargins(8, 16, 34, 42)
Or:
myView2.setMargins(topMarginDp = 8)
Use LayoutParams (as explained already). However be careful which LayoutParams to choose. According to https://stackoverflow.com/a/11971553/3184778 "you need to use the one that relates to the PARENT of the view you're working on, not the actual view"
If for example the TextView is inside a TableRow, then you need to use TableRow.LayoutParams instead of RelativeLayout or LinearLayout
Use This function to set all Type of margins
public void setViewMargins(Context con, ViewGroup.LayoutParams params,
int left, int top , int right, int bottom, View view) {
final float scale = con.getResources().getDisplayMetrics().density;
// convert the DP into pixel
int pixel_left = (int) (left * scale + 0.5f);
int pixel_top = (int) (top * scale + 0.5f);
int pixel_right = (int) (right * scale + 0.5f);
int pixel_bottom = (int) (bottom * scale + 0.5f);
ViewGroup.MarginLayoutParams s = (ViewGroup.MarginLayoutParams) params;
s.setMargins(pixel_left, pixel_top, pixel_right, pixel_bottom);
view.setLayoutParams(params);
}
精彩评论