Let me say that before facing this problem i had almost fucked up my entire project, had bugs for a few days and eventually solved them.
My Android app is now almost fine except that whenever I click on the Options Menu (in ANY activity, not just this one i'm posting here) it crashes unexpectedly with a strange message which doesn't make ANY reference to my code.
Here's the stack trace:
12-28 22:15:07.842 11672-11672/com.cats.timemanager E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.cats.timemanager, PID: 11672
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at android.support.v7.view.menu.ListMenuItemView.setTitle(ListMenuItemView.java:127)
at android.support.v7.view.menu.ListMenuItemView.initialize(ListMenuItemView.java:113)
at android.support.v7.view.menu.MenuAdapter.getView(MenuAdapter.java:100)
at android.support.v7.view.menu.MenuPopup.measureIndividualMenuWidth(MenuPopup.java:160)
at android.support.v7.view.menu.StandardMenuPopup.tryShow(StandardMenuPopup.java:153)
at android.support.v7.view.menu.StandardMenuPopup.show(StandardMenuPopup.java:187)
at android.support.v7.view.menu.MenuPopupHelper.showPopup(MenuPopupHelper.java:290)
at android.support.v7.view.menu.MenuPopupHelper.tryShow(MenuPopupHelper.java:175)
at android.support.v7.widget.ActionMenuPresenter$OpenOverflowRunnable.run(ActionMenuPresenter.java:803)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
It just looks like my app is crashing with no reason.
Here is my code:
package com.cats.timemanager.activities;
//Cannot write imports here sorry, StackOverflow editor sucks
public class MainActivity extends AppCompatActivity {
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
AppSettingsData myAppSettingsData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myAppSettingsData = new AppSettingsData(getApplicationContext());
if (myAppSettingsData.getBoolean("first_start", true)) {
Intent tempIntent = new Intent(getBaseContext(), IntroActivity.class);
startActivity(tempIntent);
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
mViewPager = (ViewPager) findViewById(R.id.container);
setSupportActionBar(toolbar);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
setTitle(mSectionsPagerAdapter.getPageTitle(position));
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
setTitle(mSectionsPagerAdapter.getPageTitle(0));
/**
* TODO find out sth else to check whether the service is on
*/
if (isServiceRunning(ScreenService.class) == false) {
Intent intentScreenService = new Intent(getApplicationContext(), ScreenService.class);
intentScreenService.putExtra("EVENT", 1);
getApplicationContext().startService(intentScreenService);
}
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent myIntent = new Intent(getBaseContext(), ApplicationStatisticsActivity.class);
startActivity(myIntent);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_activity_menu, menu);
Log.i("CATs", "THIS LOG APPEARS-> THE APP IS WORKING FINE TILL NOW.");
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.main_activity_action_settings) {
Intent myIntent = new Intent(getBaseContext(), SettingsActivity.class);
startActivity(myIntent);
return true;
}
if (id == R.id.main_activity_action_per_app_statistics) {
Intent myIntent = new Intent(getBaseContext(), ApplicationStatisticsActivity.class);
startActivity(myIntent);
return true;
}
if (id == R.id.main_activity_action_timeline) {
Intent myIntent = new Intent(getBaseContext(), TimeLineActivity.class);
startActivity(myIntent);
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a ApplicationStatisticsFragment (defined as a static inner class below).
switch (position+1) {
case 1:
return DailyFragment.newInstance(position + 1);
case 2:
return WeeklyFragment.newInstance(position + 1);
case 3:
return MonthlyFragment.newInstance(position + 1);
case 4:
return YearlyFragment.newInstance(position + 1);
}
return null;
}
#Override
public int getCount() {
// Show 4 total pages.
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position+1) {
case 1:
return "Usage stats - Today";
case 2:
return "Usage stats - This Week";
case 3:
return "Usage stats - This Month";
case 4:
return "Usage stats - This Year";
}
return null;
}
}
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
Here's the most important part of it:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_activity_menu, menu);
Log.i("CATs", "THIS LOG APPEARS-> THE APP IS WORKING FINE TILL NOW.");
//THE APP IS WORKING FINE TILL HERE. PROBABLY onCreateOptionsMenu is NOT THE PROBLEM.
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.main_activity_action_settings) {
Intent myIntent = new Intent(getBaseContext(), SettingsActivity.class);
startActivity(myIntent);
return true;
}
if (id == R.id.main_activity_action_per_app_statistics) {
Intent myIntent = new Intent(getBaseContext(), ApplicationStatisticsActivity.class);
startActivity(myIntent);
return true;
}
if (id == R.id.main_activity_action_timeline) {
Intent myIntent = new Intent(getBaseContext(), TimeLineActivity.class);
startActivity(myIntent);
return true;
}
return super.onOptionsItemSelected(item);
}
Here's main_activity_menu.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.cats.timemanager.activities.MainActivity">
<item
android:id="#+id/main_activity_action_per_app_statistics"
android:orderInCategory="100"
android:title="#string/main_activity_action_per_app_statistics" />
<item
android:id="#+id/main_activity_action_timeline"
android:orderInCategory="101"
android:title="#string/main_activity_action_timeline" />
<item
android:id="#+id/main_activity_action_settings"
android:orderInCategory="102"
android:title="#string/main_activity_action_settings" />
</menu>
And here the layout activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.cats.timemanager.activities.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="#dimen/fab_margin"
android:tint="#color/white"
app:srcCompat="#drawable/apps_icon" />
</android.support.design.widget.CoordinatorLayout>
Why is it crashing that strange way?
Sorry the question is so long, you can just ignore the first code i posted cause i don't think the error is there (if there is any...).
For the brave souls who're trying to solve this error.
The menu kept crashing the application: so i decided to create a new project importing all the old files and I updated support libraries to v27.0.2 (from 25.3.1).
Worked on it for an hour or so: now when i launch the app it tells me it crashes WITHOUT throwing any error.
When I tap on "Close application", the app keeps working just fine and the menu works perfect.
TLDR
Just give up and
git checkout [olderVersionWithNoErrors]
Related
I created a setting activity. When the user clicks setting it move from mainactivity to settingsactivity but it does not go to the previous page when I click the back button at the top of the action bar it says app keeps stopping. If I click phone back button it works.
Here I attached my coding correct it. How can I do this?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
NavUtils.navigateUpFromSameTask(this);
}
return super.onOptionsItemSelected(item);
}
public static class SettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey)
{
setPreferencesFromResource(R.xml.root_preferences, rootKey);
}
}
It's preferred to use finish() in an activity, since it'll automatically go back to the last activity.
first, add to the tollbar in the XML file
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" >
<ImageView
android:id="#+id/home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_back"/>
</androidx.appcompat.widget.Toolbar>
and
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = new Intent(this, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
I am a newbie to Android development. I am learning UI designing as of now. I want a solution where there is a bottom bar with 5 options linked directly to 5 different activities. I got Java solutions from other stack overflow answers (How to change activity on bottom navigation button click? ) - 2nd Answer by sushil, but it has no activity - XML files in it for me to understand.
Bottom bar like this:
Activity to be loaded based on bottom bar:
As per your attached image, you should used Fragment instead of Activity for 5 different MenuItem or options to achieve your desired output.
1. Create 5 different Fragments for 5 different MenuItem.
For example: MatchingFragment, WatchListFragment, RatesFragment, DealsFragment and ListingFragment.
2. Add OnNavigationItemSelectedListener to your NavigationView and change Fragment as per your selected MenuItem. Use below code to change Fragment:
// Set action to perform when any menu-item is selected.
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
// Change Fragment
selectFragment(item);
return false;
}
});
/**
* Perform action when any item is selected.
*
* #param item Item that is selected.
*/
protected void selectFragment(MenuItem item) {
item.setChecked(true);
switch (item.getItemId()) {
case R.id.action_matching:
// Action to perform when Matching Menu item is selected.
pushFragment(new MatchingFragment());
break;
case R.id.action_watch_list:
// Action to perform when WatchList Menu item is selected.
pushFragment(new WatchListFragment());
break;
case R.id.action_rates:
// Action to perform when Rates Menu item is selected.
pushFragment(new RatesFragment());
break;
case R.id.action_deals:
// Action to perform when Deals Menu item is selected.
pushFragment(new DealsFragment());
break;
case R.id.action_listing:
// Action to perform when Listing Menu item is selected.
pushFragment(new ListingFragment());
break;
}
}
/**
* Method to push any fragment into given id.
*
* #param fragment An instance of Fragment to show into the given id.
*/
protected void pushFragment(Fragment fragment) {
if (fragment == null)
return;
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null) {
FragmentTransaction ft = fragmentManager.beginTransaction();
if (ft != null) {
ft.replace(R.id.rootLayout, fragment);
ft.commit();
}
}
}
Here is the complete Tutorial: Android Bottom Navigation View Tutorial With Example
Hope this will help~
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_favorites:
Intent intent1 = new Intent(this, AnActivity.class);
startActivity(intent1);
break;
case R.id.action_schedules:
Intent intent2 = new Intent(this, AnotherActivity.class);
startActivity(intent2);
break;
case R.id.action_music:
Intent intent3 = new Intent(this, AnotherActivity.class);
startActivity(intent3);
break;
}
return true;
}
});
Base Activity :
public abstract class BaseActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {
protected BottomNavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentViewId());
navigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation);
navigationView.setOnNavigationItemSelectedListener(this);
}
#Override
protected void onStart() {
super.onStart();
updateNavigationBarState();
}
// Remove inter-activity transition to avoid screen tossing on tapping bottom navigation items
#Override
public void onPause() {
super.onPause();
overridePendingTransition(0, 0);
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
navigationView.postDelayed(() -> {
int itemId = item.getItemId();
if (itemId == R.id.navigation_analysis) {
startActivity(new Intent(getApplicationContext(), AnalysisActivity.class));
} else if (itemId == R.id.navigation_dashboard) {
startActivity(new Intent(getApplicationContext(), DashboardActivity.class));
} else if (itemId == R.id.navigation_profile) {
startActivity(new Intent(getApplicationContext(), ProfileActivity.class));
}
finish();
}, 100);
return true;
}
private void updateNavigationBarState(){
int actionId = getNavigationMenuItemId();
selectBottomNavigationBarItem(actionId);
}
void selectBottomNavigationBarItem(int itemId) {
Menu menu = navigationView.getMenu();
for (int i = 0, size = menu.size(); i < size; i++) {
MenuItem item = menu.getItem(i);
boolean shouldBeChecked = item.getItemId() == itemId;
if (shouldBeChecked) {
item.setChecked(true);
break;
}
}
}
abstract int getContentViewId();
abstract int getNavigationMenuItemId();
}
Make sure to use getApplicationContext in onNavigationSelected().
Dashboard Activity:
public class DashboardActivity extends BaseActivity {
#Override
int getContentViewId() {
return R.layout.activity_dashboard ;
}
#Override
int getNavigationMenuItemId() {
return R.id.navigation_dashboard;
} }
Similarly - make the other activities just like this.
XML PART
bottom_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.BottomNavigationView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:menu="#menu/navigation"
/>
navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_analysis"
android:icon="#drawable/ic_home_black_24dp"
android:title="#string/title_analysis" />
<item
android:id="#+id/navigation_dashboard"
android:icon="#drawable/ic_dashboard_black_24dp"
android:title="#string/title_dashboard" />
<item
android:id="#+id/navigation_profile"
android:icon="#drawable/ic_notifications_black_24dp"
android:title="#string/title_profile" />
</menu>
activity_dashboard.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="#+id/frame_dashboard">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/title_dashboard"/>
</FrameLayout>
<include
layout="#layout/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
/>
</LinearLayout>
Similarly - make other xml files just like this.
This should hopefully help
I'm developing a material design app & I've declared an Exit Animation in MainActivity.
When I'm exiting by clicking back button, the animation is working, but upon exiting the app by tapping on back arrow which is on top left of Toolbar/AppBar, the animation is not working.
Here's MainActivity.java file's code:
public class MainActivity extends AppCompatActivity {
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
int normalTabTextColor = Color.parseColor("#64B5F6");
int selectedTabTextColor = Color.parseColor("#2196F3");
#Override
protected void onCreate(Bundle savedInstanceState) {
// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Call some material design APIs here
// enable transitions
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
} else {
// Implement this feature without material design
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitleTextColor(Color.parseColor("#2196F3"));
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setTabTextColors(normalTabTextColor, selectedTabTextColor);
tabLayout.setupWithViewPager(mViewPager);
/*FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});*/
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case R.id.action_profile:
// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setExitTransition(new Explode());
// Call some material design APIs here
Intent profileIntent = new Intent(MainActivity.this, ProfileActivity.class);
startActivity(profileIntent,
ActivityOptions
.makeSceneTransitionAnimation(this).toBundle());
} else {
// Implement this feature without material design
Intent profileIntent = new Intent(MainActivity.this, ProfileActivity.class);
startActivity(profileIntent);
}
break;
case R.id.action_support_development:
// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setExitTransition(new Explode());
// Call some material design APIs here
Intent supportDevelopmentIntent = new Intent(MainActivity.this, SupportDevelopmentActivity.class);
startActivity(supportDevelopmentIntent,
ActivityOptions
.makeSceneTransitionAnimation(this).toBundle());
} else {
// Implement this feature without material design
Intent supportDevelopmentIntent = new Intent(MainActivity.this, SupportDevelopmentActivity.class);
startActivity(supportDevelopmentIntent);
}
break;
case R.id.action_settings:
// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setExitTransition(new Explode());
// Call some material design APIs here
Intent settingsIntent = new Intent(MainActivity.this, SettingsActivity.class);
startActivity(settingsIntent,
ActivityOptions
.makeSceneTransitionAnimation(this).toBundle());
} else {
// Implement this feature without material design
Intent settingsIntent = new Intent(MainActivity.this, SettingsActivity.class);
startActivity(settingsIntent);
}
break;
case R.id.action_help:
// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setExitTransition(new Explode());
// Call some material design APIs here
Intent helpIntent = new Intent(MainActivity.this, HelpActivity.class);
startActivity(helpIntent,
ActivityOptions
.makeSceneTransitionAnimation(this).toBundle());
} else {
// Implement this feature without material design
Intent helpIntent = new Intent(MainActivity.this, HelpActivity.class);
startActivity(helpIntent);
}
break;
}
return super.onOptionsItemSelected(item);
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
// Show 2 total pages.
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Accept a Request";
case 1:
return "Post a Request";
}
return null;
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
}
I really don't know what is wrong here.
Please let me know!
Thanks in advance.
You have to handle the case for 'home' in onOptionsItemSelected function.
Add an entry in switch like below:
switch(id){
.....
case android.R.id.home:
supportFinishAfterTransition();
return true;
.....
}
Basically when you click the button on top, menuitem's id is android.R.id.home
and hence the exit animation should be handled here as well. See if it helps.
I just took the sample code shared by developer android site. I wanted to create a tabbed menu along with the option menu in the action bar. I want my activity to have the navigation tabs along with the action bar menu. I am not getting the action bar menu. But i have seen the applications which have navigation tabs as well as the action bar menu items as well. Please if someone helps me that would be of great help.
MainActivity Class
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
AppSectionsPagerAdapter mAppSectionsPagerAdapter;
/**
* The {#link ViewPager} that will display the three primary sections of the app, one at a
* time.
*/
ViewPager mViewPager;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the adapter that will return a fragment for each of the three primary sections
// of the app.
mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager());
// Set up the action bar.
final ActionBar actionBar = getActionBar();
// Specify that the Home/Up button should not be enabled, since there is no hierarchical
// parent.
actionBar.setHomeButtonEnabled(true);
// Specify that we will be displaying tabs in the action bar.
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
// Set up the ViewPager, attaching the adapter and setting up a listener for when the
// user swipes between sections.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mAppSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// When swiping between different app sections, select the corresponding tab.
// We can also use ActionBar.Tab#select() to do this if we have a reference to the
// Tab.
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by the adapter.
// Also specify this Activity object, which implements the TabListener interface, as the
// listener for when this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mAppSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.template_actvity, menu);
Toast.makeText(getApplicationContext(), "Indie onCreateOptionsMenu", Toast.LENGTH_SHORT).show();
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
return super.onOptionsItemSelected(item);
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to one of the primary
* sections of the app.
*/
public static class AppSectionsPagerAdapter extends FragmentPagerAdapter {
public AppSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
// The first section of the app is the most interesting -- it offers
// a launchpad into the other demonstrations in this example application.
return new LaunchpadSectionFragment();
default:
// The other sections of the app are dummy placeholders.
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, i + 1);
fragment.setArguments(args);
return fragment;
}
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
return "Section " + (position + 1);
}
}
/**
* A fragment that launches other parts of the demo application.
*/
public static class LaunchpadSectionFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_section_launchpad, container, false);
// Demonstration of a collection-browsing activity.
rootView.findViewById(R.id.demo_collection_button)
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), CollectionDemoActivity.class);
startActivity(intent);
}
});
// Demonstration of navigating to external activities.
rootView.findViewById(R.id.demo_external_activity)
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Create an intent that asks the user to pick a photo, but using
// FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, ensures that relaunching
// the application from the device home screen does not return
// to the external activity.
Intent externalActivityIntent = new Intent(Intent.ACTION_PICK);
externalActivityIntent.setType("image/*");
externalActivityIntent.addFlags(
Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
startActivity(externalActivityIntent);
}
});
return rootView;
}
}
/**
* A dummy fragment representing a section of the app, but that simply displays dummy text.
*/
public static class DummySectionFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "section_number";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_section_dummy, container, false);
Bundle args = getArguments();
((TextView) rootView.findViewById(android.R.id.text1)).setText(
getString(R.string.dummy_section_text, args.getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
}
Activity_main XML File
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
template_activity Menu XML
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="#+id/addTemplate"
android:orderInCategory="100"
android:icon="#drawable/ic_action_new"
android:title="Add Template"
app:showAsAction="always"/>
Here are some things to try:
I assume that in your template_activity.xml you remembered to include the </menu> tag? (You might have only missed copying+pasting it into your question).
Try using this code in your activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.template_activity, menu);
return true;
}
Note: You may also have a possible typo in your getMenuInflater().inflate(R.menu.template_actvity, menu); line. Specifically, you misspelled "activity".
Edit: Try the following XML for your menu XML file:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity" >
<item
android:id="#+id/addTemplate"
android:orderInCategory="1"
android:icon="#drawable/ic_action_new"
android:title="Add Template"
android:showAsAction="always"/>
</menu>
As for getting the "three dot" overflow button, I realize now that you are using a device with a built-in menu button. It is intentional that devices with these don't include the overflow buttons. However, if you still want to implement this, you can read more about it here.
I am not going to list every reference I've read through before posting this, but I have extensively read similar questions on stackoverflow and all of the android developer docs on activity/fragment lifecycles and maintaining state and have not found a solution.
Here is my scenario:
I have a main activity (ImpulseActivity) that uses a FragmentPagerAdapter. Each fragment displays a separate list of data that I am retrieving from the server. When pressing an action_item in ImpulseActivity's actionbar, you can filter data sent from the server. To accomplish this, ImpulseActivity launches a separate activity (FilterEventsActivity). FilterEventsActivity lists ImpulseActivity as it's parent activity. When pressing the back button on FilterEventsActivity, ImpulseActivity is recreated (OnCreate called) with a null (Bundle savedInstanceState). For testing purposes, I am overriding OnSaveInstanceState and placing fake data in outState. Note that this happens for every activity launched from ImpulseActivity.
My question is:
What is the proper design paradigm to prevent each fragment from needing to reload data in this particular situation? I would prefer not to use the Singleton pattern since my fragments are reused in other activities.
Relevant source code if needed:
public class ImpulseActivity extends FragmentActivity implements
ActionBar.TabListener {
private MapSearchFragment mSearchFragment;
private BulletinFragment mBulletinFragment;
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.impulse_activity);
Log.v("ImpulseActivity", "onCreate " + savedInstanceState);
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
CategoryManager manager = CategoryManager.getManager();
manager.setListener(this);
manager.loadCategories();
mSectionsPagerAdapter = new SectionsPagerAdapter(
getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager
.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putDouble("Hello", 1.02);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.impulse_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_create) {
return true;
}
if (id == R.id.action_filter) {
Intent intent = new Intent(this, FilterEventsActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
int position = tab.getPosition();
mViewPager.setCurrentItem(position, true);
}
#Override
public void onEventListClick(Event e) {
Intent mIntent = new Intent(this, EventActivity.class);
Bundle mBundle = new Bundle();
mBundle.putSerializable(EventDetailsFragment.Event_Key, e);
mIntent.putExtras(mBundle);
startActivity(mIntent);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment;
switch(position) {
case 0:
if (mBulletinFragment != null) {
fragment = mBulletinFragment;
} else {
fragment = new BulletinFragment();
mBulletinFragment = (BulletinFragment) fragment;
}
break;
case 1:
fragment = new MapSearchFragment();
mSearchFragment = (MapSearchFragment) fragment;
break;
case 2:
fragment = new MyEventsFragment();
break;
default:
fragment = new BulletinFragment();
break;
}
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return "Bulletin";
case 1:
return "Map";
case 2:
return "My Events";
default:
return "Test";
}
}
}
}
AndroidManifest.xml
<activity
android:name=".Home.ImpulseActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Event.EventActivity"
android:label="#string/title_activity_event"
android:parentActivityName=".Home.ImpulseActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".Home.ImpulseActivity" />
</activity>
Although the question mentions Fragments, the problem is actually with up navigation.
The default implementation for up navigation doesn't work exactly as one would expect for standard activties. In particular, when the parent activity has launchMode="standard" (the default), pressing the up button will create a new instance of it, not return to the previous one.
There are two alternatives for solving this problem:
Changing the launchMode of ImpulseActivity to singleTop in the Manifest.
Overriding the home button action to launch the intent with the FLAG_ACTIVITY_CLEAR_TOP flag. For example, in EventActivity.onOptionsItemSelected():
if (id == android.R.id.home)
{
Intent intent = NavUtils.getParentActivityIntent(this);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(this, intent);
return true;
}
Either of these will bring your old activity to the top of the stack.
if your fragments have layout just like activity example mainlayout.xml
you can use intent for open each fragment with same details and dont use onstop(); pack create intent and intent flags in the main fragment activity