How to access Fragment's child views inside fragment's parent Activity?

AndroidAndroid Layout

Android Problem Overview


I have a supported fragment activity which will load diff fragments. The fragment has some textView with id = "score" and I want to get its handle but findViewById for score's textView returns null. Why so?


textView is placed in fragment

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	
    }

}

Android Solutions


Solution 1 - Android

###Note: Directly accessing fragment's views outside fragment is not a good idea. You should use fragment callback interfaces to handle such cases and avoid bugs. The following way works but it is not recommended as it is not a good practice.


If you want to access the TextView of Fragment inside its parent Activity then you should define a method inside your Fragment class like this:

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

	
}

Now you can use this inside your Activity like this:

myFragment.setTextViewText("foo");

here myFragment is of type MyFragment.

If you want to access the whole TextView then you can define a method like this inside MyFragment.java:

public TextView getTextView1(){
	return mTextView;
}

By this you can access the TextView itself.

Hope this Helps. :)

Solution 2 - Android

It is possible with following way:

Keep reference of inflated view in the Fragment like this :

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

}

Create a function in the Activity, like this:

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

Its purpose is to keep reference of current fragment. Whenever you wanna switch fragment, you call above function, like this (from fragment):

activity.switchContent( new MyFragment_2());

Now you've current fragment reference. So you can directly access Fragment's views in Activity like this: this.fragment.view

Solution 3 - Android

You have no need of reference of Fragment view to get its components in Activity. As you can directly access layout components of a Fragment in parent Activity.

Simply you can access any component by this

findViewById(R.id.child_of_fragment_layout);  

Solution 4 - Android

You can access with getView method of Fragment class.

For example You have a TextView in Your MyFragment with id of "text_view"
In Your Activity make a Fragment of Yours:

MyFragment myFragment = new MyFragment();

And when You need a child just call getView and then find Your childView.

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

Note: if you want the root view of your fragment, then myFragment.getView(); is simply enough.

Solution 5 - Android

In order to access the TextView or Button or whatever in your fragment you need to do the following:

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

Once that is done in your MainActivity or any other where you want to access your TextView from your Fragment you should make sure to set up the fragment in your OnCreate() method other ways it will most likely throw nullPointer. So your activity where you want to change the TextView should look smth like this:

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");

        }
    });
}

Hope this helps :)

Solution 6 - Android

Just put in fragment instead of putting in activity:

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

Solution 7 - Android

Only doing this:

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

Solution 8 - Android

If your TextView placed inside Fragment that case you cannot access TextView inside your Fragment Parent Activity you can set the interface for intercommunication between Fragment and Activity and send Data when you click on TextView or anyother thing which you want to happend

Solution 9 - Android

You can't access Fragment element in Parent Activity, But You can pass values to your Fragment by following way.

in your onNavigationDrawerItemSelected method of MyActivity do the following

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

And in MyFragment class create a method called newInstance like following

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

And in MyFragment's onCreateView() method

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

That's All, I hope this will help you. If not please let me know.

Solution 10 - Android

The score textView is in the layout of fragment, it's not in the layout of the MyActivity, i.e. R.layout.activity_home. So you could find the score textview in that fragment once you inflate the corresponding layout file.

Solution 11 - Android

It returns null cause the TextView is an element of the Fragment, not the Activity.

Please note that the idea of using Fragment is to encapsulate a module inside the Fragment, which means the Activity should not have direct access to it's properties. Consider moving your logic where you get the TextView reference inside the Fragment

Solution 12 - Android

Simply declare TextView as public in fragment, initialize it by findViewById() in fragment's onCreateView(). Now by using the Fragment Object which you added in activity you can access TextView.

Solution 13 - Android

You need to call method findViewById from your fragment view.

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

This way works for me.

Solution 14 - Android

I suggest you to make the textview part of your activity layout. Alternately you can have the textview as a separete fragment. Have a look at my question here. Its similar to yours but in reverse direction. Here's a stripped down version of code I used in my project. The explanation are along the code.

The Activity Class

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");

}

}

The fragment class:

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
}

}

Communication from activity to fragment is straight forward. This is because activity contains fragment. Keep the fragment object and access its property via setters and getters or the public fields inside it. But communication from fragment to activity requires an interface.

Solution 15 - Android

why you don't access it directly from your FragmentPagerAdapter,

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

and here is the full example:

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

Solution 16 - Android

If the view is already inflated (e.g. visible) on the screen then you can just use findViewById(R.id.yourTextView) within the activity as normal and it will return the handle to the text view or null if the view was not found.

Solution 17 - Android

I just use methods to access fragment views from parent activity, because we create a new fragment class object to insert the fragment. So I do like this.

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

In MainActivity

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

val webView = browserFragment.getWebView()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser93796View Question on Stackoverflow
Solution 1 - AndroidSMRView Answer on Stackoverflow
Solution 2 - AndroidArsalan MehmoodView Answer on Stackoverflow
Solution 3 - AndroidAli ImranView Answer on Stackoverflow
Solution 4 - AndroidSaman SattariView Answer on Stackoverflow
Solution 5 - AndroidF.A. BoticView Answer on Stackoverflow
Solution 6 - AndroidZoranView Answer on Stackoverflow
Solution 7 - AndroidLalit kumarView Answer on Stackoverflow
Solution 8 - AndroidRamkailashView Answer on Stackoverflow
Solution 9 - AndroidGunaseelanView Answer on Stackoverflow
Solution 10 - AndroidSherlockView Answer on Stackoverflow
Solution 11 - AndroidChristopher FranciscoView Answer on Stackoverflow
Solution 12 - AndroidHimanshu GuptaView Answer on Stackoverflow
Solution 13 - AndroidYoricView Answer on Stackoverflow
Solution 14 - AndroidIllegal ArgumentView Answer on Stackoverflow
Solution 15 - AndroidFareed AlnamroutiView Answer on Stackoverflow
Solution 16 - AndroidshamView Answer on Stackoverflow
Solution 17 - AndroidJeevaView Answer on Stackoverflow