我无法通过XML中布局的ID到达片段的顶层“”,它原来是一个空对象。但我可以访问其子视图的父视图。父级不是布局本身,而是包含该布局的''。当我以编程的方式将子元素添加到这个片段中时,它们不会与已经存在的子元素对齐,这表明这些子元素实际上在嵌套布局中。
这种行为真使我恼火。有人能解释发生了什么事吗?
我声明了一个顶级的分段布局,如下所示:
同级片段和布局设置被剥离以提高可读性
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_view"
>
<fragment
android:layout_gravity="center_horizontal|center_vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="40dp"
android:layout_weight="0.3"
android:name="foo.bar.foobar.fragments.ShowWeightsFragment"
android:id="@+id/show_weights_fragment"
tools:layout="@layout/frag_show_weights"
/>
</LinearLayout>
layout/frag_show_weights
定义如下:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout_container_weights"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Foo"
android:id="@+id/xmlTextChildren"
android:layout_gravity="center" />
</LinearLayout>
mainActivity.java如下所示
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView t = (TextView) findViewById(R.id.xmlTextChildren);
t.setText("Foo");
LinearLayout parentLayout = (LinearLayout) findViewById(R.id.xmlTextChildren).getParent();
LinearLayout layoutFromID = (LinearLayout) findViewById(R.id.layout_container_weights);
TextView v = new TextView(this);
v.setText("Bar");
if (layoutFromID == null) Log.d(TAG, "Layout from ID is null");
Log.d(TAG, "ID parent name: " + getResources().getResourceEntryName(parentLayout.getId()));
parentLayout.addView(v);
}
日志输出如下:
08-22 12:06:24.855:d/mainActivity(2346):来自ID的布局为空
08-22 12:06:24.856:d/mainActivity(2346):id父名称:show_weights_fragment
而实际的模拟器输出显示两个文本不对齐,这使我假设它们不包含在同一个
<LinearLayout>
最佳答案
简而言之:如果您在R.id.show_weights_fragment
中设置了id,那么可以使用片段的id<fragment>
来访问其视图。
The documentation for Fragments有一个处理片段id的语句:
注意:每个片段都需要一个唯一的标识符,如果活动重新启动,系统可以使用该标识符还原片段(并且可以使用该标识符捕获片段以执行事务,例如移除它)。提供片段ID的方法有三种:
为android:id属性提供唯一的id。
为android:tag属性提供一个唯一的字符串。
如果前两个都不提供,则系统将使用容器视图的ID。
这激发了一种假设,即如果片段的id被设置,那么它只会以相反的方式工作。我找不到关于这个的文档,但是the sources for FragmentManagerImpl
表明,这个假设成立:
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
if (!"fragment".equals(name)) {
return null;
}
[...]
int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID);
String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
[...]
if (id != 0) {
fragment.mView.setId(id);
}
if (fragment.mView.getTag() == null) {
fragment.mView.setTag(tag);
}
return fragment.mView;
}
这也是您的日志所显示的:
parentLayout.getId() == R.id.show_weights_fragment
。