如何在片段的父活动中访问片段的子视图?

77

我有一个支持片段活动,它将加载不同的片段。该片段具有一些textView,其id =“score”,我想获取它的句柄,但是对于得分的textViewfindViewById返回null。为什么会这样?


textView位于片段中。

public class MyActivity extends  extends ActionBarActivity
        implements NavigationDrawerFragment.NavigationDrawerCallbacks{

   private TextView scoreBoardTextView = null;

   protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_home);
     mNavigationDrawerFragment = (NavigationDrawerFragment)
                getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
     scoreBoardTextView = (TextView) findViewById(R.id.score); //this returns null
  }

    @Override
    public void onNavigationDrawerItemSelected(int position) {
      //set fragment    
    }

}

你的TextView放在哪里?它是在Fragment布局中吗?如果是,那么你必须在Fragment的onCreateView方法中调用scoreBoardTextView = (TextView) findViewById(R.id.score);。类似这样:http://stackoverflow.com/questions/24156139/android-spinner-nullpointexception/24156516#24156516 - Zoran
在片段中。 - user93796
@Rod_Algonquin 我没听懂你的意思。 - user93796
4
你想要在Activity中更新Fragment的TextView吗?最好在Fragment本身中进行操作。 - Yaroslav Mytkalyk
你想引用的 TextView 属于 fragment 的布局还是 MainActivity 的布局? - user2121
显示剩余3条评论
17个回答

72

注意:

直接在片段之外访问片段视图不是一个好主意。您应该使用片段回调接口来处理这种情况并避免错误。下面的方法虽然可行,但并不推荐,因为这不是一个好习惯。


如果您想在父Activity中访问FragmentTextView,那么您应该在Fragment类中定义一个方法,如下所示:

public class MyFragment extends Fragment {

    TextView mTextView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_main, container, false);
        mTextView = (TextView) view.findViewById(R.id.textView1);
        return view;
    }

    public void setTextViewText(String value){
        mTextView.setText(value);
    }


}

现在你可以在Activity中像这样使用它:

myFragment.setTextViewText("foo");

这里的myFragmentMyFragment类型。

如果您想要访问整个TextView,那么您可以在MyFragment.java内定义一个像这样的方法:

public TextView getTextView1(){
    return mTextView;
}

通过这种方式,您可以访问TextView本身。

希望这能帮到您。:)


2
这看起来是一个不错的答案,但我认为应该重写onCreateView()方法而不是getView()方法。 - matiash
这是正确的方法,使用view.findViewById()。 - Android Noob
假设我想在用户按下返回按钮时检查片段视图是否可见。那么就需要使用这个解决方案。 - Kaveesh Kanwal
2
你可以实现片段,以便它可以告诉你特定视图是否可见。这样更加清晰。片段负责视图,Activity使用片段提供的接口获取有关视图的信息。没有直接访问。 - kupsef
@kupsef 这个回答也建议同样的方法。欢迎您编辑答案或自己详细解释相同的内容。 - SMR
显示剩余5条评论

26

可以通过以下方式实现:

在 Fragment 中像这样保留已填充视图的引用:

public class MyFragment extends SherlockFragment{

MainMenuActivity activity;
public View view;
public MyFragment(){
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    if ( getActivity() instanceof MainMenuActivity){
        activity = (MainMenuActivity) getActivity();
    }

    view = inflater.inflate(R.layout.aboutus, container, false);        
    return view;
}

}

