Android Fragment顶级布局无法以编程方式访问

我无法通过其xml中给出布局的id到达片段的顶级”,它原来是一个空对象.但我可以访问其子视图的父级.那个父母不是布局本身,而是“包含布局”.当我以编程方式将子项添加到此片段时,它们不会与已存在的子项对齐,这表明这些子项实际上位于嵌套布局中.

这种行为真的让我感到困惑.任何人都可以解释发生了什么?

我声明了一个顶级碎片布局,如下所示:

Sibling fragments and layout settings stripped for readability

<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): Layout from ID is null

08-22 12:06:24.856: D/MainActivity(2346): ID parent name: show_weights_fragment

并且实际的模拟器输出显示两个文本不对齐,这使我假设它们不包含在相同的< LinearLayout>内.
《Android Fragment顶级布局无法以编程方式访问》

最佳答案 简答:如果您在< fragment>中设置了ID,请使用片段的ID R.id.show_weights_fragment来访问其视图.

The documentation for Fragments有一个处理ID片段的声明:

Note: Each fragment requires a unique identifier that the system can use to restore the fragment if the activity is restarted (and which you can use to capture the fragment to perform transactions, such as remove it). There are three ways to provide an ID for a fragment:

  • Supply the android:id attribute with a unique ID.
  • Supply the android:tag attribute with a unique string.
  • If you provide neither of the previous two, the system uses the ID of the container view.

如果设置了片段的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.

点赞