如何访问fragment的父Activity中的Fragment的子视图?
我有一个支持的片段活动,将加载diff片段。 该片段有一些id = "score"
findViewById
,我想得到它的句柄,但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 } }
注意:
直接访问片段外的片段是不是一个好主意。 你应该使用片段callback接口来处理这种情况,并避免错误。 以下方法可行,但不推荐,因为这不是一个好的做法。
如果你想在其父Activity
访问Fragment
的TextView
,那么你应该在你的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
types的。
如果你想访问整个TextView
那么你可以在MyFragment.java
定义一个像这样的方法:
public TextView getTextView1(){ return mTextView; }
通过这个你可以访问TextView
本身。
希望这可以帮助。 🙂
可以用以下方法:
请继续参照片段中的膨胀视图:
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中创build一个函数,如下所示:
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
你不需要引用片段视图来获取它在Activity中的组件。 因为您可以直接访问父活动中 Fragment的布局组件。
只要你可以通过这个访问任何组件
findViewById(R.id.child_of_fragment_layout);
您可以使用Fragment类的getView方法访问。
例如,您的MyFragment中有一个TextView,其ID为“text_view”
在你的活动中做一个你的片段:
MyFragment myFragment = new MyFragment();
而当你需要一个孩子只需调用getView然后find你的childView。
View view = myFragment.getView(); if (view !=null) { view.findViewById(R.id.text_view).setText("Child Accessed :D"); }
如果你的TextView放在Fragment中,那么你不能在你的Fragment Parent Activity中访问TextView,你可以设置Fragment和Activity之间的相互通信接口,当你点击TextView或者其他想要发生的事情时发送数据
只有这样做:
((Your_Activity) this.getActivity()).YouyActivityElements;
只是放在片段而不是放在活动中:
@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; }
得分textView是在片段的布局,它不是在MyActivity的布局,即R.layout.activity_home。 所以一旦你膨胀相应的布局文件,你可以在该片段中find分数textview。
它返回null
因为TextView
是Fragment
一个元素,而不是Activity
。
请注意,使用Fragment
的想法是将一个模块封装在Fragment
,这意味着Activity
不应直接访问它的属性。 考虑移动你的逻辑,在Fragment
获得TextView
引用
您不能访问父Activity
Fragment
元素,但可以按照以下方式将值传递给您的Fragment
。
在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
类中创build一个名为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
的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; }
这就是全部,我希望这会帮助你。 如果不是,请让我知道。
只需将TextView声明为公共片段,通过片段的onCreateView()中的findViewById()对其进行初始化。 现在通过使用活动中添加的Fragment对象,您可以访问TextView。
您需要从片段视图调用方法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); }
这种方式适合我。
我build议你将textview作为你的活动布局的一部分。 或者,您可以将textview作为分隔符片段。 看看我的问题在这里。 它与你的类似,但方向相反。 这里是我在我的项目中使用的代码的简化版本。 解释是沿着代码。
活动类
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或其内部的公共字段来访问它的属性。 但是从片段到活动的通信需要一个接口。
为什么你不直接从你的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); } }
如果视图已经在屏幕上膨胀(例如可见),那么你可以在活动中使用findViewById(R.id.yourTextView),正常情况下它将把句柄返回到文本视图,如果没有find视图,则返回null。