如何在片段父Activity中访问Fragment子视图?

时间:2014-06-12 15:18:09

标签: android android-layout

我有一个受支持的片段活动,它将加载diff片段。该片段包含一些textView id = "score",我希望得到它的句柄,但findViewById得分textView返回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    
    }

}

17 个答案:

答案 0 :(得分:63)

注意:

直接访问片段外的片段视图不是一个好主意。您应该使用片段回调接口来处理此类情况并避免错误。以下方式有效但不建议使用,因为这不是一个好习惯。

<小时/> 如果您想访问其父TextView内的Fragment Activity,那么您应该在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");

此处myFragment的类型为MyFragment

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

public TextView getTextView1(){
    return mTextView;
}

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

希望这有助于。 :)

答案 1 :(得分:22)

可以通过以下方式:

在片段中保持对膨胀视图的引用,如下所示:

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

答案 2 :(得分:12)

您无需参考 Fragment 视图即可在活动中获取其组件。您可以直接访问父活动片段的布局组件。

您只需通过此

访问任何组件即可
findViewById(R.id.child_of_fragment_layout);  

答案 3 :(得分:4)

您可以使用Fragment类的getView方法进行访问。

例如,你的MyFragment中有一个ID为“text_view”的TextView
在你的活动中制作你的片段:

MyFragment myFragment = new MyFragment();

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

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

答案 4 :(得分:3)

要访问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");

        }
    });
}

希望这有帮助:)

答案 5 :(得分:2)

只需放入片段而不是放入活动:

@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;
}

答案 6 :(得分:2)

只做这个:

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

答案 7 :(得分:2)

如果您的TextView放置在Fragment中,那么您无法访问 Fragment Parent Activity 中的TextView,您可以设置Fragment和Activity之间进行相互通信的界面,并在单击TextView或其他任何东西时发送数据你想要发生

答案 8 :(得分:0)

您需要从片段视图中调用方法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); 
}

这种方式适合我。

答案 9 :(得分:0)

我建议您将textview作为活动布局的一部分。或者,您可以将textview作为separete片段。在这里查看我的question。它与你的相似,但方向相反。这是我在项目中使用的精简版代码。解释是沿着代码进行的。

活动类

public class MainActivity extends ActionBarActivity {
PlaceFragment fragment;
TextView fragmentsTextView;

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

@Override
protected void onStart() {
    // TODO Auto-generated method stub
    super.onStart();
    Bundle bundle = new Bundle();
    bundle.putString("score", "1000");
    fragment = PlaceFragment.newInstance(bundle);
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.replace(R.id.container, fragment);
    ft.addToBackStack(null);
    ft.commit();
    // method 1
    // fragment is added some ways to access views
    // get the reference of fragment's textview
    if (fragment.getTextView() != null) {
        fragmentsTextView = fragment.getTextView();
    }
    // method 2
    // using static method dont use in production code
    // PlaceFragment.textViewInFragment.setText("2000");

    // method 3
    // let the fragment handle update its own text this is the recommended
    // way wait until fragment transaction is complete before calling
    //fragment.updateText("2000");

}

}

片段类:

public class PlaceFragment extends Fragment {
public TextView textViewInFragment;// to access via object.field same to
                                    // string.length

// public static TextView textViewInFragment;//to access via
// PlaceFragment.textView dont try this in production code
public PlaceFragment() {
}

public static PlaceFragment newInstance(Bundle bundle) {
    PlaceFragment fragment = new PlaceFragment();
    fragment.setArguments(bundle);
    return fragment;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    View view = inflater.inflate(R.layout.fragment_place, container, false);
    textViewInFragment = (TextView) view
            .findViewById(R.id.textViewInFragment);
    return view;
}

@Override
public void onStart() {
    // TODO Auto-generated method stub
    super.onStart();
    if (getArguments() != null) {
        textViewInFragment.setText(getArguments().getString("score"));

    }
}

public TextView getTextView() {
    if (textViewInFragment != null) {
        return textViewInFragment;// returns instance of inflated textview
    }
    return null;// return null and check null
}

public void updateText(String text) {
    textViewInFragment.setText(text);// this is recommended way to alter
                                        // view property of fragment in
                                        // activity
}

}

从活动到片段的沟通是直截了当的。这是因为活动包含片段。保留片段对象并通过setter和getter或其中的公共字段访问其属性。但是从片段到活动的通信需要一个接口。

答案 10 :(得分:0)

只需在片段中将TextView声明为public,然后通过片段的onCreateView()中的findViewById()对其进行初始化。现在,通过使用您在活动中添加的Fragment对象,您可以访问TextView。

答案 11 :(得分:0)

为什么你不能直接从FragmentPagerAdapter

