Issue
PROBLEM:
When I try to reference the layout of one Fragment from another via the parent Activity. The layout I am trying to access is always null.
I believe it is something to do with the onCreate() and onCreateView() not being called when created via a newInstance() method from an Activity. This is an area of Android that is a bit unfamiliar to me and I am not 100% sure on how the Activity & Fragment lifecycle interact. Brief overview in background and all code included at the bottom of question.
It is most likely a simple fix that I am currently blind to. Detail is included for the sake of completeness.
BACKGROUND:
The problem is, I have two Fragments
hosted by an Activity
Class. The Activity
class is made up a standard base Activity
class which I use for many Activities across the app. This keeps reference to the ActionBar Fragments layout (for changing the title, images etc) and contains methods for getting a new ActionBar instance etc. (Key method here is setActionBarTitle(title)
- referred to later) Code included below [1]
The second part of the Activity
inheriting class that contains the two Fragments is a task specific Activity
, in this case a help Activity
.
This is the Activity
that loads the action bar fragment (via newInstance(title)
method from base class) and the corresponding fragment, in this case help fragment. [2]
WHERE THINGS GO WRONG:
In the onAttach()
method, I get reference to the parent Activity
- Activity_Help
.
The problem comes in the onCreateView()
of my help Fragment
[3]. The goal is to access the setActionBarTitle method of Activity_Help.
As Activity_Help extends the Activity base class (General_Activity), the setActionBarTitle()
method and the stored actionBarLayout are both accessible. It seems like it should have access to everything neccessary to change the action bar fragment text?
However, this is what goes on..
[Fragment_Help]
parentActivity.setActionBarTitle("New title");
Leads to..[General_Activity]
fragmentActionBar.setTitle(newTitle);
Leads to..[Fragment_Example1_ActionBar]
TextView tvTitle = (TextView) actionBarLayout.findViewById(R.id.tvCustomActionBarTitle);
ERROR LINE - actionBarLayout is null
Full code for action bar fragment is included at the very bottom. [4]
I believe as first mentioned is in the Activity_Help.fragmentActionBar not keeping it's layout. When it is accessed for the second time to change the TextView
, the layout is null hence NPE.
Any advice would be truly appreciated!
Superclass Activity code [1]
public class General_Activity extends Activity
{
Fragment_Example1_ActionBar fragmentActionBar;
....
// Start Help Activity
case R.id.bMenuHelp:
Intent helpIntent = new Intent(this, Activity_Help.class);
helpIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(helpIntent);
break;
....
// Create a new ActionBar with given title
public void newActionBarInstance(String initialTitle)
{
fragmentActionBar = Fragment_Example1_ActionBar.newInstance(initialTitle);
}
// Create a new ActionBar with no title
public Fragment_Example1_ActionBar newActionBarInstance()
{
return Fragment_Wurth_Example1_ActionBar.newInstance("");
}
// Set ActionBar title
public void setActionBarTitle(String newTitle)
{
fragmentActionBar.setTitle(newTitle);
}
}
Activity_Help code [2]
public class Activity_Help extends General_Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_container_layout);
FragmentManager fragmentManager = getFragmentManager();
Fragment_Help fragmentWholeScreen = new Fragment_Help();
// SC - Create new ActionBar with given title
newActionBarInstance("Help");
if (!fragmentWholeScreen.isAdded())
{
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container_layout_example1, fragmentWholeScreen);
fragmentTransaction.add(R.id.fragment_action_bar, fragmentActionBar);
fragmentTransaction.commit();
}
}
};
Fragment_Help code [3]
public class Fragment_Help extends Fragment
{
Activity_Help parentActivity;
@Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
parentActivity = (Activity_Help) activity;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View helpLayout = inflater.inflate(R.layout.fragment_help, null);
parentActivity.setActionBarTitle("New title");
return helpLayout;
}
}
Fragment_Example1_ActionBar code [4]
public class Fragment_Example1_ActionBar extends Fragment
{
OnCustomActionBarItemSelectedListener onCustomActionBarItemSelectedListener;
View actionBarLayout;
String title;
// Pass in original title
@Override
public void onCreate(Bundle savedInstanceState)
{
Log.i("ACTiON_BAR", "++ ON CREATE ++ " + System.currentTimeMillis());
super.onCreate(savedInstanceState);
Bundle receivedArguments = getArguments();
title = receivedArguments.getString(App.ACTION_BAR_TITLE_KEY);
actionBarLayout = getActivity().getLayoutInflater().inflate(R.layout.action_bar_layout, null);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Log.i("ACTiON_BAR", "+ ON CREATE VIEW + " + System.currentTimeMillis());
if (title != null)
{
setTitle(title);
}
// Get reference to ActionBar buttons and set Listeners
final ImageButton bActionBarLogo = (ImageButton) actionBarLayout.findViewById(R.id.bCustomActionBarHome);
final ImageButton bActionBarMenu = (ImageButton) actionBarLayout.findViewById(R.id.bCustomActionBarMenu);
final ImageButton bActionBarVehicleCheckIn = (ImageButton) actionBarLayout.findViewById(R.id.bCustomActionBarVehicleCheckIn);
bActionBarLogo.setOnClickListener(actionBarButtonListener);
bActionBarMenu.setOnClickListener(actionBarButtonListener);
bActionBarVehicleCheckIn.setOnClickListener(actionBarButtonListener);
return actionBarLayout;
}
// Intermediate menu button listener calling parent Activity implementation
OnClickListener actionBarButtonListener = new OnClickListener()
{
public void onClick(View actionBarItem)
{
onCustomActionBarItemSelectedListener.onCustomActionBarItemSelected(actionBarItem);
}
};
// Set ActionBar title
public void setTitle(String newTitle)
{
// Get refence to the title TextView in the custom layout
TextView tvTitle = (TextView) actionBarLayout.findViewById(R.id.tvCustomActionBarTitle);
// Set the title
tvTitle.setText(newTitle);
}
// Set ActionBar text size
public void setTextSize(float textSize)
{
// Get refence to the title TextView in the custom layout
TextView tvTitle = (TextView) actionBarLayout.findViewById(R.id.tvCustomActionBarTitle);
// Set the title
tvTitle.setTextSize(textSize);
}
// Get reference to parent activity and it's Action Bar listener
@Override
public void onAttach(Activity activity)
{
Log.i("ACTiON_BAR", "+++ ON ATTACH +++ " + System.currentTimeMillis());
super.onAttach(activity);
try
{
// Get reference to Activity's implementation of listener
onCustomActionBarItemSelectedListener = (OnCustomActionBarItemSelectedListener) activity;
}
catch (ClassCastException e)
{
// If Activity doesn't implement listener, throw exception explaining error
throw new ClassCastException(activity.toString() + " must implement OnCustomActionBarItemSelectedListener");
}
}
// New instance - keep the creation within the class in one place
public static Fragment_Example1_ActionBar newInstance(String initialTitle)
{
// Package the title up in a bundle
Bundle titleBundle = new Bundle();
titleBundle.putString(App.ACTION_BAR_TITLE_KEY, initialTitle);
Fragment_Example1_ActionBar fragmentActionBar = new Fragment_Example1_ActionBar();
fragmentActionBar.setArguments(titleBundle);
return fragmentActionBar;
}
// New instance - keep the creation within the class in one place
public static Fragment_Example1_ActionBar newInstance()
{
// Package the title up in a bundle
Bundle titleBundle = new Bundle();
titleBundle.putString(App.ACTION_BAR_TITLE_KEY, "");
Fragment_Example1_ActionBar fragmentActionBar = new Fragment_Example1_ActionBar();
fragmentActionBar.setArguments(titleBundle);
return fragmentActionBar;
}
}
Cheers!
Solution
The problem was as dmon suggested that the fragments in the FragmentTransaction were being initialized in the wrong order
Answered By - mgibson
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.