【问题标题】:Using findViewById in Activity's onCreate not behaving as expected在 Activity 的 onCreate 中使用 findViewById 的行为不符合预期
【发布时间】:2014-04-26 18:29:22
【问题描述】:

我正在尝试使用“RangeSeekBar”(https://code.google.com/p/range-seek-bar/)。这必须在代码而不是 XML 中完成,因此我已按照说明将示例代码插入到我的活动的 onCreate 方法中。

我的代码在下面概述的findViewById 方法中崩溃了。使用示例代码,我得到以下两个结果:

  1. 如果我尝试通过引用其 ID 来直接获取 LinearLayout,则会收到空指针异常。我希望这能提供 LinearLayout,我不明白为什么这是 null。

  2. 如果我引用R.id.container,我可以插入 RangeSeekBar,但它与第一​​个字段重叠。请注意,如果我尝试将容器转换为 LinearLayout 而不是 ViewGroup,我会收到一个错误,指出容器是 FrameLayout,这告诉我容器不是我想要的 LinearLayout。

我的问题是,如何将 RangeSeekBar 插入片段 ViewGroup 以使其符合 LinearLayout? 或者,如何从活动 onCreate 中检索片段 LinearLayout 和避免空指针异常?

更新:我之前列出了片段 xml 而不是活动 xml。我已经用下面的两个 XML 更新了问题。

这是我的 onCreate 方法:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_manage_seeds);

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
    }

    // I replaced the sample code's "context" with getBaseContext() should this be something else??
    //RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(20, 75, context); //CODE SAMPLE 
    RangeSeekBar<Integer> seekBar = new RangeSeekBar<Integer>(0, 40, getBaseContext()); //MY VERSION

    seekBar.setOnRangeSeekBarChangeListener(new OnRangeSeekBarChangeListener<Integer>() {
        @Override
        public void onRangeSeekBarValuesChanged(RangeSeekBar<?> bar, Integer minValue, Integer maxValue) {
            // handle changed range values
            Log.i(TAG, "User selected new range values: MIN=" + minValue + ", MAX=" + maxValue);
        }
    });

    // add RangeSeekBar to pre-defined layout
    //ViewGroup layout = (ViewGroup) findViewById(<your-layout-id>); //SAMPLE CODE
    ViewGroup layout = (ViewGroup) findViewById(R.id.container); //MY CODE THAT SORT OF WORKS
    layout.addView(seekBar); // This inserts the RangeSeekBar overlapping the Name field

    //ViewGroup layout = (ViewGroup) findViewById(R.id.layout_manage); //MY CODE THAT RETURNS A NULL POINTER EXCEPTION AT RUNTIME
    //layout.addView(seekBar); // This causes the null pointer exception because the line above returns null.
}

这是我的片段 XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout_manage"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <EditText android:id="@+id/test_edit_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/test_edit_name" />

    <EditText android:id="@+id/test_edit_type"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/test_edit_type" />

    <!-- I want the custom RangeSeekBar added here. Must be done via java code, not possible through XML -->

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/test_button_save"
        android:layout_gravity="right" />
</LinearLayout>

这是我的 activity_manage_seeds xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.mypackage.myapp.ManageSeedsActivity"
    tools:ignore="MergeRootFrame" />

【问题讨论】:

  • 您可以在布局之间保留一个空的线性布局,并以编程方式在其中膨胀范围栏。
  • 但是R.id.container 是什么?您的 xml 中没有此 id 的任何视图?
  • 问题已更新以包含活动 xml,@Gustek,由于我正在使用片段文件,因此我忽略了它。我不明白我现在所做的活动与片段 xml 之间的区别。

标签: android android-layout oncreate


【解决方案1】:

我认为一个更简洁的解决方案是将 FrameLayout 添加到现有的 LinearLayout 中,并将 RangeSeekBar 添加到 FrameLayout 中。见下文:

<!-- Activity Layout -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:id="@+id/layout_manage"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical" >

<EditText android:id="@+id/test_edit_name"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />

<EditText android:id="@+id/test_edit_type"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />

<!-- This is the container for the RangeSeekBar -->
<FrameLayout
    android:id="@+id/range_seek_bar_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="right" />
</LinearLayout>

您的 onCreate() 方法可能如下所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    RangeSeekBar rangeSeekBar = new RangeSeekBar<Integer>(20, 75, context);

    ViewGroup rangeBarContainer = (ViewGroup) findViewById(R.id.range_seek_bar_container);
    rangeBarContainer.addView(rangeSeekBar);
}

这使得编辑 RangeSeekBar 的布局属性变得更加容易

更新

在阅读您的新代码时,我注意到您正试图从您的 Activity 代码中编辑您的片段之一的布局。你不应该这样做。在PlaceholderFragment 内部工作。

PlaceholderFragment 中的 onCreateView() 方法:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.your_fragment_layout, container, false);

    RangeSeekBar rangeSeekBar = new RangeSeekBar<Integer>(20, 75, context);

    ViewGroup rangeBarContainer = (ViewGroup) rootView.findViewById(R.id.range_seek_bar_container);
    rangeBarContainer.addView(rangeSeekBar);

    return rootView;
}

【讨论】:

  • 嗯,我从来没有想过这种方法,谢谢你的建议。我会试一试,然后告诉你进展如何。
  • 感谢我更新后的澄清。这有助于我更清楚地了解 android 活动和片段。
  • 不用担心,Android API 指南提供了大量关于活动和片段如何交互的信息Activities - Fragments
【解决方案2】:

1) 当您尝试访问一个不在您的布局文件 (activity_manage_seeds) 中的视图时,会发生 NullPointerExcption。

请确保您的 Viewgroup layout_manage 在 activity_manage_seeds.xml 文件中。

2) 关于您的搜索栏位置,您需要添加布局参数以设置其正确位置,前提是您的 viewGroup R.id.container 位于上面显示的 xml 文件中不存在的 activity_manage_seeds.xml 中。

【讨论】:

  • 1) 啊,我明白了。然后我想我的问题实际上是:如何从我的片段 XML 访问 LinearLayout,这是定义我的其他 View 对象的地方。我会更新问题以反映这个细节(我以前不明白,谢谢)。 2) 容器位于 activity_manage_seeds.xml 中,而我已经发布了片段 XML 文件。我也会用这个更新问题。
【解决方案3】:

您在代码中弄错了线性布局 ID,尝试将其更改为 layout_manage 而不是容器。

【讨论】:

  • 不幸的是,正如我在代码示例末尾的评论所述,这会在运行时产生空指针异常。 layout_manage 不起作用。
  • 快速更新:我提供了我的片段 xml(layout_manage 所在的位置),而不是我的活动 xml。我已更新问题以反映这一点。
【解决方案4】:

您正在尝试获取不在您的 xml 中的视图,这就是它返回空指针的原因..

改变这个布局:

setContentView(R.layout.activity_manage_seeds);

到 id R.id.container 所在的布局

【讨论】:

  • 嗯,我不确定我是否理解。我的理解是活动(ManageSeedsActivity)被激活,然后从该文件中调用此 onCreate 方法,因此 setContentView 应该针对该活动,因为它是该活动的 onCreate。它是否正确? R.id.container 来自活动 XML 文件(我已在问题中更新)。我想要的是我的片段 xml 文件中的 LinearLayout。所以我现在的问题是:如何从 Activity onCreate 中检索片段 LinearLayout?
猜你喜欢
  • 2018-10-22
  • 1970-01-01
  • 2012-01-09
  • 1970-01-01
  • 1970-01-01
  • 2017-01-27
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多