I would like to access methods (or global variables) of a fragment created for an action bar but unfortunately I cannot find any ID for it and cannot access it. Does someone know how to do this?
trainingFragment.somemethode(aParameter) does not work.
NB: For information I didn't touched the Manifest File, I don't know if I should have. And I'm NOT using Android.Support.V4.App or Android.Support.V7.AppCompat, I'm simply using Android.App. And the target Framework is Android 4.4 (Kit Kat).
Here is the code:
Main Activity:
public class MainActivity : Activity
{
static readonly string Tag = "ActionBarTabsSupport";
Fragment[] _fragments;
// Layout Views
public TextView title;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.mainactivity);
ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
SetContentView(Resource.Layout.mainactivity);
Fragment trainingFragment = new TrainingFragment ();
Fragment bluetoothChatFragment = new TestFragment();
_fragments = new Fragment[]
{
trainingFragment,
bluetoothChatFragment
};
AddTabToActionBar(Resource.String.training_label, Resource.Drawable.ic_action_speakers);
AddTabToActionBar(Resource.String.btchat_label, Resource.Drawable.ic_action_sessions);}
void AddTabToActionBar(int labelResourceId, int iconResourceId)
{
ActionBar.Tab tab = ActionBar.NewTab()
.SetText(labelResourceId)
.SetIcon(iconResourceId);
tab.TabSelected += TabOnTabSelected;
ActionBar.AddTab(tab);
}
void TabOnTabSelected(object sender, ActionBar.TabEventArgs tabEventArgs)
{
ActionBar.Tab tab = (ActionBar.Tab)sender;
Log.Debug(Tag, "The tab {0} has been selected.", tab.Text);
Fragment frag = _fragments[tab.Position];
tabEventArgs.FragmentTransaction.Replace(Resource.Id.frameLayout1, frag);
}
One of the fragments:
public class TrainingFragment : Fragment
{
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.Inflate(Resource.Layout.training_layout, null);
return view;
}
public void somemethod(int aParameter)
{
//Do something
}
}
Thanks in advance
try that
void TabOnTabSelected(object sender, ActionBar.TabEventArgs tabEventArgs)
{
ActionBar.Tab tab = (ActionBar.Tab)sender;
Log.Debug(Tag, "The tab {0} has been selected.", tab.Text);
Fragment frag = _fragments[tab.Position];
if(frag instanceof TrainingFragment ){
((TrainingFragment)frag).somemethod(0);
}
tabEventArgs.FragmentTransaction.Replace(Resource.Id.frameLayout1, frag);
}
Related
I have a main activity which contains the action bar with 3 menu buttons in it.
I then have a fragment within this main activity which has a list.
I would like to be able to refresh the list in the fragment from the main activity, when one of the menu buttons is clicked, or preferably just removed all the rows from the list.
Any help is appreciated.
Thanks.
public class Favourite extends SherlockFragmentActivity {
ActionBar actionBar;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.favourite);
actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
BitmapDrawable bg = (BitmapDrawable)getResources().getDrawable(R.drawable.actionbar_bg);
bg.setTileModeX(TileMode.REPEAT);
getSupportActionBar().setBackgroundDrawable(bg);
getSupportActionBar().setIcon(R.drawable.favourite_title);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tabAll = actionBar.newTab();
ActionBar.Tab tabfavs = actionBar.newTab();
ActionBar.Tab tabhist = actionBar.newTab();
tabAll.setText("all");
tabfavs.setText("favs");
tabhist.setText("hist");
tabAll.setTabListener(new MyTabListener());
tabfavs.setTabListener(new MyTabListener());
tabhist.setTabListener(new MyTabListener());
actionBar.addTab(tabAll);
actionBar.addTab(tabfavs);
actionBar.addTab(tabhist);
try{
}
catch(Exception e)
{
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.actionbar_itemlist_favourite, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.history:
break;
case R.id.favourite:
Intent favAct = new Intent(this, Favourite.class);
startActivity(favAct);
break;
case R.id.delete:
///I WANT TO BE ABLE TO REFRESH FRAGMENTLIST FROM HERE
}
return true;
}
}
class MyTabListener implements ActionBar.TabListener {
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if(tab.getPosition()==0)
{
FavouriteAllWords frag = new FavouriteAllWords();
ft.replace(android.R.id.content, frag);
}
else if(tab.getPosition()==1)
{
FavouriteFavWords frag = new FavouriteFavWords();
ft.replace(android.R.id.content, frag);
}
else if(tab.getPosition()==2)
{
FavouriteHistWords frag = new FavouriteHistWords();
ft.replace(android.R.id.content, frag);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
}
////////////////////MY LIST FRAGMENT CLASS
public class FavouriteAllWords extends ListFragment {
ArrayAdapter<String> adapter;
List<String> stringOfFavWords;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle saved)
{
adapter = new ArrayAdapter<String>(
inflater.getContext(), R.layout.row, stringOfFavWords);
setListAdapter(adapter);
return super.onCreateView(inflater, group, saved);
}
#Override
public void onActivityCreated (Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
}
}
You can easily achieve this using INTERFACE
MainActivity.java
public class MainActivity extends Activity {
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
private FragmentRefreshListener fragmentRefreshListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button)findViewById(R.id.btnRefreshFragment);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(getFragmentRefreshListener()!=null){
getFragmentRefreshListener().onRefresh();
}
}
});
}
public interface FragmentRefreshListener{
void onRefresh();
}
}
MyFragment.java
public class MyFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = null; // some view
/// Your Code
((MainActivity)getActivity()).setFragmentRefreshListener(new MainActivity.FragmentRefreshListener() {
#Override
public void onRefresh() {
// Refresh Your Fragment
}
});
return v;
}
}
Just make your update/refresh method public and call it from your Activity.
OR
Use LocalBroadcastManager or EventBus to send event from your Activity, and by subscribing to this event in a Fragment - react to it and call refresh/update method.
Your activity can call methods in the fragment by acquiring a reference to the Fragment.
(1) Provide a tag when you add your fragment.
transaction.add(R.id.fragment_container, myFragment, "myfragmentTag");
(2) In your hosting activity you can find the fragment and have access to it's methods.
FragmentManager fm = getSupportFragmentManager();
myFragment f = (myFragment) fm.findFragmentByTag("myfragmentTag");
f.refreshAdapter()
(3) refreshAdapter() could now call adapter.notifyDataSetChanged().
This is one of the recommended ways to communicate up to a fragment.
The interface implementation is mainly for communicating back to the activity.
Biraj Zalavadia's answer is 100% right, you will call nay fragment methods from using interface....
this interface methods is running without error...
use this in MainActivity above oncreate
private FragmentRefreshListener fragmentRefreshListener;
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(
FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
inside of Activity
private void refreshcall(String result2) {
// TODO Auto-generated method stub
if (getFragmentRefreshListener() != null) {
getFragmentRefreshListener().onRefresh(result2);
}
}
and put this in needed Fragment
private FragmentRefreshListener fragmentRefreshListener;
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(
FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
Communicating with Other Fragments
http://developer.android.com/training/basics/fragments/communicating.html
This can also be used to communicate between an Activity and a Fragment.
When you click on ActionBar any Button then call interface to refresh the ListFragment. Because in java interface is used for inter-communication.
In Kotlin
Get the list of Support Fragment from the activity and check Instance and then call fragment function
val fragments = supportFragmentManager.fragments
for (fragment in fragments) {
if (fragment is HomeCategoriesFragment) {
fragment.updateAdapter() // Define function in Fragment
}
}
I'm using Xamarin Studio and developing a small test project for Android.
I have an Activity with three Tabs on it, each Tab have a different Fragment. So far I got the hang of how to add Tabs and event handlers.
But when I rotate the screen, the default Tab I set is selected which causes the Fragment assigned to that Tab to be displayed.
Another problem I face is that when I change Tabs, I want to preserve the state of the previous Tab, so when I select it again it won't be rendered again. For example, one of my Tabs is a GridView which loads remote images in its cells. When I switch Tabs I don't want for the images to be loaded again.
My main Activity looks like this:
public class MainActivity : Activity
{
private ActionBar.Tab UploadImageTab;
private ActionBar.Tab ImgurTwitterTab;
private ActionBar.Tab RecentImagesTab;
private int selected_tab;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
if (bundle != null) {
selected_tab = bundle.GetInt ("selected_tab", 0);
Log.Debug (GetType ().FullName, "selected tab was " + selected_tab);
}
if (ActionBar != null) {
InitializeActionBar ();
}
SetContentView (Resource.Layout.Main);
}
protected override void OnSaveInstanceState (Bundle outState)
{
Log.Debug (GetType ().FullName, "Saving state tab selected " + selected_tab);
outState.PutInt ("selected_tab", selected_tab);
base.OnSaveInstanceState (outState);
}
protected void InitializeActionBar(){
ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
AddTab (UploadImageTab, Resources.GetString (Resource.String.upload_image), Resource.Drawable.ic_upload, new UploadImageFragment(), 1);
AddTab (ImgurTwitterTab, Resources.GetString (Resource.String.imgur_twitter), Resource.Drawable.ic_com, new ImgurOnTwitterFragment(), 2);
AddTab (RecentImagesTab, Resources.GetString (Resource.String.recent_images), Resource.Drawable.ic_gallery, new RecentImagesFragment(), 3);
if (selected_tab == 0) {
Log.Debug (GetType ().FullName, "No value found");
ActionBar.SelectTab (UploadImageTab);
} else {
if (selected_tab == 1) {
Log.Debug (GetType ().FullName, "Selecting tab 1");
ActionBar.SelectTab (UploadImageTab);
} else if (selected_tab == 2) {
Log.Debug (GetType ().FullName, "Selecting tab 2");
ActionBar.SelectTab (ImgurTwitterTab);
}else if(selected_tab == 3){
Log.Debug (GetType ().FullName, "Selecting tab 3");
ActionBar.SelectTab (RecentImagesTab);
}
}
}
protected void AddTab(ActionBar.Tab tab, string tabText, int iconResourceId, Fragment fragment, int index){
tab = ActionBar.NewTab ();
tab.SetText (tabText);
tab.SetIcon (iconResourceId);
tab.TabSelected += delegate(object sender, ActionBar.TabEventArgs e) {
e.FragmentTransaction.Replace(Resource.Id.fragmentContainer, fragment);
if(ActionBar.SelectedTab.Position == 0){
selected_tab = 1;
}else if(ActionBar.SelectedTab.Position == 1){
selected_tab = 2;
}else if(ActionBar.SelectedTab.Position == 2){
selected_tab = 3;
}
Log.Debug(GetType().FullName, "selection is " + selected_tab);
};
ActionBar.AddTab (tab);
}
}
For starters I tried to save the selected Tab. But when I rotate the device, for some reason the TabSelected event on the first Tab (UploadImageTab in this case) is fired, causing the saved value I had to be overwritten.
On the example for my Fragment with a GridView, my code is like this:
public class RecentImagesFragment : Fragment
{
private GridView collectionView;
public List<Photo> photos;
public static float DENSITY;
public override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
}
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Console.WriteLine ("is this called every time I switch tabs");
base.OnCreateView (inflater, container, savedInstanceState);
var view = inflater.Inflate (Resource.Layout.RecentImagesTab, container, false);
DENSITY = Activity.Resources.DisplayMetrics.Density;
collectionView = view.FindViewById<GridView> (Resource.Id.collectionView);
collectionView.ItemClick += ItemClick;
photos = new List<Photo> ();
MakeRequest ();
return view;
}
public void ItemClick(object sender, AdapterView.ItemClickEventArgs args){
Console.WriteLine ("photo selected " + photos [args.Position].OriginalUrl);
Intent intent = new Intent (this.Activity, typeof(PhotoDetail));
intent.PutExtra ("url", photos [args.Position].OriginalUrl);
StartActivity (intent);
}
public void MakeRequest(){
var request = (HttpWebRequest)WebRequest.Create("https://api.imgur.com/3/gallery/hot/viral/0.json");
request.Headers.Add ("Authorization", "Client-ID " + "XXXXXXXXXXX");
request.Method = "GET";
Task<WebResponse> task = Task.Factory.FromAsync (
request.BeginGetResponse,
asyncResult => request.EndGetResponse (asyncResult),
(object)null);
task.ContinueWith (t => ReadStreamFromResponse (t.Result));
}
private void ReadStreamFromResponse(WebResponse response){
using (Stream responseStream = response.GetResponseStream ()) {
using (StreamReader sr = new StreamReader (responseStream)) {
string content = sr.ReadToEnd ();
Console.WriteLine (content);
try{
var json = JsonObject.Parse (content);
var array = json ["data"];
foreach (JsonObject o in array) {
string url = o ["link"];
bool isAlbum = o ["is_album"];
if (!isAlbum) {
var short_url = url.Insert (url.Length - 4, "s");
photos.Add (new Photo{ OriginalUrl = url, SmallThumbUrl = short_url });
}
}
} catch(Exception ex){
Console.WriteLine ("Error: " + ex.Message);
}
if (photos.Count > 0) {
Activity.RunOnUiThread (() => {
collectionView.Adapter = new ImageAdapter (this.Activity, photos);
});
}
}
}
}
}
When the view is created I make a HTTP request to Imgur for the latest images url, then I assign the List of Photo objects I create to my ImageAdapter that will download/render them. But these objects are lost when I switch Tabs.
How can I make sure I save the state of my Fragments? And how do I save the state of my Fragment's GridView adapter?
I was able to find an basic example here which helped me dealing with the situation I'm facing. I made the following changes to my code (comments will explain the functionality):
MainActivity.cs
public class MainActivity : Activity
{
private ActionBar.Tab UploadImageTab;
private ActionBar.Tab ImgurTwitterTab;
private ActionBar.Tab RecentImagesTab;
private int selected_tab;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// Initialize Action Bar
InitializeActionBar ();
// Check if bundle is different from null, then load saved state and set selected tab
if (bundle != null) {
selected_tab = bundle.GetInt ("selected_tab", 0);
ActionBar.SetSelectedNavigationItem (selected_tab);
Log.Debug (GetType ().FullName, "selected tab was " + selected_tab);
}
}
// Save the selected tab
protected override void OnSaveInstanceState (Bundle outState)
{
Log.Debug (GetType ().FullName, "Saving state tab selected " + this.ActionBar.SelectedNavigationIndex);
outState.PutInt ("selected_tab", this.ActionBar.SelectedNavigationIndex);
base.OnSaveInstanceState (outState);
}
// Initialize Action Bar
protected void InitializeActionBar(){
ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
// First big change
// Pass to AddTab method a tab instace, tab text, icon and a tag
AddTab<UploadImageFragment> (UploadImageTab, Resources.GetString (Resource.String.upload_image), Resource.Drawable.ic_upload, "upload");
AddTab<ImgurOnTwitterFragment> (ImgurTwitterTab, Resources.GetString (Resource.String.imgur_twitter), Resource.Drawable.ic_com, "tweets");
AddTab<RecentImagesFragment> (RecentImagesTab, Resources.GetString (Resource.String.recent_images), Resource.Drawable.ic_gallery, "recent");
}
// AddTab now handles generic types that inherit from Fragment
protected void AddTab<T> (ActionBar.Tab tab, string tabText, int iconResourceId, string tag) where T : Fragment{
tab = ActionBar.NewTab ();
tab.SetText (tabText);
tab.SetIcon (iconResourceId);
// tag will help us id this tab
tab.SetTag (tag);
// Get instance of Fragment if it exists
T existing = (T)FragmentManager.FindFragmentByTag (tag);
// Set listener for tab
tab.SetTabListener(new ActivityTabListener<T>(this, tag, existing));
ActionBar.AddTab (tab);
}
}
ActivityTabListener.cs
// Tab listener for generic type that inherits from Fragment
public class ActivityTabListener<T> : Java.Lang.Object, ActionBar.ITabListener where T : Fragment{
// Instance of current context
private Activity context;
// Reference to fragment to be displayed
private Fragment fragment;
// Name of Fragment class
private string fragmentName;
// Tag for tab
private string tag;
// Base constructor requires an Activity instance
public ActivityTabListener(Activity context){
this.context = context;
this.fragmentName = typeof(T).Namespace.ToLower() + "." + typeof(T).Name;
}
// Second constructor receives context, tag and existing fragment instance if available
public ActivityTabListener(Activity context, string tag, T existingFragment = null) : this(context){
this.fragment = existingFragment;
this.tag = tag;
}
// if fragment instance is null then create instance from generic type
// else just attach the fragment
public void OnTabSelected(ActionBar.Tab tab, FragmentTransaction ft){
if (fragment == null) {
fragment = (T)global::Android.App.Fragment.Instantiate (this.context, this.fragmentName);
// if there's a tag then add the fragment to its container and tag it
// else just fragment
if (this.tag != null) {
ft.Add (Resource.Id.fragmentContainer, fragment, tag);
} else {
ft.Add (Resource.Id.fragmentContainer, fragment);
}
} else {
ft.Attach (fragment);
}
}
// if fragment is not null then detach it
public void OnTabUnselected(ActionBar.Tab tab, FragmentTransaction ft){
if (fragment != null) {
ft.Detach (fragment);
}
}
public void OnTabReselected(ActionBar.Tab tab, FragmentTransaction ft){
}
// if disposing the dispose of fragment
protected override void Dispose (bool disposing)
{
if (disposing)
this.fragment.Dispose ();
base.Dispose (disposing);
}
}
These are the important parts for making sure the state of each Fragment on the Activity is persistent when making a configuration change (changing tab, changing orientation, etc).
Now you only need for each Fragment subclass you create to retain their instance and whatever parameters you were using (a list filled by a HTTP request, an adapter, etc) to be reassigned to where they belong (DON'T REINITIALIZE YOUR VARIABLES OR YOU WON'T RETAIN THE SAME VALUES).
Each Fragment subclass must have the following on its OnCreate method:
public override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
// Don't call this method again
RetainInstance = true;
// whatever code you need on its first creation
}
Then you need to make sure your OnCreateView handles the logic to display the view with the data you want, for example if you have a fragment with a List View then you'd be wanting to have a reference to its adapter and its content, then when the view its being created check if any of those is null, if it is then you need to follow your logic to initialize them, else reassign them to the view that will be displayed:
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView (inflater, container, savedInstanceState);
var view = inflater.Inflate (Resource.Layout.some_layout, container, false);
some_list_view = view.FindViewById<ListView> (Resource.Id.some_list_view);
// since the state of this object is retained then check if the list that holds the objects for the list view is not null
// else then just reassing the adapter to the list view
if (some_list == null) {
some_list = new List<SomeObject> ();
// make a HTTP request, load images, create adapter, etc
} else {
some_list_view.Adapter = someAdapter;
}
return view;
}
With this you can avoid your fragments from losing their state when you change tabs or change orientation.
In Fragment Tab:
`#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt('tabSelected', viewPager.getCurrentItem());
}`
Inside onCreateView insert:
tabSelected=savedInstanceState.getInt("tabSelected", 0);
` #Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_config_assoc_tab, container, false);
viewPager = rootView.findViewById(R.id.viewpager_config);
viewPager.setPagingEnabled(false);
viewPager.setOffscreenPageLimit(0);
**if (savedInstanceState != null) {
tabSelected=savedInstanceState.getInt("tabSelected", 0);
}**
....
....
`
Now after rotating you will be tabSelected to the tab position. tabSelected is a global var.
I have an Android Tab Layout with swipeable views.
The file structure is as follows:
There is an activity class: TabMainActivity.java
Under this activity, there is a fragment class: bookLockerFragment.java
This fragment class is linked to an XML file which contains various buttons.
public class bookLockerFragment extends Fragment {
Button btnSis;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_booklocker, container, false);
btnSis = (Button) rootView.findViewById(R.id.btnSis);
}
.......
}
I have read up on vogella activity testing tutorials, but there is minimal information on unit testing for fragment.
I attempted to write some code but got stuck at this line:
transaction.add(R.layout.fragment_booklocker, fragment, "tag");
I get the following error:
The method add(int, Fragment, String) in the type FragmentTransaction is not applicable for the arguments (int, booklockertest, String)
Code:
public class booklockertest extends
ActivityInstrumentationTestCase2 < TabMainActivity > {
private TabMainActivity mActivity;
Fragment fragment;
FragmentManager mFragmentManager;
public booklockertest() {
super(TabMainActivity.class);
// TODO Auto-generated constructor stub
}
protected void setUp() throws Exception {
super.setUp();
mActivity = getActivity();
}
private Fragment startFragment(booklockertest fragment) {
FragmentTransaction transaction =
mActivity.getSupportFragmentManager().beginTransaction();
transaction.add(R.layout.fragment_booklocker, fragment, "tag");
transaction.commit();
getInstrumentation().waitForIdleSync();
Fragment frag =
mActivity.getSupportFragmentManager().findFragmentByTag("tag");
return frag;
}
public void testFragment() {
booklockertest fragment = new booklockertest() {
//Override methods and add assertations here.
};
Fragment frag = startFragment(fragment);
}
}
stumble upon this, and you probably have figured it out already, but
private Fragment startFragment(booklockertest fragment) { ... }
...
public void testFragment() {
booklockertest fragment = new booklockertest() {
//Override methods and add assertations here.
};
Fragment frag = startFragment(fragment);
}
should be
private Fragment startFragment(bookLockerFragment fragment) { ... }
...
public void testFragment() {
bookLockerFragment fragment = new bookLockerFragment() {
//Override methods and add assertations here.
};
Fragment frag = startFragment(fragment);
}
Yesterday I downloaded new HoloEverywhere library.
Currently, I have problem with tab navigation after screen rotation.
My Home Activity:
public class MainActivity extends Activity implements TabListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setUpTabs();
}
private void setUpTabs() {
String[] titles = {
"First", "Second",
};
ActionBar supportActionBar = getSupportActionBar();
for (int i = 0; i < titles.length; i++) {
ActionBar.Tab tab = supportActionBar.newTab();
tab.setText(titles[i]);
tab.setTag(MyFragment.TAG);
tab.setTabListener(this);
supportActionBar.addTab(tab, false);
}
supportActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
supportActionBar.setSelectedNavigationItem(0);
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction fragmentTransaction) {
final String fragmentTag = tab.getTag().toString();
Fragment fragment = getSupportFragmentManager().findFragmentByTag(fragmentTag);
if (fragment == null) {
fragment = new MyFragment();
fragmentTransaction.add(android.R.id.content, fragment, fragmentTag);
} else {
fragmentTransaction.attach(fragment);
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction fragmentTransaction) {
Fragment fragment = getSupportFragmentManager().findFragmentByTag((String) tab.getTag());
if (fragment != null) {
fragmentTransaction.detach(fragment);
}
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction fragmentTransaction) {
}
}
And my Fragment class.
public class MyFragment extends Fragment {
public static final String TAG = MyFragment.class.getCanonicalName();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = new View(getActivity());
view.setBackgroundColor(Color.BLACK);
return view;
}
}
When I rotate the screen fragment not displaying. It displays when i select tab (which is not currently selected) manually.
I just solve the problem.
I post my code here and see if those can help you :D
if (savedInstanceState == null){
TabHomeFragment homeFragment = new TabHomeFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, homeFragment, "home_fragment").commit();
}else{
TabHomeFragment homeFragment = (TabHomeFragment) getSupportFragmentManager().findFragmentByTag("home_fragment");
}
Those code are located in OnCreate method.
When the Device rotate and Ortiention change, the fragment will recreate again. So add a if clase to check if there is already one here.
But I am using normal Fragment in Android. Hope it can help you a little.
I have a problem with one thing - when I change orientation my second fragment, which is active at the moment, replaces by first fragment. I have never so such a behaviour, how can If fix it?
MainActivity:
public class MainActivity extends SherlockFragmentActivity implements onDialogClickListener, ITaskLoaderListener {
FragmentManager fm;
public ActionBar actionBar;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager_layout);
fm = getSupportFragmentManager();
actionBar = getSupportActionBar();
actionBar.setHomeButtonEnabled(false);
actionBar.setDisplayUseLogoEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
FragmentTransaction ft = fm.beginTransaction();
ft.add(android.R.id.content, new FirstActivity.FirstFragment(), "loan").commit();
}
}
FirstFragment:
public class FirstActivity extends SherlockFragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "here");
final ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayUseLogoEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentById(android.R.id.content) == null) {
FirstFragment first = new FirstFragment();
fm.beginTransaction().add(android.R.id.content, first).commit();
}
}
public static class FirstFragment extends SherlockFragment implements OnClickListener, OnItemClickListener {
private static final String TAG = "LoanFragment";
private View rootView;
private Button bExtend;
private FragmentManager fm;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (session.hasLoan()) {
rootView = inflater.inflate(R.layout.fragment_loan, container, false);
bExtend = (Button) rootView.findViewById(R.id.b1);
return rootView;
}
}
#Override
public void onClick(View v) {
FragmentTransaction ft = fm.beginTransaction();
switch (v.getId()) {
case R.id.b1:
ft.add(android.R.id.content, new SecondActivity.SecondFragment(), "second").addToBackStack(null).commit();
break;
}
Second Fragment:
public class SecondActivity extends SherlockFragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayUseLogoEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentById(android.R.id.content) == null) {
SecondFragment second = new secondFragment();
fm.beginTransaction().add(android.R.id.content, second).commit();
}
}
public static class SecondFragment extends SherlockFragment {
private View rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_extend, container, false);
return rootView;
}
That`s to say when I am in second fragment and try to change orientation then my second fragment will replaced on first fragment. Why? How to fix it?
onCreate will be called on orientation change and you add the first fragment there. You can save which fragment you want to show in onSaveInstanceState and then use the instance state in onCreate to add the correct fragment.
EDIT:
You need to maintain a variable currentFragmentIndex and save it in onSaveInstanceState like so:
protected void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putInt("currentFragment", currentFragment);
}
Then retrieve it in onCreate and initialize the fragment accordingly:
public void onCreate(Bundle bundle) {
if (bundle!= null){
currentFragmentIndex= bundle.getInt("currentFragment");
} else {
currentFragmentIndex = 0;
}
switch(currentFragmentIndex) {
case 0:
// TODO: Add first fragment
break;
case 1:
// TODO: Add second fragment
break;
}
}
Don't forget to change currentFragmentIndex to 1 when you switch to the second fragment.
I ran into the same issue, though as a note, I'm using the v4 support library. After reading Sapan Diwakar's answer, I wondered if this was necessary; instead, I tried this...
if (null == mFragmentManager.findFragmentByTag(TAG_HERE)) {
mFragmentManager.beginTransaction()./*blah blah blah*/.commit();
}
...so the original fragment is only instantiated/attached if there's nothing already attached where it's supposed to go.
I've tested this a bit and it seems to be fine... of course, the fact that it works doesn't mean it's a good idea, but I'm too new at this to know why it wouldn't be. If anyone can chime in on that, it'd be useful.
Thanks for posting this question, and also to everyone with input!