在Activity中创建一个函数,像这样:

 public class MainMenuActivity extends SherlockFragmentActivity {

 SherlockFragment fragment = null;

 public void switchContent(SherlockFragment fragment) {     
    this.fragment = fragment;
    getSupportFragmentManager()
    .beginTransaction()
    .replace(R.id.mainmenu, fragment)
    .commit();

    invalidateOptionsMenu();
}

它的目的是保持当前片段的参考。每当你想要切换片段时,你调用上述函数,就像这样(来自片段):

activity.switchContent( new MyFragment_2());

现在您已经拥有当前片段引用。因此,您可以像这样直接在Activity中访问Fragment的视图:this.fragment.view


不错的技巧,我会试一下...! - Arsalan
父活动不应直接操作片段的视图。您应该编写一个在片段内执行修改的函数。直接访问片段的视图实际上使片段无用。这样会丢失封装性,您最好将这些视图添加到活动的布局中。 - kupsef
@kupsef 显然我们需要通过方法访问它们,我只是为了理解在这里进行了访问。 - Arsalan Mehmood

11

您不需要在Activity中引用Fragment视图即可获取其组件。因为您可以直接在父级Activity中访问Fragment的布局组件。

只需使用以下方法即可访问任何组件。


findViewById(R.id.child_of_fragment_layout);  

4
这句话的意思是:这个说法基本上是正确的,但有一点需要注意(至少对我来说),即碎片视图可能还没有准备好。当我将那段代码移动到我的活动的onStart()方法时,它起作用了。 - Amr Mostafa

5
您可以使用Fragment类的getView方法访问它。例如,如果您有一个ID为"text_view"的TextView在MyFragment中,那么在您的Activity中创建一个您自己的Fragment:
MyFragment myFragment = new MyFragment();

当您需要一个子项时,只需调用getView,然后找到您的childView。

View view = myFragment.getView();
if (view !=null) {
view.findViewById(R.id.text_view).setText("Child Accessed :D");
}

注意:如果你想要获取片段的根视图,那么myFragment.getView();就足够了。


我对你的回答有问题,如果R.id.something是根视图,那么getView()就足够了。 - cutiko
@cutiko 是的,getView方法返回片段布局的根视图。 - Saman Sattari

5
为了访问你的片段中的 TextView、Button 或其他组件,需要按照以下步骤进行操作:
public class BlankFragment extends Fragment {
public View view;
public TextView textView;
public Button button;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    view =inflater.inflate(R.layout.fragment_blank, container, false);
    textView = (TextView)view.getRootView().findViewById(R.id.textView_fragment1);
    return view;
}

public void changeTextOfFragment(String text){
    textView.setText(text);
    view.setBackgroundResource(R.color.colorPrimaryDark);
}

一旦您在MainActivity或任何其他您想从Fragment中访问TextView的位置完成了这项工作,您应该确保在OnCreate()方法中设置片段,否则它很可能会抛出nullPointer异常。因此,您想更改TextView的活动应该如下所示:

public class MainActivity extends AppCompatActivity {
private Button button1;
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
BlankFragment blankFragment = new BlankFragment();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    button1 = (Button)findViewById(R.id.button1);
    changeFragment();

    fragmentManager = getFragmentManager();
    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.fragment1,blankFragment);
    fragmentTransaction.commit();
}

private void changeFragment(){
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            blankFragment.changeTextOfFragment("Enter here the text which you want to be displayed on your Updated Fragment");

        }
    });
}

希望这可以帮到您 :)

3

只需使用片段而不是活动:

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

    TextView scoreBoardTextView = (TextView) rootView.findViewById(R.id.score);

    return rootView;
}

我需要在加载片段的父活动中获取“scoreBoardTextView”活动的句柄。我该怎么做? - user93796
1
“Handle” 是什么意思?您需要更改 TextView(文本、背景……)还是需要在 Activity 中获取 TextView 的文本? - Zoran
似乎你不太想得到答案? - Zoran
@Zoran,是的,我需要在按钮的onClick事件中从片段中获取TextView的字符串。 - Amogh Jahagirdar

3

只需要这样做:

((Your_Activity) this.getActivity()).YouyActivityElements;

2
如果您的TextView位于Fragment内,那么您无法在Fragment的父Activity中访问TextView。您可以为Fragment和Activity之间的交互设置接口,并在单击TextView或其他任何想要发生的事情时发送数据。请注意保留HTML标签。

1
您无法在父Activity中访问Fragment元素,但可以通过以下方式向Fragment传递值。
在MyActivity的onNavigationDrawerItemSelected方法中进行如下操作。
int myScore = 100;
@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager
            .beginTransaction()
            .replace(R.id.container,
                    MyFragment.newInstance(myScore)).commit();
}

MyFragment类中创建一个名为newInstance的方法,如下所示。
private static final String SCORE = "score";
public static MyFragment newInstance(int score) {
    MyFragment fragment = new MyFragment();
    Bundle args = new Bundle();
    args.putInt(SCORE, score);
    fragment.setArguments(args);
    return fragment;
}

MyFragmentonCreateView()方法中。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_main, container,
            false);
    TextView textView = (TextView) rootView
            .findViewById(R.id.score);
    textView.setText(Integer.toString(getArguments().getInt(
            SCORE)));
    return rootView;
}

这就是全部了,我希望这能对你有所帮助。如果不行,请告诉我。


0
你需要从你的Fragment视图中调用findViewById方法。
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);
    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
    scoreBoardTextView = (TextView) mNavigationDrawerFragment.getView().findViewById(R.id.score); 
}

这种方法对我很有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接