Czy ten atrybut można zmieniać dynamicznie w kodzie Java?
android:layout_marginRight
Mam element TextView
, który musi dynamicznie zmieniać swoje położenie o kilka pikseli w lewo.
Jak to zrobić programowo?
Czy ten atrybut można zmieniać dynamicznie w kodzie Java?
android:layout_marginRight
Mam element TextView
, który musi dynamicznie zmieniać swoje położenie o kilka pikseli w lewo.
Jak to zrobić programowo?
Odpowiedzi:
EDYCJA: Bardziej ogólny sposób, który nie zależy od typu układu (poza tym, że jest to typ układu, który obsługuje marginesy):
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();
}
}
Powinieneś sprawdzić dokumenty pod kątem TextView . Zasadniczo będziesz chciał pobrać obiekt LayoutParams TextView i zmodyfikować marginesy, a następnie ustawić go z powrotem na TextView. Zakładając, że jest w LinearLayout, spróbuj czegoś takiego:
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);
Nie mogę tego teraz przetestować, więc rzutowanie może być trochę wyłączone, ale LayoutParams są tym, co należy zmodyfikować, aby zmienić margines.
Nie zapominaj, że jeśli twój TextView znajduje się wewnątrz, na przykład RelativeLayout , należy użyć RelativeLayout.LayoutParams zamiast LinearLayout.LayoutParams
Użyj LayoutParams (jak już wyjaśniono). Uważaj jednak, które LayoutParams wybrać. Według https://stackoverflow.com/a/11971553/3184778 „musisz użyć widoku, który odnosi się do RODZICY widoku, nad którym pracujesz, a nie do rzeczywistego widoku”
Jeśli na przykład TextView znajduje się wewnątrz TableRow, musisz użyć TableRow.LayoutParams zamiast RelativeLayout lub LinearLayout
Użyj tej funkcji, aby ustawić wszystkie typy marginesów
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);
}
Moduł Core KTX zawiera rozszerzenia dla popularnych bibliotek, które są częścią struktury systemu Android, androidx.core.view
między innymi.
dependencies {
implementation "androidx.core:core-ktx:{latest-version}"
}
Do obsługi marginesów przydatne są następujące funkcje rozszerzające:
setMargins()
funkcja rozszerzenia:Ustawia marginesy wszystkich osi w ViewGroup
plikach MarginLayoutParams
. (Wymiar należy podać w pikselach, patrz ostatnia sekcja, jeśli chcesz pracować z dp)
inline fun MarginLayoutParams.setMargins(@Px size: Int): Unit
// E.g. 16px margins
val params = (myView.layoutParams as ViewGroup.MarginLayoutParams)
params.setMargins(16)
updateMargins()
funkcja rozszerzenia:Aktualizuje marginesy w ViewGroup
pliku 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()
funkcja rozszerzenia:Aktualizacje względne marginesy w ViewGroup
„s MarginLayoutParams
(start / koniec zamiast w lewo / prawo).
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)
Poniższe właściwości rozszerzenia są przydatne, aby uzyskać aktualne marginesy:
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
dp
zamiast px
:Jeśli chcesz pracować z dp
(pikselami niezależnymi od gęstości) zamiast z px
, musisz najpierw je przekonwertować. Możesz to łatwo zrobić za pomocą następującej właściwości rozszerzenia:
val Int.px: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
Następnie możesz wywołać poprzednie funkcje rozszerzeń, takie jak:
params.updateMargins(start = 16.px, end = 16.px, top = 8.px, bottom = 8.px)
val bottomDp = myView1.marginBottom.dp
Stara odpowiedź:
W Kotlinie możesz zadeklarować funkcję rozszerzającą taką jak:
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()
}
Następnie możesz to nazwać tak:
myView1.setMargins(8, 16, 34, 42)
Lub:
myView2.setMargins(topMarginDp = 8)