currently i am using ActionBarSherlock for my project. I am creating my actionbar with this code.
setTheme(R.style.Theme_Sherlock);
Context context = getSupportActionBar().getThemedContext();
list = ArrayAdapter.createFromResource(context, R.array.locations, R.layout.sherlock_spinner_item);
list.setDropDownViewResource(R.layout.sherlock_spinner_dropdown_item);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
getSupportActionBar().setListNavigationCallbacks(list, this);
My question is. After I choose an option from the dropdown navigation, How do I keep that state throughout my activities?
For Example, in the homescreen, I choose "Sports" under my dropdown navigation. The title of the dropdown navigation then becomes "Sports". When I change activites however, the dropdown navigation title defaults back to the first item on the list.
One method I used was to create a base activity that each navigation item / activity extended from. Within the base activity, I overloaded onResume with an int to track which activity was active, and set the selected navigation item in that method.
Example:
public class BaseActivity extends FragmentActivity {
//...
protected void onResume(final int actId) {
super.onResume();
//...setup your action bar via getSupportActionBar() calls...
getSupportActionBar().setSelectedNavigationItem(actId);
}
Then in your individual activities:
public class ExampleActivity extends BaseActivity {
private final int ACT_ID = 1;
//...
protected void onResume() {
super.onResume(ACT_ID);
//...
}
}
Hope that helps!
Related
I am making an Android application which has one activity and many fragments. The activity contains a bottom app bar and that bottom bar has a navigation icon in it. Like this:
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottom_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:backgroundTint="#color/colorbottomappbar"
app:fabAlignmentMode="center"
app:navigationIcon="#drawable/ic_menu_green_24dp">
</com.google.android.material.bottomappbar.BottomAppBar>
This navigation menu icon will be shown in every fragment. However, in some fragments I want to change that navigation icon in the bottom app bar to back button/icon. How can I achieve this? Also, currently I handle the navigation icon click in the main activity. How can I handle the click in the case of the back icon? How will it know what the current fragment is and how can I determine which fragment the back icon leads to?
If you look at the documentation, you'll see that BottomAppBar extends from Toolbar and it has an inherited method called setNavigationIcon(int res).
You can implement an interface that your main Activity implements like so:
interface FramentChangedListener {
void onFragmentChanged(int type);
}
Your activity would do something like this:
public class MainActivity extends Activity implements FragmentChangedListener {
// This will keep track of what is currently shown
private int current = 0;
#Override
public void onFragmentChanged(int type) {
if (type == FirstFragment.SOME_TYPE) {
// Update the current fragment value, we're associating each fragment
// with an int value.
current = type;
bottomAppBar.setNavigationIcon(R.drawable.your_back_icon);
}
}
...
}
In your fragment you would do something like this:
public class FirstFragment extends Fragment {
private FragmentChangedListener listener;
public static final int SOME_TYPE = 1;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceOf FragmentChangedListener) {
// context in this case is your activity, which implements FragmentChangedListener
listener = (FragmentChangedListener) context;
// You can call the listener now
listener.onFragmentChanged(SOME_TYPE);
}
}
}
In your Activity, add a listener to the BottomAppBar via setNavigationOnClickListener and whenever you receive the navigation icon event, you can check against the current value that we defined.
How can I define a different Statusbar and Actionbar color for each fragment ?
At the moment.
How it should look.
First of all, I would highly recommend you to migrate to new approach - Toolbar. It is much more flexible and you can customize it as plain View.
About your question.
You can just get ActionBar object and setBackground programatically.
Here is short example
ActionBar bar = getActionBar();
bar.setBackgroundDrawable(new ColorDrawable("COLOR IN HEX 0xFFFF6666 for instance"));
I will show how would I implement this. This is more about architecture and patterns.
Use some base class for Fragment it would be better to have base class for Activity as well. Lets consider
public class BaseFragment extends Fragment
And you Activity class in which your fragment lives.
public class MainActivity extends Activity
And you have to define responsibilities of Activity in this case and create interfaces
In your case to work with ActionBar
Create interface
public interface ActionBarProvider {
void setActionBarColor(ColorDrawable color);
}
Make your activity implement this interface
public class MainActivity extends Activity implements ActionBarProvider {
public void setActionBarColo(ColorDrawable color) {
ActionBar bar = getActionBar();
bar.setBackgroundDrawable(color));
}
}
And finally in BaseFragment in onAttach
public void onAttach(Context context) {
super.onAttach(context);
mActionBarProvider = (ActionBarProvider) context;
}
Make mActionBarProvider variable protected and make each fragment extend BaseFragment and you can change action bar color from any fragment like this mActionBarProvider.setActionBarColor(new ColorDrawable());
Hope this helps.
in my app i am developing an activity using the actionbar in NAVIGATION_MODE_TABS-mode.
Each tab is showing a fragment (list, detail).
Initially the list-tab is visibile.
The list is implementing setMultiChoicheModeListener() and modifies the ActionBar and the title of the activity if one or more items are selected.
How can i reset the title and the ActionBar to the inital value (title and actions) when the user clicks on the detail-tab without deselecting the items?
BTW Target-Platform is > 4.1 and i am not using the support library.
Thanks.
public class MyActivity extends Activity {
#Override
protected void onCreate (Bundle savedInstanceState) {
this.actionBar = getActionBar();
this.actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
....
for (Tab tab : getTabs())
{
//here are two tabs added (List and Detail)
this.actionBar.addTab(tab);
}
....
}
protected class NavigationTabListener implements ActionBar.TabListener {
private Fragment fragment;
....
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(newFragmentResourceId, this.fragment);
}
}
}
public class MyListViewFragment extends LinearLayout implements IListViewFragment {
....
#Override
public void initialize() {
inflate(getContext(), listLayoutResourceId, this);
this.myList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL);
this.myList.setMultiChoiceModeListener(new MultiChoiceModeListener() {
....
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)
{
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(selectedItemsMenuResourceId, menu);
return true;
}
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked)
{
if (checked)
{
this.numberItemsSelected++;
adapter.setNewSelection(position);
}
else
{
this.numberItemsSelected--;
adapter.removeSelection(position);
}
mode.setTitle(getContext().getResources().getQuantityString(
R.plurals.items_selected, this.numberItemsSelected,
Integer.valueOf(this.numberItemsSelected)));
}
....
}
}
I am trying to implement the MVP pattern, but it's still in evaluation phase. The Activity acts as the presenter, the views are in separate classes.
For each Fragment i am also implementing the MVP apttern, but i think this is not interesting to solve the problem.
Some notes to the classes:
MyActivity creates two fragments (one for List, one for Detail view, the detail view has nothing to do with the selected items).
The initial view of the activity is the fragment with the list.
If the user selects some entries I am updating the action bar and the title through the callback of MultiChoiceModeListener.
But the user can now change the fragment by clicking on the "Detail" tab without deselecting the items or clicking to the new elements in the action bar, the result is that the detail fragment is shown, but the title of the activity is still the one I modified in the MultiChoiceModeListener, and there is also the check mark of the action bar visible (auto created by the system).
So the best way is I think to get somehow the current ActionMode, so I can invoke finish() to "reset" the ActionBar and the title.
Make sure you keep reference of the ActionMode in the ActionMode.Callback methods inside your activity which has the ActionBar.TabListener.
When a new tab is selected just finish the action mode, like:
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if(mActionMode != null){
mActionMode.finish();
}
ft.replace(newFragmentResourceId, this.fragment);
}
Make the ActionMode reference back to null when onDestroyActionMode(ActionMode) is called.
In my Activity I want to show arrow to left of ActionBar icon, so in Activity I write:
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
It works fine, but I decide move ActionBar initialization to another class and use it for all activities in my application, new class for this:
public class Utils {
public static void initActionBar(Activity activity, boolean homeIconNeeded) {
ActionBar actionBar = activity.getActionBar();
actionBar.setIcon(R.drawable.logo);
actionBar.setHomeButtonEnabled(homeIconNeeded);
actionBar.setBackgroundDrawable(activity.getResources().getDrawable(R.drawable.action_bar_background));
}
public static void initActionBar(ActionBar actionBar, boolean homeIconNeeded) {
actionBar.setIcon(R.drawable.logo);
actionBar.setHomeButtonEnabled(true);
actionBar.setBackgroundDrawable(SmartVmsApplication.getContext().getResources().getDrawable(R.drawable.action_bar_background));
}
}
Then in my activity I insert in onCreate() callback initActionBar(this, true), however arrow doesn’t appear, no matters I passed Activity or ActionBar as parameter and it is an issue.
You forgot to call the setDisplayHomeAsUpEnabled() method.
Can anyone give a quick example of how to change the contents of an Activity action bar based on something that takes place in a fragment? My intent:
Normal menu items -> Something in the fragment is moved -> menu items change to save / discard buttons.
My first impulse is to setup Broadcast Receivers in both the activity and the fragment to cross talk, but I am not sure if this is correct.
Fragments can change menu in actionbar. For that you have to add necessary flag in fragment's oncreate() using method setHasOptionsMenu(true);
When your fragment is loaded you will get call at onCreateOptionsMenu(Menu menu, MenuInflater inflater) just like in an activity. Then do necessary changes to your menu.
Save you menu as global in fragment, and whenever you want to make a change, apply on it.
The following works for me. I have a custom class that implements ListView.MultiChoiceModeListener inside a Fragment:
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
// Choose the correct Action Bar menu to display
int menu = myCondition == true ? R.menu.my_default_menu : R.menu.my_menu_2;
// Configure to use the desired menu
mode.getMenu().clear();
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(menu);
}
Given how you detect 'something in the fragment has moved', extending ListView.MultiChoiceModeListener may not work for you, but hopefully this illustrates how to change the menu. The key is to get access to a ActionMode instance.
I think you want to use a contextual action mode. On the drag event, you will start a new ActionMode which can replace the contents of the action bar with menu items specific to what you want to allow the user to do. Once the user chooses an action, you finish the action mode and the action bar returns to its previous state.
Not sure if an ActionBar instance would help with the menu you but would surely be useful.. Here's a way to get about it
Try this to get the ActionBar from the FragmentActivity using the onAttach(Activity activity) method in the Fragment.
First of all make a global object of your FragmentActivity in the Fragment like this
public class YourFragment extends Fragment {
private YourFragmentActivity context;
}
Override this in the YourFragment class
#Override
public void onAttach(Activity activity){
context = (YourFragmentActivity)activity;
super.onAttach(activity);
}
Then in the OnCreate method in the YourFragment do this
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState){
...
android.support.v7.ActionBar actionBar = context.getSupportActionBar();
...
}