I have an application, that at the moment only has 2 fragments. Fragment 1, this has the nav drawer and the title.
Fragment 2 requires a custom view as adding menu items won't work as I need alignment. So I add the view as follows:
ActionBar.LayoutParams params = new ActionBar.LayoutParams(
ActionBar.LayoutParams.MATCH_PARENT,
ActionBar.LayoutParams.MATCH_PARENT,
Gravity.LEFT);
//Remove nav drawer "hamburger"
mMainActivity.mActionBarDrawerToggle.setDrawerIndicatorEnabled(false);
//Remove title from Toolbar
bar.setDisplayShowTitleEnabled(false);
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View postToolBar = layoutInflater.inflate(R.layout.upload_content_toolbar, null);
mMainActivity.mToolBar.addView(postToolBar, params);
That is fine and it displays correctly. However, when I want to return to the previous fragment Fragment 1, I then call mMainActivity.mToolBar.removeView(postToolBar); I call this on return to Fragment 1 as the user can navigate either by the back button or by button in the postToolBar. However, the view is still in place. I can't get rid of it. I have now tried setting the visibility to GONE but that won't work either.
This was pretty simple with the Action Bar, however things seem to have gotten a bit complicated with the Tool bar.
I must add that in each of my two fragments I extend a BaseFragment in which I declare the toolbar view.
Can any one help or send me in the direction of a tutorial?
This is how i achieved it at this time:
in activity onCreateView();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowCustomEnabled(true); // enable overriding the default toolbar_home layout
getSupportActionBar().setDisplayShowTitleEnabled(false); // disable the default title element here (for centered title)
getSupportActionBar().setDisplayShowHomeEnabled(false);
cutomToolbarView=getLayoutInflater().inflate(R.layout.custom_toolbar_home, null);
getSupportActionBar().setCustomView(cutomToolbarView);
}
and here is two simple method to do the magic
public void setToolbarTitleEnabled(String title) {
getSupportActionBar().setDisplayShowCustomEnabled(false);
getSupportActionBar().setDisplayShowTitleEnabled(true);
getSupportActionBar().setTitle(title);
}
public void setCustomToolbarEnabled() {
getSupportActionBar().setDisplayShowCustomEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
then simply when you can change actionbar like these:
when to select HomeFragment.java or whatever in your case
setToolbarTitleEnabled(CURRENT_TAG);
and when to select other fragment:
setCustomToolbarEnabled();
Related
What I am trying to achieve is to add a Toolbar to my Fragment UI when my Activity also has a bar that is NOT shown inside the fragment. Basically, how can my Activity and Fragment(s) have their own toolbar?
This is my code in my activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(mToolbar);
}
And here is my code in my fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_layout, container, false);
mToolbar = (Toolbar) mView.findViewById(R.id.fragment_toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(mToolbar);
return mView;
}
What I get is that when I create the toolbar in my Fragment, the toolbar is the toolbar from the activity. What I want to do is I want the fragment to have it's separate toolbar from it's parent Activity.
Here are a few things that I can think of which are definitely not ideal:
Make the fragment an activity.
Simulate as if I have created a toolbar but simply have the Fragment toolbar defined as a UI element that I have pieced together myself.
Somehow edit the parent Activity's toolbar to make it specific to the fragment, and then somehow redraw the Activity toolbar? This seems weird and I am not even sure if it's possible.
Having 2 toolbars in one activity is not advisable since it'll look really bad.
with ((AppCompatActivity) getActivity()).setSupportActionBar(mToolbar);
you're replacing the activities toolbar with the one that you're defined in the fragment's layout file.
I would suggest you to use fragment specific actions for the toolbar when the fragment is visible on the screen and change it's behavior by accessing the content of the toolbar by
Toolbar mToolbar = ((AppCompatActivity) getActivity()).getSupportActionBar();
now use the mToolbar to change the actions
I have a generic
MyActivity extends AppCompatActivity
I don't override the toolbar with a custom xml defined toolbar, just use the generated one Android provides.
I can set the title via your normal
getSupportActionBar().setTitle("foo");
but setting the subtitle via
getSupportActionBar().setSubtitle("bar");
doesn't set it. It remains blank. I'm doing this onCreate()
(I feel I've done this many times before with no fail)
Although I've noticed if I visit another activity, then return, the subtitle would then show... not on orientation change, not on recreate() but only when I'm returning from an activity.
I'm experiencing this on 5.0 and 7.0
For the time being I'll likely define my own Toolbar and move forward since that seems where most people have solutions for this same problem.
Relevant code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_replenishment_list);
ButterKnife.bind(this);
MyApplication.getInstance().getComponent().inject(this);
setupUI();
}
private void setupUI() {
setupActionBar();
}
private void setupActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
//TODO: not working unless activity is recreated...
// explore custom xml defined toolbar
//actionBar.setTitle("different title than what is defined in manifest"); <-- this does work, but not this
actionBar.setSubtitle(UserUtil.getFormattedFirstNameLastName(userService.getUserFromJWT(), this));
}
}
I have put the below code in my onCreate() method.
ActionBar actionBar = getActionBar();
if (actionBar==null) {
System.out.println("TEST NULL");
} else {
System.out.println("TEST NOT NULL");
}
The result is null. When I add the toolbar first it works fine.
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getActionBar();
actionBar.setSubtitle("TESTING");
Your getSupportActionBar or getActionBar will return null if you didn't set toolbar to it. You need to set the toolbar to your action bar before using getSupportActionBar or getActionBar.
Why navigation drawer icon gets disappeared on setting customView by
actionbar.setCustomView(R.layout.blah);
How can this be resolved?
OK, you don't post any code, so I have to assume stuff here. So if you can update your question and show actual code!!
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
// Depending on what your custom Action Bar will do, you might want to disable these!
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayShowTitleEnabled(false);
LayoutInflater inflater = LayoutInflater.from(this);
View customView = inflater.inflate(R.layout.custom_actionbar, null);
// Here is how you can get specific items from your custom view!
TextView titleTextView = (TextView) customView.findViewById(R.id.title_text);
titleTextView.setText("My Own Title");
...
// MAKE SURE THESE ARE SET!! BOTH OF THEM!!
actionBar.setCustomView(mCustomView);
actionBar.setDisplayShowCustomEnabled(true);
}
The biggest issue is probably the code at the very end. Please make sure you have that code!
Problem:
The Fragment backstack is made so that traversing backwards through a stack of fragments in one activity does not revert the Action Bar to its original state in the previous fragment.
Why does this happen?
Turns out, the Action Bar is actually attached to the Activity itself, not the fragment! Remember, fragments are only modular bits of the UI, and have to explicitly specify control to other fragments, sections of the activity, or even the Action Bar.
Keep reading for the solution...
Solution:
I found that the best approach to this problem is done by what is generally described in Reto Meier's answer to a previous question. My solution will just expand more deeply on his answer.
What we want to establish though is that we don't want to re-create the action bar every time we switch to a different fragment, reason being it's not very efficient. I'm going to walk you through an I wrote for a student scheduling app. It's not very complicated, and it's onboarding experience is composed of multiple fragments held within an activity.
To make this work, we need to make sure we're using replace() to switch between fragments. This is better than layering fragments on top of each other, because it lets you configure the action bar separately for each fragment.
The first chunk of code comes from the activity's inner class, LoginOptionsFragment, in its onCreateView() method.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_login_options, container, false);
//LoginOptionsFragment will have its own action bar
setHasOptionsMenu(true);
//inject views. e.g: Button add_course
ButterKnife.inject(this, rootView);
add_course.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getFragmentManager().beginTransaction()
//exchange fragments. no messy clean-up necessary.
.replace(R.id.container, new AddCourseFragment())
.addToBackStack(null)
.commit();
}
});
return rootView;
}
Here, I not only make sure to call onCreateOptionsMenu() via the setHasOptionsMenu(true), but mainly, as soon as the "ADD COURSE" button is clicked to switch to the AddCourseFragment, the new fragment replaces the old fragment as the primary child of the activity. Next, after we override the onCreateOptionsMenu(), we come to onResume(), but we'll get to that later ;)
Secondly, we arrive at the AddCourseFragment, where we even inflate a custom done-cancel view for the action bar. So let's look at the code!
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// BEGIN_INCLUDE (inflate_set_custom_view)
// Inflate a "Done/Cancel" custom action bar view.
final ActionBar actionBar = getActivity().getActionBar();
inflater = (LayoutInflater) actionBar.getThemedContext()
.getSystemService(LAYOUT_INFLATER_SERVICE);
//inflate custom action bar view
View customActionBarView = inflater.inflate(
R.layout.actionbar_custom_view_done_cancel, null);
//set listeners to items in the view
customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
// "Done"
//remove custom view from action bar
actionBar.setDisplayShowCustomEnabled(false);
getFragmentManager().popBackStack();
//add course to list
}
});
customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
// "Cancel"
//remove custom view from action bar
actionBar.setDisplayShowCustomEnabled(false);
getFragmentManager().popBackStack();
}
});
// Show the custom action bar view and hide the normal Home icon and title.
actionBar.setDisplayOptions(
ActionBar.DISPLAY_SHOW_CUSTOM,
ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME
| ActionBar.DISPLAY_SHOW_TITLE);
actionBar.setCustomView(customActionBarView,
new ActionBar.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
actionBar.setDisplayHomeAsUpEnabled(false);
// END_INCLUDE (inflate_set_custom_view)
View rootView = inflater.inflate(R.layout.fragment_add_course, container, false);
ButterKnife.inject(this, rootView);
return rootView;
}
The ONLY part that you need to pay attention to are the OnClickListener's added to the DONE and CANCEL buttons. In here, I use my previous reference to the parent Activity's action bar and tell it to stop displaying the custom view. Now in addition to this specific method, there are more setDisplayXEnabled() methods that you can pass in false to. After that, I pop the backstack to get to the previous fragment.
But how do I actually revert the action bar!?
Here's how. Remember that onResume() method that was hanging out in our LoginOptionsFragment? Well, onResume() is called once a fragment gets back into focus from the backstack! So if we override it and re-enable the parts of the action bar that we want, we win right? Yes we do. Here is all you need to add into the onResume().
#Override
public void onResume() {
super.onResume();
ActionBar actionBar = getActivity().getActionBar();
actionBar.setDisplayShowHomeEnabled(true); //show Home icon
actionBar.setDisplayShowTitleEnabled(true); //show title
// actionBar.setDisplayUseLogoEnabled(true); <--- more options
// actionBar.setDisplayHomeAsUpEnabled(true); <--- more options
}
And we did it all without recreating the action bar. Here's how it looks!
Thanks for reading, and happy coding!
I want to remove from the arrow image from the HomeAsUpButton.
I tried removing the arrow's ImageView from the layout (nothing happens) and also tried using SupportActionBar.SetDisplayHomeAsUpEnabled(false); removes the button functionality entirely.
I'm using johnkil's SideNavigation code. Any suggestions?
Using YouTube's App as example:
With the ActionBar Sherlock, inside your Activity's onCreate method, you just need to do the following:
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
If the up image does not disappear, it might be something related to the library that you referred. In my app, I use the SlidingMenu library and it works just fine (source: https://github.com/jfeinstein10/SlidingMenu)
EDIT: With the SlidingMenu library, the Activity would look like this:
public class MainAct extends SlidingFragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Sliding menu
// Here I set the menu's layout
setBehindContentView(R.layout.menu_frame);
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
MenuListFrag frag = MenuListFrag.newInstance(getSlidingMenuItems());
t.replace(R.id.menu_frame, frag);
t.commit();
// Customizing the SlidingMenu
SlidingMenu sm = getSlidingMenu();
sm.setShadowWidthRes(R.dimen.shadow_width);
sm.setShadowDrawable(R.drawable.shadow);
sm.setFadeDegree(0.35f);
// Hiding the ActionBar's up button
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setHomeButtonEnabled(true);
}
}
You can disable the action bar using this method
actionBar.setHomeButtonEnabled(false);
I was able to hide the "arrow" by setting a transparent image.