'getSupportFragmentManager getFragment without tag or id
I'm developing an Android 3.1 Tablet application.
I'm using ViewPager and fragments on one activity. My problem is that I don't know how to set an ID or Tag to fragments.
Activity
public class FillEReportFragmentActivity extends FragmentActivity
{
...
/**
* View Pager to manage form parts.
*/
private ViewPager mViewPager;
/**
* Page Adapter to handle fragments.
*/
private FillEReportFragmentPagerAdapter mPagerAdapter;
@Override
protected void onCreate(Bundle savedInstance)
{
Log.v("FillEReportFragmentActivity", "onCreate");
super.onCreate(savedInstance);
setContentView(R.layout.fill_ereport_paged);
// Recoge los argumentos que le llegan de la actividad padre.
Bundle extras = getIntent().getExtras();
if (extras != null)
{
qapId = extras.getLong(BundleKeys.qapIdKey);
orderId = extras.getLong(BundleKeys.orderIdKey);
eReportId = extras.getLong(BundleKeys.eReportIdKey);
}
// Cargamos el E-Report o creamos uno nuevo. Además se recuperan los
// artículos de la orden actual.
LoadEReportAsyncTask task = new LoadEReportAsyncTask(this);
task.execute(Long.toString(this.qapId));
// Establezco los fragmentos (o partes del form) que se mostrarán en el
// View Pager.
mViewPager = (ViewPager)findViewById(R.id.pager);
mPagerAdapter = new FillEReportFragmentPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mPagerAdapter);
// Muestro en la parte inferior unos círculos para indicar donde me
// encuentro dentro del E-Report.
CirclePageIndicator mIndicator = (CirclePageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mViewPager);
// Creo unos tabs para poder navegar más facilmente a través de las
// partes del E-Report.
TabPageIndicator titleIndicator = (TabPageIndicator)findViewById(R.id.tabIndicator);
titleIndicator.setViewPager(mViewPager);
}
...
}
FragmentPagerAdapter
public class FillEReportFragmentPagerAdapter extends FragmentPagerAdapter
{
private static final String[] TITLES = new String[] {
"Factory",
"Items"
};
public FillEReportFragmentPagerAdapter(FragmentManager fm)
{
super(fm);
// TODO Auto-generated constructor stub
}
@Override
public Fragment getItem(int index)
{
switch (index)
{
case 0:
return FactoryInfoFragment.newInstance();
case 1:
return ItemsFragment.newInstance();
default:
return null;
}
}
@Override
public int getCount()
{
return 2; // TODO: Este número hay que cambiarlo porque serán más.
}
public String getPageTitle(int position)
{
return TITLES[position];
}
}
res/values/ids.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="frag_general_info_factory"/>
<item type="id" name="frag_general_info_items"/>
</resources>
FactoryInfoFragment
public class FactoryInfoFragment extends Fragment
{
public static FactoryInfoFragment newInstance()
{
FactoryInfoFragment frag = new FactoryInfoFragment();
return frag;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
Log.v("FactoryInfoFragment", "onCreateView");
View v = inflater.inflate(R.layout.frag_general_info_factory, container, false);
view.setId(R.id.frag_general_info_factory);
return v;
}
}
frag_general_info_factory.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_margin="10dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:shrinkColumns="*"
android:stretchColumns="*">
<TableRow
android:weightSum="1"> <!-- 0 -->
<TextView
android:id="@+id/txtGenInfo"
android:layout_span="8"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/layout_title_general_information"
android:textAppearance="?android:attr/textAppearanceLarge" />
</TableRow>
...
</TableLayout>
Here I want to get an specific fragment
private class LoadEReportAsyncTask extends AsyncTask<String, Void, Boolean>
{
private Context mContext;
private ProgressDialog loadingDialog;
private EReport eReport;
private QAP qap;
public LoadEReportAsyncTask(Context context)
{
Log.v("LoadEReportAsyncTask", "constructor");
eReport = null;
qap = null;
this.mContext = context;
loadingDialog = new ProgressDialog(mContext);
loadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
loadingDialog.setMessage(getString(R.string.msg_loading_ereport));
loadingDialog.setCancelable(false);
loadingDialog.show();
}
@Override
protected Boolean doInBackground(String... params)
{
Log.v("LoadEReportAsyncTask", "doInBackground");
...
}
protected void onPostExecute(Boolean result)
{
Log.v("LoadEReportAsyncTask", "onPostExecute");
FillEReportFragmentActivity parentActivity = (FillEReportFragmentActivity) mContext;
if (result)
{
FactoryInfoFragment factFragment = (FactoryInfoFragment)getSupportFragmentManager().findFragmentById(R.id.frag_general_info_factory);
factFragment.fillEReport(eReport, qap);
Toast.makeText(getApplicationContext(), getString(R.string.msg_ereport_got_correct), Toast.LENGTH_SHORT).show();
ItemsFragment fragment = (ItemsFragment)getSupportFragmentManager().findFragmentById(R.id.frag_general_info_items);
fragment.setUpArticles(orderArticles);
}
else
{
Toast.makeText(getApplicationContext(), getString(R.string.msg_ereport_problem), Toast.LENGTH_LONG).show();
}
loadingDialog.dismiss();
}
}
Here:(FactoryInfoFragment)getSupportFragmentManager().findFragmentById(R.id.frag_general_info_factory);
I use R.id.frag_general_info_factory
to get that fragment reference but I get a null.
How can I set a Tag or an Id to FactoryInfoFragment
?
Solution 1:[1]
I haven't tried it, but I don't know if findFragmentById()
will work properly in this case, given that there is actually more than one fragment associated with the ViewPager container.
If you look at the source code of the FragmentPagerAdapter
you can see how it is using tags internally. Then perhaps you override instantiateItem()
in your custom pager adapter, copying in the code from FragmentPagerAdapter
and adjusting it to use tags that you can also use elsewhere in your code to retrieve the fragments yourself.
For example, if your PagerAdapter implementation could be specific to this one problem, you could do something as simple as this:
private String getTag(int position) {
switch (position) {
case 0:
return FactoryInfoFragment.class.toString();
case 1:
return ItemsFragment.class.toString();
default:
return "unknown:" + position;
}
Solution 2:[2]
In this case it looks like findFragmentById()
and findFragmentByTag()
won't do the job so what I would do is to store all of your Fragments
into an ArrayList<Fragment>
so you can access them from both your Adapter
and the AsyncTask
.
Solution 3:[3]
You can get a Fragment by using the id
of the View the ViewPager adds it to:
getFragmentManager().findFragmentById(R.id.frameWhichFragmentHasBeenAddedTo);
Your problem is finding this id. I've run through the source code for ViewPager
and it doesn't jump out, if anything I would suggest it uses itself (a ViewGroup
) so the id you should use in this instance would be R.id.pager
;
NB
You may also want to be very careful when mixing android.support.v4.app.Fragment
and android.app.Fragment
- It means the difference between using the functionality in the support library or in the Honeycomb+ API.
i.e, if you use android.support.v4.app.Fragment
:
getSupportFragmentManager();
else if you use android.app.Fragment
:
getFragmentManager();
Solution 4:[4]
You can try to override
public Object instantiateItem (ViewGroup container, int position)
in your FragmentPagerAdapter
to save or set the id of that container ViewGroup
and then call super
.
Then you can use that saved id on getSupportFragmentManager().findFragmentById()
to retrieve the fragment.
Let me know if that works!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Scott W |
Solution 2 | monchote |
Solution 3 | |
Solution 4 |