访问它
SubAccountFragment subAccountFragment = (SubAccountFragment) mSectionsPagerAdapter.getItem(1);
subAccountFragment.requestConnectPressed(view);

这是完整的例子:

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.Locale;


public class TabsActivity extends ActionBarActivity implements ActionBar.TabListener {

    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link FragmentPagerAdapter} derivative, which will keep every
     * loaded fragment in memory. If this becomes too memory intensive, it
     * may be best to switch to a
     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */
    SectionsPagerAdapter mSectionsPagerAdapter;

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    ViewPager mViewPager;

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

        // Set up the action bar.
        final ActionBar actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        // When swiping between different sections, select the corresponding
        // tab. We can also use ActionBar.Tab#select() to do this if we have
        // a reference to the Tab.
        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                actionBar.setSelectedNavigationItem(position);
            }
        });

        // For each of the sections in the app, add a tab to the action bar.
        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            // Create a tab with text corresponding to the page title defined by
            // the adapter. Also specify this Activity object, which implements
            // the TabListener interface, as the callback (listener) for when
            // this tab is selected.
            ActionBar.Tab tab = actionBar.newTab();

            View tabView = this.getLayoutInflater().inflate(R.layout.activity_tab, null);

            ImageView icon = (ImageView) tabView.findViewById(R.id.tab_icon);
            icon.setImageDrawable(getResources().getDrawable(mSectionsPagerAdapter.getPageIcon(i)));

            TextView title = (TextView) tabView.findViewById(R.id.tab_title);
            title.setText(mSectionsPagerAdapter.getPageTitle(i));

            tab.setCustomView(tabView);

            tab.setTabListener(this);

            actionBar.addTab(tab);
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_tabs, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_logout) {
            finish();
            gotoLogin();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
        // When the given tab is selected, switch to the corresponding page in
        // the ViewPager.
        mViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public ProfileFragment profileFragment;
        public SubAccountFragment subAccountFragment;
        public ChatFragment chatFragment;

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
            profileFragment = new ProfileFragment();
            subAccountFragment = new SubAccountFragment();
            chatFragment = new ChatFragment();
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return profileFragment;
                case 1:
                    return subAccountFragment;
                case 2:
                    return chatFragment;
            }
            return null;
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Locale l = Locale.getDefault();
            switch (position) {
                case 0:
                    return getString(R.string.title_section1).toUpperCase(l);
                case 1:
                    return getString(R.string.title_section2).toUpperCase(l);
                case 2:
                    return getString(R.string.title_section3).toUpperCase(l);
            }
            return null;
        }

        public int getPageIcon(int position) {
            switch (position) {
                case 0:
                    return R.drawable.tab_icon_0;
                case 1:
                    return R.drawable.tab_icon_1;
                case 2:
                    return R.drawable.tab_icon_2;
            }
            return 0;
        }
    }


    public void gotoLogin() {
        Intent intent = new Intent(this, LoginActivity.class);
        this.startActivity(intent);
    }

    public void requestConnectPressed(View view){
        SubAccountFragment subAccountFragment = (SubAccountFragment) mSectionsPagerAdapter.getItem(1);
        subAccountFragment.requestConnectPressed(view);
    }
}

答案 12 :(得分:0)

您无法访问父Fragment中的Activity元素,但您可以通过以下方式将值传递到Fragment

onNavigationDrawerItemSelected MyActivity方法中执行以下操作

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;
}

并在MyFragment&#39; onCreateView()方法

@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;
}

全部,我希望这会对你有所帮助。如果没有,请告诉我。

答案 13 :(得分:0)

如果视图已经在屏幕上膨胀(例如可见),那么您可以正常使用活动中的findViewById(R.id.yourTextView),它将返回文本视图的句柄,如果视图是没找到。

答案 14 :(得分:0)

返回null因为TextViewFragment的元素,而不是Activity

请注意,使用Fragment的想法是将模块封装在Fragment中,这意味着Activity不应该直接访问它的属性。考虑将您的逻辑移到TextView

中获得Fragment引用的位置

答案 15 :(得分:0)

得分textView位于片段的布局中,它不在MyActivity的布局中,即R.layout.activity_home。因此,一旦您膨胀相应的布局文件,您就可以在该片段中找到得分textview。

答案 16 :(得分:0)

我只是使用方法从父级活动访问片段视图,因为我们创建了一个新的片段类对象来插入片段。所以我喜欢这样。

class BrowserFragment : Fragment(), Serializable {
    private lateinit var webView: NestedScrollWebView
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        webView = view.findViewById(R.id.web_view)
    }
    fun getWebView(): WebView {
        return webView
    }
}

MainActivity

val browserFragment = BrowserFragment()
val fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.add(R.id.browser_fragment_placeholder, browserFragment)
fragmentTransaction.commit()

val webView = browserFragment.getWebView()