英文:
Change a view margins programmatically
问题
我有一个RecyclerView,底部有250dp的边距,我需要以编程方式将底部边距设置为0dp,然后再将其设置回250dp。我尝试过这样做,但只能将其设置为0dp,设置为250dp无效:
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
params.setMargins(0, 0, 0, 250); // 最初是 params.setMargins(0, 0, 0, 0);
linearLayoutRv.setLayoutParams(params);
这里有一些不必要的内容,但以下是XML文件:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/linearLayoutRv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginBottom="250dp"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="51dp"
android:gravity="center">
<!-- 这里是TextView -->
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="51dp"
android:orientation="horizontal">
<!-- 这里是一些按钮 -->
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="5dp"
android:padding="4dp"
android:scrollbars="vertical" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
英文:
So I have a RecyclerView that has 250dp bottom margin
And I need to set the bottom margin programmatically to 0dp then set it back to 250dp, I have tried this but it's working just to set it 0dp and it doesn't work setting it to 250dp back:
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
params.setMargins(0,0,0,250); // params.setMargins(0,0,0,0); at first
linearLayoutRv.setLayoutParams(params);
There's some unnecessary things but here's the xml file :
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/linearLayoutRv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginBottom="250dp"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="51dp"
android:gravity="center">
//textview
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="51dp"
android:orientation="horizontal">
//some buttons
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="5dp"
android:padding="4dp"
android:scrollbars="vertical" />
</LinearLayout>
答案1
得分: 0
问题在于setMargins
接受的值不是以dp
(密度无关像素)为单位,而是以px
(像素)为单位。
在将其传递给params
对象之前,您必须将值250转换为dp
。
Context context = ...; // 如果您在Activity中,可以使用'this';如果您在Fragment中,可以使用'requireContext()'
Resources res = context.getResources();
float dp250 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 250, res.getDisplayMetrics());
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
params.setMargins(0, 0, 0, dp250);
linearLayoutRv.setLayoutParams(params);
dp250
将在不同设备上产生不同数量的像素。这取决于分辨率和物理屏幕大小。
英文:
The problem is that setMargins
accepts values not in dp
(density independent pixels) unit but in px
(pixel) unit.
You must convert your value of 250 to dp
before passing it to the params
object.
Context context = ...; // place 'this' if you are in an Activity or 'requireContext()' if you are in a Fragment
Resources res = context.getResources();
float dp250 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 250, res.getDisplayMetrics());
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
params.setMargins(0, 0, 0, dp250);
linearLayoutRv.setLayoutParams(params);
dp250
will result in a different number of pixels on different devices. It depends on the resolution and physical screen size.
答案2
得分: 0
当您以编程方式设置边距时,您需要以像素为单位设置值,而不是dp。LayoutParams的来源:
/**
* 以像素为单位设置边距。需要调用 {@link android.view.View#requestLayout()} 以便新边距得到考虑。
* 根据布局方向,左右边距可能会被 {@link android.view.View#requestLayout()} 覆盖。
* 边距值应该是正数。
*
* @param left 左边距大小
* @param top 顶部边距大小
* @param right 右边距大小
* @param bottom 底部边距大小
*
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginLeft
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginRight
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
*/
public void setMargins(int left, int top, int right, int bottom) {
leftMargin = left;
topMargin = top;
rightMargin = right;
bottomMargin = bottom;
mMarginFlags &= ~LEFT_MARGIN_UNDEFINED_MASK;
mMarginFlags &= ~RIGHT_MARGIN_UNDEFINED_MASK;
if (isMarginRelative()) {
mMarginFlags |= NEED_RESOLUTION_MASK;
} else {
mMarginFlags &= ~NEED_RESOLUTION_MASK;
}
}
您需要将dp转换为像素:
int yourDP = 250;
Resources r = getResources();
float px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
yourDP,
r.getDisplayMetrics()
);
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
params.setMargins(0, 0, 0, (int) px); // 最初 params.setMargins(0,0,0,0);
linearLayoutRv.setLayoutParams(params);
英文:
When you set margins programatically, you set value in pixels, not dp. Source of LayoutParams:
/**
* Sets the margins, in pixels. A call to {@link android.view.View#requestLayout()} needs
* to be done so that the new margins are taken into account. Left and right margins may be
* overridden by {@link android.view.View#requestLayout()} depending on layout direction.
* Margin values should be positive.
*
* @param left the left margin size
* @param top the top margin size
* @param right the right margin size
* @param bottom the bottom margin size
*
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginLeft
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginRight
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
*/
public void setMargins(int left, int top, int right, int bottom) {
leftMargin = left;
topMargin = top;
rightMargin = right;
bottomMargin = bottom;
mMarginFlags &= ~LEFT_MARGIN_UNDEFINED_MASK;
mMarginFlags &= ~RIGHT_MARGIN_UNDEFINED_MASK;
if (isMarginRelative()) {
mMarginFlags |= NEED_RESOLUTION_MASK;
} else {
mMarginFlags &= ~NEED_RESOLUTION_MASK;
}
}
You need convert your dp to pixels:
Int yourDP = 250
Resources r = getResources();
float px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
yourDP,
r.getDisplayMetrics()
);
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
params.setMargins(0,0,0,(int) px); // params.setMargins(0,0,0,0); at first
linearLayoutRv.setLayoutParams(params);
答案3
得分: 0
你可以很容易地使用 MotionLayout
完成这个操作。只需将父级 ConstraintLayout
转换为 MotionLayout
,创建 MotionScene
,然后在代码中使用 transitionToEnd()
和 transitionToStart()
。
英文:
You can easily do this with MotionLayout
.
Just convert parent ConstraintLayout
to MotionLayout
, create MotionScene
and in code use transitionToEnd()
and transitionToStart()
答案4
得分: 0
我添加了这个方法:
public static int convertDpToPixel(int dp, Context context){
return dp * ((int) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
并修改了这部分代码:
params.setMargins(0,0,0,convertDpToPixel(250,getContext()));
英文:
it was working but in pixels, so i added this method:
public static int convertDpToPixel(int dp, Context context){
return dp * ((int) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
and changed this:
params.setMargins(0,0,0,convertDpToPixel(250,getContext()));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论