使用 LayoutParams.addRule 设置动态设置视图到视图的最后位置
Setting views dynamically with LayoutParams.addRule setting to the last position of the view
我正在向相对布局动态添加视图并以编程方式定义它们。视图可以在屏幕上移动,因此它们的位置会发生变化。
当我尝试将视图 (button2) 设置为位于另一个视图 (button1) 下方时,button2 被放置在 button1 的旧位置(在移动之前添加视图的默认位置)。我已经链接了图片,希望能更好地传达这一点。
这是原始布局
Button2重新定位后的布局
我有一个后台 LinkedList,用于跟踪布局的所有视图更改和视图属性(如果有差异的话)。
以下是代码函数:
我如何重新定位 Button1:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.CENTER_VERTICAL);
b.setLayoutParams(positioningLayout);
baseLayout.addView(b);
在另一个视图下方重新定位视图代码片段:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.setLayoutParams(positioningLayout);
b.invalidate();
我如何将视图添加到布局中。
uiList.addView(new Buttons(this), "BUTTON");
setDialogView(uiList.getLast());
showDialog(SET_ID);
reloadUI();
setDialogView 只是将视图传递给对话框 SET_ID 以便我可以手动为视图分配一个 ID(用于测试)。
reloadUI() 只是找到最后添加到后台 LinkedList 的视图,并将其添加到 relativeLayout using .addView;
如果您需要更多代码,请告诉我。在对 relativeLayout 子视图进行更改后,我是否错过了更新视图布局的调用?看起来视图在视觉上正在重新定位,但实际的 LayoutParams 没有更新,所以当您将 Button2 设置为 Button1 时,它正在获得旧位置。
有没有办法强制重新定位相对布局视图?
您似乎走对了路,但犯了一个小错误。如果没有更多代码,就很难提供实际的解决方案。不过我会尽量指出错误的。
看,要在 RelativeLayout 中以编程方式相对定位项目,您必须 为每个项目分配唯一 ID。
喜欢,
Button b = new Button(this);
b.setId(1);
Button c = new Button(this);
c.setId(2);
每个元素都应该有唯一的 ID。
现在如果要将按钮 b 垂直放置在中央,
layout.addRule(RelativeLayout.CENTER_VERTICAL);
b.setLayoutParams(layout);
现在如果你想把 Button c 放在它下面,
layout.addRule(RelativeLayout.BELOW, b.getId());
layout.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
b.setLayoutparams(layout);
这肯定会将按钮 c 放在按钮 b 的下方。正如您所说,您可以使用您选择的任何数据结构来跟踪每个元素的 ID。
这只是关于如何正确移动按钮的详细示例。所以首先,为 View
创建一个唯一的 id,即在 res/values/
中创建一个新的 XML 资源文件,并将其命名为 ids.xml
:
而ids.xml
的内容是:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="button_1" type="id"/>
<item name="button_2" type="id"/>
</resources>
我们必须为您的主布局设置一个 id:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout_main"> <!-- the id -->
<!-- content of this layout -->
</RelativeLayout>
然后,让我们创建 Button
s:
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.layout_main);
final Button button1 = new Button(this);
button1.setId(R.id.button_1);
button1.setText("BUTTON 1");
button1.setTextColor(Color.BLACK);
final Button button2 = new Button(this);
button2.setId(R.id.button_2);
button2.setText("BUTTON 2");
button2.setTextColor(Color.BLACK);
relativeLayout.addView(button1, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
relativeLayout.addView(button2, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) button1.getLayoutParams();
params1.addRule(RelativeLayout.CENTER_IN_PARENT); // set to the center of screen
button1.setLayoutParams(params1);
final RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) button2.getLayoutParams();
params2.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
button2.setLayoutParams(params2);
button2.setOnClickListener(new View.OnClickListener() {
@SuppressLint("NewApi")
@Override
public void onClick(View v) {
/* We need to remove the existing rules and update it!
* For API 16 and earlier, set the rule to 0, e.g. --> layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
* For API 17 and higher, call layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
*/
int api = android.os.Build.VERSION.SDK_INT;
if (api >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // API level 17
params2.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
params2.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
}else if (api < Build.VERSION_CODES.JELLY_BEAN_MR1) {
params2.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
}
params2.addRule(RelativeLayout.CENTER_IN_PARENT);
params2.addRule(RelativeLayout.BELOW, R.id.button_1); // place below button1
button2.setLayoutParams(params2);
}
});
所以一旦你点击 button2
,它就会移到 button1
下面。
我认为您应该尝试简单的解决方案 - 将 b.invalidate()
替换为 b.requestLayout()
。如需更多背景调查 this link。我没有测试它,但我希望它会起作用。所以代码应该是这样的:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.setLayoutParams(positioningLayout);
b.requestLayout();
或者您可以将其简化为:
Buttons b = (Buttons) viewIndex;
((RelativeLayout.LayoutParams) b.getLayoutParams()).addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.requestLayout();
我正在向相对布局动态添加视图并以编程方式定义它们。视图可以在屏幕上移动,因此它们的位置会发生变化。
当我尝试将视图 (button2) 设置为位于另一个视图 (button1) 下方时,button2 被放置在 button1 的旧位置(在移动之前添加视图的默认位置)。我已经链接了图片,希望能更好地传达这一点。
这是原始布局
Button2重新定位后的布局
我有一个后台 LinkedList,用于跟踪布局的所有视图更改和视图属性(如果有差异的话)。
以下是代码函数:
我如何重新定位 Button1:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.CENTER_VERTICAL);
b.setLayoutParams(positioningLayout);
baseLayout.addView(b);
在另一个视图下方重新定位视图代码片段:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.setLayoutParams(positioningLayout);
b.invalidate();
我如何将视图添加到布局中。
uiList.addView(new Buttons(this), "BUTTON");
setDialogView(uiList.getLast());
showDialog(SET_ID);
reloadUI();
setDialogView 只是将视图传递给对话框 SET_ID 以便我可以手动为视图分配一个 ID(用于测试)。 reloadUI() 只是找到最后添加到后台 LinkedList 的视图,并将其添加到 relativeLayout using .addView;
如果您需要更多代码,请告诉我。在对 relativeLayout 子视图进行更改后,我是否错过了更新视图布局的调用?看起来视图在视觉上正在重新定位,但实际的 LayoutParams 没有更新,所以当您将 Button2 设置为 Button1 时,它正在获得旧位置。
有没有办法强制重新定位相对布局视图?
您似乎走对了路,但犯了一个小错误。如果没有更多代码,就很难提供实际的解决方案。不过我会尽量指出错误的。
看,要在 RelativeLayout 中以编程方式相对定位项目,您必须 为每个项目分配唯一 ID。
喜欢,
Button b = new Button(this);
b.setId(1);
Button c = new Button(this);
c.setId(2);
每个元素都应该有唯一的 ID。
现在如果要将按钮 b 垂直放置在中央,
layout.addRule(RelativeLayout.CENTER_VERTICAL);
b.setLayoutParams(layout);
现在如果你想把 Button c 放在它下面,
layout.addRule(RelativeLayout.BELOW, b.getId());
layout.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
b.setLayoutparams(layout);
这肯定会将按钮 c 放在按钮 b 的下方。正如您所说,您可以使用您选择的任何数据结构来跟踪每个元素的 ID。
这只是关于如何正确移动按钮的详细示例。所以首先,为 View
创建一个唯一的 id,即在 res/values/
中创建一个新的 XML 资源文件,并将其命名为 ids.xml
:
而ids.xml
的内容是:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="button_1" type="id"/>
<item name="button_2" type="id"/>
</resources>
我们必须为您的主布局设置一个 id:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout_main"> <!-- the id -->
<!-- content of this layout -->
</RelativeLayout>
然后,让我们创建 Button
s:
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.layout_main);
final Button button1 = new Button(this);
button1.setId(R.id.button_1);
button1.setText("BUTTON 1");
button1.setTextColor(Color.BLACK);
final Button button2 = new Button(this);
button2.setId(R.id.button_2);
button2.setText("BUTTON 2");
button2.setTextColor(Color.BLACK);
relativeLayout.addView(button1, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
relativeLayout.addView(button2, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) button1.getLayoutParams();
params1.addRule(RelativeLayout.CENTER_IN_PARENT); // set to the center of screen
button1.setLayoutParams(params1);
final RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) button2.getLayoutParams();
params2.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
button2.setLayoutParams(params2);
button2.setOnClickListener(new View.OnClickListener() {
@SuppressLint("NewApi")
@Override
public void onClick(View v) {
/* We need to remove the existing rules and update it!
* For API 16 and earlier, set the rule to 0, e.g. --> layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
* For API 17 and higher, call layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
*/
int api = android.os.Build.VERSION.SDK_INT;
if (api >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // API level 17
params2.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
params2.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
}else if (api < Build.VERSION_CODES.JELLY_BEAN_MR1) {
params2.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
}
params2.addRule(RelativeLayout.CENTER_IN_PARENT);
params2.addRule(RelativeLayout.BELOW, R.id.button_1); // place below button1
button2.setLayoutParams(params2);
}
});
所以一旦你点击 button2
,它就会移到 button1
下面。
我认为您应该尝试简单的解决方案 - 将 b.invalidate()
替换为 b.requestLayout()
。如需更多背景调查 this link。我没有测试它,但我希望它会起作用。所以代码应该是这样的:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.setLayoutParams(positioningLayout);
b.requestLayout();
或者您可以将其简化为:
Buttons b = (Buttons) viewIndex;
((RelativeLayout.LayoutParams) b.getLayoutParams()).addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.requestLayout();