I have an activity in which I have Tablayout and have two tab named as "Deal","Story" when I navigate to other activity and again resume to that activity
then that tab was appears which I had viewed earlier,while I want whenever I resumed to that activity always show default tab .How can I DO THAT
code:-
public void init() {
s_oCloginSession = new CLoginSessionManagement(CMainActivity.this);// object creation of Login Session...
setupToolbar();// setting toolbar
// navigation bar code
m_Drawer = (DrawerLayout) findViewById(R.id.drawer_layout);//finding id of drawerlayout
s_drawerToggle = new ActionBarDrawerToggle(
this, m_Drawer, m_Toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
m_Drawer.setDrawerListener(s_drawerToggle);
m_Drawer.setScrimColor(getResources().getColor(android.R.color.transparent));
s_drawerToggle.syncState();
NavigationView m_Navigation = (NavigationView) findViewById(R.id.nav_view);
m_Navigation.setNavigationItemSelectedListener(this);
m_TabLayout = (TabLayout) findViewById(R.id.tab_layout);// finding Id of tablayout
m_TabLayout.addTab(m_TabLayout.newTab().setText("Deals"));// add deal listin tab
m_TabLayout.addTab(m_TabLayout.newTab().setText("Stories"));// add stories tab
m_TabLayout.setTabGravity(TabLayout.GRAVITY_FILL);// setting Gravity of Tab
m_ViewPager = (ViewPager) findViewById(R.id.pager);//finding Id of ViewPager
CDealMainListingPager m_oDealMainScreenPager = new CDealMainListingPager
(getSupportFragmentManager(), m_TabLayout.getTabCount());
m_ViewPager.setAdapter(m_oDealMainScreenPager);// adiing adapter to ViewPager
m_ViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(m_TabLayout));// performing action of page changing
m_TabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
m_ViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
You can create one class named BaseActivity which extends AppCompatActivity. All your activity will now extend to this BaseActivity class instead of AppCompatActivity. So whenever you have not defined onBackPressed it will call it's parent class method and perform it's operations.
public class BaseActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onBackPressed() {
super.onBackPressed();
overridePendingTransition(R.anim.translate, R.anim.left_to_right_simple);
}
}
If you want to customise this method for one class then just need to override this method in that respective class. For other classes it will work same as defined in BaseActivity
Your all activity will be something like this.
public class HomeScreen extends BaseActivity{
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Make a class, say CommonMethods and put the method into that class:
public class CommonMethods extends AppCompatActivity {
/*This method functions when user press device back button*/
#Override
public void onBackPressed() {
long currentTime = System.currentTimeMillis();
if ((currentTime - lastPressTime) < 2000) {
// Double Press
moveTaskToBack(true);
} else {
Toast.makeText(this, "Press again to exit", Toast.LENGTH_SHORT).show();
lastPressTime = currentTime;
}
}
}
Here, you can make this class extend Activity or AppCompatActivity based on your needs.
Finally, you can make the activity classes which need this feature, extend this CommonMethods class.
You can do this by taking one common class and implement this function in it,
Check below code,
Take one common class for method
//Here I am taking it as common class you can take it as per your choice
CommonClass.java
public class CommonClass
{
public bool manageBackPressed(Activity activity, long lastPressTime)
{
long currentTime = System.currentTimeMillis();
if ((currentTime - lastPressTime) < 2000) {
return true;
} else {
return false;
}
return false;
}
}
Now below check your onBackPressed method in any activity
#Override
public void onBackPressed() {
if(commonClass.manageBackPressed(this, lastPressTime))
{
moveTaskToBack(true);
}
else
{
Toast.makeText(this, "Press again to exit", Toast.LENGTH_SHORT).show();
lastPressTime = System.currentTimeMillis();
}
}
I think your previous thread will also work in background please cancel it when you dont want to update.
Related
I've implemented the newest appcompat library and using the Toolbar as action bar. But the problem is I cannot catch the home button / hamburger icon click event. I've tried and looked everything but doesn't seem to find a similar problem.
This is my Activity class :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Set up the drawer.
navDrawerFragment =
(NavigationDrawerFragment) getSupportFragmentManager()
.findFragmentById(R.id.navigation_drawer);
navDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout),
toolbar);
}
And this is my NavigationDrawerFragment class :
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
currentSelectedPosition = savedInstanceState.getInt(
STATE_SELECTED_POSITION);
fromSavedInstanceState = true;
}
// Select either the default item (0) or the last selected item.
selectItem(currentSelectedPosition);
}
#Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Indicate that this fragment would like
// to influence the set of actions in the action bar.
setHasOptionsMenu(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
drawerListView = (ListView) inflater.inflate(
R.layout.fragment_navigation_drawer, container, false);
drawerListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent,
View view, int position, long id) {
selectItem(position);
}
});
//mDrawerListView.setAdapter();
//mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
return drawerListView;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {
fragmentContainerView = getActivity().findViewById(fragmentId);
this.drawerLayout = drawerLayout;
// set a custom shadow that overlays the main
// content when the drawer opens
drawerLayout.setDrawerShadow(
R.drawable.drawer_shadow, GravityCompat.START);
// set up the drawer's list view
// with items and click listener
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the navigation drawer and the action bar app icon.
drawerToggle = new ActionBarDrawerToggle(
getActivity(),
drawerLayout,
toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
}
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
// If the user hasn't 'learned' about the drawer,
// open it to introduce them to the drawer,
// per the navigation drawer design guidelines.
if (!userLearnedDrawer && !fromSavedInstanceState) {
drawerLayout.openDrawer(fragmentContainerView);
}
// Defer code dependent on restoration of previous instance state.
drawerLayout.post(new Runnable() {
#Override
public void run() {
drawerToggle.syncState();
}
});
drawerLayout.setDrawerListener(drawerToggle);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Forward the new configuration the drawer toggle component.
drawerToggle.onConfigurationChanged(newConfig);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("cek", "item selected");
if (drawerToggle.onOptionsItemSelected(item)) {
Log.d("cek", "home selected");
return true;
}
return super.onOptionsItemSelected(item);
}
when I clicked a menu item, the log "item selected" gets called. But when I click on the home button, it opens navigation drawer but the log "home selected" never get called. I've set onOptionsItemSelected method inside my Activity as well, but it still doesn't get called.
If you want to know when home is clicked is an AppCompatActivity then you should try it like this:
First tell Android you want to use your Toolbar as your ActionBar:
setSupportActionBar(toolbar);
Then set Home to be displayed via setDisplayShowHomeEnabled like this:
getSupportActionBar().setDisplayShowHomeEnabled(true);
Finally listen for click events on android.R.id.home like usual:
#Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() == android.R.id.home) {
Timber.d("Home pressed");
}
return super.onOptionsItemSelected(menuItem);
}
If you want to know when the navigation button is clicked on a Toolbar in a class other than AppCompatActivity you can use these methods to set a navigation icon and listen for click events on it. The navigation icon will appear on the left side of your Toolbar where the the "home" button used to be.
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_nav_back));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("cek", "home selected");
}
});
If you want to know when the hamburger is clicked and when the drawer opens, you're already listening for these events via onDrawerOpened and onDrawerClosed so you'll want to see if those callbacks fit your requirements.
mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// event when click home button
}
});
in mycase this code work perfect
This is how I do it to return to the right fragment otherwise if you have several fragments on the same level it would return to the first one if you donĀ“t override the toolbar back button behavior.
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
I think the correct solution with support library 21 is the following
// action_bar is def resource of appcompat;
// if you have not provided your own toolbar I mean
Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
if (toolbar != null) {
// change home icon if you wish
toolbar.setLogo(this.getResValues().homeIconDrawable());
toolbar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//catch here title and home icon click
}
});
}
I have handled back and Home button in Navigation Drawer like
public class HomeActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private ActionBarDrawerToggle drawerToggle;
private DrawerLayout drawerLayout;
NavigationView navigationView;
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
resetActionBar();
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(this);
//showing first fragment on Start
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).replace(R.id.content_fragment, new FirstFragment()).commit();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//listener for home
if(id==android.R.id.home)
{
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
onBackPressed();
else
drawerLayout.openDrawer(navigationView);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START))
drawerLayout.closeDrawer(GravityCompat.START);
else
super.onBackPressed();
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Begin the transaction
Fragment fragment = null;
// Handle navigation view item clicks here.
int id = item.getItemId();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (id == R.id.nav_companies_list) {
fragment = new FirstFragment();
// Handle the action
}
// Begin the transaction
if(fragment!=null){
if(item.isChecked()){
if(getSupportFragmentManager().getBackStackEntryCount()==0){
drawer.closeDrawers();
}else{
removeAllFragments();
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}else{
removeAllFragments();
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}
return true;
}
public void removeAllFragments(){
getSupportFragmentManager().popBackStackImmediate(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
public void replaceFragment(final Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.replace(R.id.WikiCompany, fragment).addToBackStack("")
.commit();
}
public void updateDrawerIcon() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
try {
Log.i("", "BackStackCount: " + getSupportFragmentManager().getBackStackEntryCount());
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
drawerToggle.setDrawerIndicatorEnabled(false);
else
drawerToggle.setDrawerIndicatorEnabled(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 50);
}
public void resetActionBar()
{
//display home
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
public void setActionBarTitle(String title) {
getSupportActionBar().setTitle(title);
}
}
and In each onViewCreated I call
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((HomeActivity)getActivity()).updateDrawerIcon();
((HomeActivity) getActivity()).setActionBarTitle("List");
}
This is how I implemented it pre-material design and it seems to still work now I've switched to the new Toolbar. In my case I want to log the user in if they attempt to open the side nav while logged out, (and catch the event so the side nav won't open). In your case you could not return true;.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!isLoggedIn() && item.getItemId() == android.R.id.home) {
login();
return true;
}
return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}
I changed the DrawerLayout a bit to get the events and be able to consume and event, such as if you want to use the actionToggle as back if you are in detail view:
public class ListenableDrawerLayout extends DrawerLayout {
private OnToggleButtonClickedListener mOnToggleButtonClickedListener;
private boolean mManualCall;
public ListenableDrawerLayout(Context context) {
super(context);
}
public ListenableDrawerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListenableDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Sets the listener for the toggle button
*
* #param mOnToggleButtonClickedListener
*/
public void setOnToggleButtonClickedListener(OnToggleButtonClickedListener mOnToggleButtonClickedListener) {
this.mOnToggleButtonClickedListener = mOnToggleButtonClickedListener;
}
/**
* Opens the navigation drawer manually from code<br>
* <b>NOTE: </b>Use this function instead of the normal openDrawer method
*
* #param drawerView
*/
public void openDrawerManual(View drawerView) {
mManualCall = true;
openDrawer(drawerView);
}
/**
* Closes the navigation drawer manually from code<br>
* <b>NOTE: </b>Use this function instead of the normal closeDrawer method
*
* #param drawerView
*/
public void closeDrawerManual(View drawerView) {
mManualCall = true;
closeDrawer(drawerView);
}
#Override
public void openDrawer(View drawerView) {
// Check for listener and for not manual open
if (!mManualCall && mOnToggleButtonClickedListener != null) {
// Notify the listener and behave on its reaction
if (mOnToggleButtonClickedListener.toggleOpenDrawer()) {
return;
}
}
// Manual call done
mManualCall = false;
// Let the drawer layout to its stuff
super.openDrawer(drawerView);
}
#Override
public void closeDrawer(View drawerView) {
// Check for listener and for not manual close
if (!mManualCall && mOnToggleButtonClickedListener != null) {
// Notify the listener and behave on its reaction
if (mOnToggleButtonClickedListener.toggleCloseDrawer()) {
return;
}
}
// Manual call done
mManualCall = false;
// Let the drawer layout to its stuff
super.closeDrawer(drawerView);
}
/**
* Interface for toggle button callbacks
*/
public static interface OnToggleButtonClickedListener {
/**
* The ActionBarDrawerToggle has been pressed in order to open the drawer
*
* #return true if we want to consume the event, false if we want the normal behaviour
*/
public boolean toggleOpenDrawer();
/**
* The ActionBarDrawerToggle has been pressed in order to close the drawer
*
* #return true if we want to consume the event, false if we want the normal behaviour
*/
public boolean toggleCloseDrawer();
}
}
The easiest approach we could do is change the home icon to a known icon and compare drawables (because android.R.id.home icon can differ to different api versions
so set a toolbar as actionbar
SetSupportActionBar(_toolbar);
_toolbar.NavigationIcon = your_known_drawable_here;
for (int i = 0; i < _toolbar.ChildCount; i++)
{
View v = _toolbar.GetChildAt(i);
if (v is ImageButton)
{
ImageButton imageButton = v as ImageButton;
if (imageButton.Drawable.GetConstantState().Equals(_bookMarkIcon.GetConstantState()))
{
//here v is the widget that contains the home icon you can add your click events here
}
}
}
In my case I had to put the icon using:
toolbar.setNavigationIcon(R.drawable.ic_my_home);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
And then listen to click events with default onOptionsItemSelected and android.R.id.home id
For anyone looking for a Xamarin implementation (since events are done differently in C#), I simply created this NavClickHandler class as follows:
public class NavClickHandler : Java.Lang.Object, View.IOnClickListener
{
private Activity mActivity;
public NavClickHandler(Activity activity)
{
this.mActivity = activity;
}
public void OnClick(View v)
{
DrawerLayout drawer = (DrawerLayout)mActivity.FindViewById(Resource.Id.drawer_layout);
if (drawer.IsDrawerOpen(GravityCompat.Start))
{
drawer.CloseDrawer(GravityCompat.Start);
}
else
{
drawer.OpenDrawer(GravityCompat.Start);
}
}
}
Then, assigned a custom hamburger menu button like this:
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetDefaultDisplayHomeAsUpEnabled(false);
this.drawerToggle.DrawerIndicatorEnabled = false;
this.drawerToggle.SetHomeAsUpIndicator(Resource.Drawable.MenuButton);
And finally, assigned the drawer menu toggler a ToolbarNavigationClickListener of the class type I created earlier:
this.drawerToggle.ToolbarNavigationClickListener = new NavClickHandler(this);
And then you've got a custom menu button, with click events handled.
Try this code
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home){
//You can get
}
return super.onOptionsItemSelected(item);
}
Add below code to your onCreate() metod
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
Apart from the answer provided by MrEngineer13, there is also another possible reason why the click event might not have been captured in the onOptionsSelected method. Your DrawerLayout may have overlayed your Toolbar's interface component in the layout XML file. Therefore, whenever you attempt to click the Home button, you're only clicking the DrawerLayout, but not the Home button that's located beneath it.
All you have to do now is rearrange your Toolbar in the corresponding layout XML file so that it is not blocked by any other UI component.
Programmatically, I did attempt to call the bringToFront() method on the toolbar (toolbar.bringToFront()). However, in my app's context, it does not seem to be the solution.
Background:
I have a FragmentActivity that uses a DrawerLayout. I created a class called NavDrawerManager to abstract out the code for dealing with the drawer layout. To construct this object, I need to pass in and keep a reference to an Activity. I use this activity reference to call findViewById(), and I also use the activity as a context when creating a list adapter, etc. I keep a reference to a NavDrawerManager object in my activity so I can perform callbacks and operations on the drawer layout.
UPDATE: Per Xaver's suggestion, I switched to extend FragmentActivity into a NavDrawerActivity. Instead of having a NavDrawerManager object in my activity, the superclass handles the nav drawer code. See updated code.
Issue:
Everything works fine until I change orientations. After changing orientations, it appears that my NavDrawerActivity still references the old layout. I say this because I have a progress bar and a couple of buttons in the DrawerLayout that I am attempting to update, but they don't reflect the updates.
When I call Activity.findViewById() to get the progress bar and make it visible, it doesn't show any changes, nor do any of the changes to the buttons show. Note: Activity.findViewById() does not return null. However, if I do the same things before changing orientation, the progress bar and buttons show the appropriate changes.
Code:
NavDrawerActivity:
public class NavDrawerActivity extends LowProfileFragmentActivity {
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private ExpandableListView mDrawerList;
private NavDrawerAdapter mListAdapter;
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
mDrawerToggle.onOptionsItemSelected(item);
return super.onOptionsItemSelected(item);
}
//Called via subclass after setContentView
protected void setupNavDrawer() {
initDrawerLayout();
initDrawerList();
setButton1();
setButton2();
}
private void initDrawerLayout() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = getActionBarDrawerToggle();
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
private void initDrawerList() {
mDrawerList = (ExpandableListView) mDrawerLayout
.findViewById(android.R.id.list);
mListAdapter = getNavDrawerAdapter();
}
private ActionBarDrawerToggle getActionBarDrawerToggle() {
return new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_navigation_drawer, 0, 0) {
public void onDrawerClosed(View view) {
}
public void onDrawerOpened(View view) {
}
};
}
public void setDrawerLoading(boolean loading) {
ProgressBar progressBar = (ProgressBar) mDrawerLayout
.findViewById(R.id.progress_bar);
Button button1 = (Button) this.findViewById(R.id.button1);
Button button2 = (Button) this
.findViewById(R.id.button2);
/* None of the below changes appear after changing orientation */
if (loading) {
button1.setEnabled(false);
button2.setEnabled(false);
progressBar.setVisibility(View.VISIBLE);
} else {
progressBar.setVisibility(View.GONE);
button1.setEnabled(true);
button2.setEnabled(true);
}
}
private void setButton1() {
Button button1 = (Button) this.findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//do something
}
});
}
private void setButton2() {
Button button2 = (Button) this
.findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//do something
}
});
}
}
ExampleActivity:
public class ExampleActivity extends NavDrawerActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initUI();
}
private void initUI() {
setContentView(R.layout.activity_sift);
// Call the superclass method to set up the nav drawer
setupNavDrawer();
}
}
AndroidManifest.xml:
<activity
android:name="com.example.app.ExampleActivity"
android:label="#string/app_name"
android:launchMode="singleTop"
android:theme="#style/AppTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Wouldn't it be easier if you implemented a NavDrawerActivity instead of a NavDrawerManager? Generally things like this should be avoided. The UI should be handled solely by the Fragments or Activities themselves.
I understand why you would want to create such a NavDrawerManager, simply to make the whole thing reusable and a lot of abstraction is great, but when it is overdone it can become a problem. Don't focus so much on everything being perfectly abstracted and according to OOP standards. There is nothing wrong with an Activity having both a NavigationDrawer and hiding the notification bar. And if you already have an Activity that implements one of those two things you should extend it. Your only other option would be to reimplement the same behaviour in a second Activity and that would pretty much defeat the purpose of abstraction.
EDIT: I have refactored and improved your code, you really should not have so many different methods for everything, all the setup belongs in onCreate(), that you write extra methods for each step just introduces the possibility for additional errors. Try this:
public abstract class NavDrawerActivity extends LowProfileFragmentActivity {
private ActionBarDrawerToggle drawerToggle;
private DrawerLayout drawerLayout;
private ProgressBar progressBar;
private Button button1;
private Button button2;
private ExpandableListView drawerList;
private NavDrawerAdapter drawerListAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayout());
this.drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
this.drawerToggle = new ActionBarDrawerToggle(this, this.drawerLayout, R.drawable.icon_drawer, R.string.drawer_open, R.string.drawer_close);
this.drawerLayout.setDrawerListener(this.drawerToggle);
this.drawerList = (ExpandableListView) this.drawerLayout.findViewById(android.R.id.list);
this.progressBar = (ProgressBar) this.drawerLayout.findViewById(R.id.progress_bar);
this.button1 = (Button) findViewById(R.id.button1);
this.button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something
}
});
this.button2 = (Button) findViewById(R.id.button2);
this.button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something
}
});
this.drawerListAdapter = new NavDrawerAdapter(...);
this.drawerList.setAdapter(this.drawerListAdapter);
}
protected abstract int getLayout();
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
this.drawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
this.drawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return this.drawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}
public void setDrawerLoading(boolean loading) {
this.button1.setEnabled(!loading);
this.button2.setEnabled(!loading);
this.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
}
}
As you can see I use an abstract method called getLayout() to pass the correct layout to setContentView(). getLayout() has to be implemented by all Activities which extend the NavDrawerActivity therfore giving the sub Activities control over the used layout.
As such your ExampleActivity should look like this:
public class ExampleActivity extends NavDrawerActivity {
#Override
protected int getLayout() {
return R.layout.activity_sift;
}
}
I tested everything and it's working for me.
I am using a navigation drawer in my main activity defined as
private DrawerLayout drawerlayout;
I am using it in main activity to open and close my nav fragment, but there are 3 specific buttons in nav fragment class where I would like to use the nav fragment functionality drawerlayout.closedrawer(r.id.drawer)
But everytime I define it again in nav fragment class and try to add it in the onclick for these buttons, upon clicking the buttons, the app crashes with a nullpointer exception.How do I go about the same?
Thanks!
Here's the sample code from my app:
public class navfragment extends fragment {
public interface OnCloseDrawerListener
{
void onCloseDrawer();
}
#Override
public void onClick(final View v) {
switch (v.getId()) {
case R.id.button_logout:
final DialogFragment dialog = new LogoutCancelSignoutDialogFragment(mLogoutListener);
dialog.show(getActivity().getSupportFragmentManager(), AbsBaseaActivity.TAG_LOGOUT_DIALOG);
BangoHelper.eventLogout();
((OnCloseDrawerListener)getActivity()).onCloseDrawer();
break;
}
}
In my class MainActivity:
public class MainActivity extends AbsBaseaActivity implements OnBackStackChangedListener {
private DrawerLayout drawerLayout;
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
//----------Code for Navigation Drawer setup
// 2. App Icon
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// 2.1 create ActionBarDrawerToggle
actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
R.drawable.arrow_up, R.string.drawer_open, R.string.drawer_close){
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
// getActionBar().setTitle(NavigationPanelFragment.activeFragmentTitle);
// invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
// getActionBar().setTitle(NavigationPanelFragment.activeFragmentTitle);
// invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
// 2.2 Set actionBarDrawerToggle as the DrawerListener
drawerLayout.setDrawerListener(actionBarDrawerToggle);
}
public void onCloseDrawer()
{
drawerLayout.closeDrawer(R.id.drawer);
}
Even after modifying the code as per the given suggestion it crashes when I click on the button defined onclick for the fragment class, any clue?
You could add a callback from your fragment to your activity to close the drawer..
Ex.
public class YourFragment extends Fragment
{
public void onClick(View v)
{
((OnCloseDrawerListener)getActivity()).onCloseDrawer();
}
public interface OnCloseDrawerListener
{
void onCloseDrawer();
}
}
Then in your activity you would need to implement this interface
public class MyActivity extends Activity implements OnCloseDrawerListener
{
#Override
public void onCloseDrawer()
{
// add whatever code you need to close the drawer
}
}
Obviously you can name this interface something that more accurately represents your needs and pass it whatever arguments you require
I'm using the Google DrawerLayout.
When an item gets clicked, the drawer is smoothly closed and an Activity will be launched. Turning these activities into Fragments is not an option. Because of this, launching an activity and then closing the drawer is also not an option. Closing the drawer and launching the activity at the same time will make the closing animation stutter.
Given that I want to smoothly close it first, and then launch the activity, I have a problem with the latency between when a user clicks on the drawer item, and when they see the activity they wanted to go to.
This is what the click listener for each item looks like.
final View.OnClickListener mainItemClickListener = new View.OnClickListener() {
#Override
public void onClick(final View v) {
mViewToLaunch = v;
mDrawerLayout.closeDrawers();
}
};
My activity is also the DrawerListener, its onDrawerClosed method looks like:
#Override
public synchronized void onDrawerClosed(final View view) {
if (mViewToLaunch != null) {
onDrawerItemSelection(mViewToLaunch);
mViewToLaunch = null;
}
}
onDrawerItemSelection just launches one of the five activities.
I do nothing on onPause of the DrawerActivity.
I am instrumenting this and it takes on average from 500-650ms from the moment onClick is called, to the moment onDrawerClosed ends.
There is a noticeable lag, once the drawer closes, before the corresponding activity is launched.
I realize a couple of things are happening:
The closing animation takes place, which is a couple of milliseconds right there (let's say 300).
Then there's probably some latency between the drawer visually closing and its listener getting fired. I'm trying to figure out exactly how much of this is happening by looking at DrawerLayout source but haven't figured it out yet.
Then there's the amount of time it takes for the launched activity to perform its startup lifecycle methods up to, and including, onResume. I have not instrumented this yet but I estimate about 200-300ms.
This seems like a problem where going down the wrong path would be quite costly so I want to make sure I fully understand it.
One solution is just to skip the closing animation but I was hoping to keep it around.
How can I decrease my transition time as much as possible?
According the docs,
Avoid performing expensive operations such as layout during animation as it can cause stuttering; try to perform expensive operations during the STATE_IDLE state.
Instead of using a Handler and hard-coding the time delay, you can override the onDrawerStateChanged method of ActionBarDrawerToggle (which implements DrawerLayout.DrawerListener), so that you can perform the expensive operations when the drawer is fully closed.
Inside MainActivity,
private class SmoothActionBarDrawerToggle extends ActionBarDrawerToggle {
private Runnable runnable;
public SmoothActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, Toolbar toolbar, int openDrawerContentDescRes, int closeDrawerContentDescRes) {
super(activity, drawerLayout, toolbar, openDrawerContentDescRes, closeDrawerContentDescRes);
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
invalidateOptionsMenu();
}
#Override
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
invalidateOptionsMenu();
}
#Override
public void onDrawerStateChanged(int newState) {
super.onDrawerStateChanged(newState);
if (runnable != null && newState == DrawerLayout.STATE_IDLE) {
runnable.run();
runnable = null;
}
}
public void runWhenIdle(Runnable runnable) {
this.runnable = runnable;
}
}
Set the DrawerListener in onCreate:
mDrawerToggle = new SmoothActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.open, R.string.close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
Finally,
private void selectItem(int position) {
switch (position) {
case DRAWER_ITEM_SETTINGS: {
mDrawerToggle.runWhenIdle(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
startActivity(intent);
}
});
mDrawerLayout.closeDrawers();
break;
}
case DRAWER_ITEM_HELP: {
mDrawerToggle.runWhenIdle(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MainActivity.this, HelpActivity.class);
startActivity(intent);
}
});
mDrawerLayout.closeDrawers();
break;
}
}
}
I was facing same issue with DrawerLayout.
I have research for that and then find one nice solution for it.
What i am doing is.....
If you refer Android Sample app for the DrawerLayout then check the code for selectItem(position);
In this function based on the position selection fragment is called. I have modify it with below code as per my need and works fine with no animation close stutter.
private void selectItem(final int position) {
//Toast.makeText(getApplicationContext(), "Clicked", Toast.LENGTH_SHORT).show();
mDrawerLayout.closeDrawer(drawerMain);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Fragment fragment = new TimelineFragment(UserTimeLineActivity.this);
Bundle args = new Bundle();
args.putInt(TimelineFragment.ARG_PLANET_NUMBER, position);
fragment.setArguments(args);
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// update selected item and title, then close the drawer
mCategoryDrawerList.setItemChecked(position, true);
setTitle("TimeLine: " + mCategolyTitles[position]);
}
}, 200);
// update the main content by replacing fragments
}
Here i am first closing the DrawerLayout. which takes approx 250 miliseconds. and then my handler will call the fragment. Which works smooth and as per the requirement.
Hope it will also helpful to you.
Enjoy Coding... :)
So I seem to have solved the problem with a reasonable solution.
The largest source of perceivable latency was the delay between when the drawer was visually closed, and when onDrawerClosed was called. I solved this by posting a Runnable to a private Handler that launches the intended activity at some specified delay. This delay is chosen to correspond with the drawer closing.
I tried to do the launching onDrawerSlide after 80% progress, but this has two problems. The first was that it stuttered. The second was that if you increased the percentage to 90% or 95% the likelihood that it wouldn't get called at all due to the nature of the animation increased--and you then had to fall back to onDrawerClosed, which defeats the purpose.
This solution has the possibility to stutter, specially on older phones, but the likelihood can be reduced to 0 simply by increasing the delay high enough. I thought 250ms was a reasonable balance between stutter and latency.
The relevant portions of the code look like this:
public class DrawerActivity extends SherlockFragmentActivity {
private final Handler mDrawerHandler = new Handler();
private void scheduleLaunchAndCloseDrawer(final View v) {
// Clears any previously posted runnables, for double clicks
mDrawerHandler.removeCallbacksAndMessages(null);
mDrawerHandler.postDelayed(new Runnable() {
#Override
public void run() {
onDrawerItemSelection(v);
}
}, 250);
// The millisecond delay is arbitrary and was arrived at through trial and error
mDrawerLayout.closeDrawer();
}
}
Google IOsched 2015 runs extremely smoothly (except from settings) the reason for that is how they've implemented the drawer and how they launch stuff.
First of they use handler to launch delayed:
// launch the target Activity after a short delay, to allow the close animation to play
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
goToNavDrawerItem(itemId);
}
}, NAVDRAWER_LAUNCH_DELAY);
with delay being:
private static final int NAVDRAWER_LAUNCH_DELAY = 250;
Another thing they do is to remove animations from the activities that are launched with following code inside the activities onCreate():
overridePendingTransition(0, 0);
To view the source go to git.
I'm using approach like below. Works smoothly.
public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener {
private DrawerLayout drawerLayout;
private MenuItem menuItemWaiting;
/* other stuff here ... */
private void setupDrawerLayout() {
/* other stuff here ... */
drawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
if(menuItemWaiting != null) {
onNavigationItemSelected(menuItemWaiting);
}
}
});
}
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItemWaiting = null;
if(drawerLayout.isDrawerOpen(GravityCompat.START)) {
menuItemWaiting = menuItem;
drawerLayout.closeDrawers();
return false;
};
switch(menuItem.getItemId()) {
case R.id.drawer_action:
startActivity(new Intent(this, SecondActivity.class));
/* other stuff here ... */
}
return true;
}
}
The same with ActionBarDrawerToggle:
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close){
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
if(menuItemWaiting != null) {
onNavigationItemSelected(menuItemWaiting);
}
}
};
drawerLayout.setDrawerListener(drawerToggle);
A better approach would be to use the onDrawerSlide(View, float) method and start the Activity once the slideOffset is 0. See below
public void onDrawerSlide(View drawerView, float slideOffset) {
if (slideOffset <= 0 && mPendingDrawerIntent != null) {
startActivity(mPendingDrawerIntent);
mPendingDrawerIntent = null;
}
}
Just set the mPendingDrawerIntent in the Drawer's ListView.OnItemClickListener onItemClick method.
This answer is for guys who uses RxJava and RxBinding. Idea is to prevent the activity launch until drawer closes. NavigationView is used for displaying the menu.
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
private DrawerLayout drawer;
private CompositeDisposable compositeDisposable;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setup views and listeners (NavigationView.OnNavigationItemSelectedListener)
compositeDisposable = new CompositeDisposable();
compositeDisposable.add(observeDrawerClose());
}
// uncomment if second activitiy comes back to this one again
/*
#Override
protected void onPause() {
super.onPause();
compositeDisposable.clear();
}
#Override
protected void onResume() {
super.onResume();
compositeDisposable.add(observeDrawerClose());
}*/
#Override
protected void onDestroy() {
super.onDestroy();
compositeDisposable.clear();
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
navSubject.onNext(id);
drawer.closeDrawer(GravityCompat.START);
return true;
}
private Disposable observeDrawerClose() {
return RxDrawerLayout.drawerOpen(drawer, GravityCompat.START)
.skipInitialValue() // this is important otherwise caused to zip with previous drawer event
.filter(open -> !open)
.zipWith(navSubject, new BiFunction<Boolean, Integer, Integer>() {
#Override
public Integer apply(Boolean aBoolean, Integer u) throws Exception {
return u;
}
}).subscribe(id -> {
if (id == R.id.nav_home) {
// Handle the home action
} else {
}
});
}
}
I am attempting to create an app which has a Master/Detail flow using Fragments. Selecting an item will open a detail fragment which may then which to "open" another fragment and add it to the back stack.
I have renamed classes to help illustrate what they do.
public class ListOfDetails extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}
//Callback method indicating that an item with the given ID was selected.
public void onItemSelected(String id) {
// Performing logic to determine what fragment to start omitted
if (ifTwoPanes()) {
Fragment fragment = new DetailFragmentType1();
getSupportFragmentManager().beginTransaction().replace(R.id.aContainer, fragment).commit();
} else {
Intent newIntent = new Intent(this, SinglePaneFragmentWrapper.class);
newIntent.putExtra("id", id);
startActivity(newIntent);
}
}
// My attempt at making it possible to change displayed fragment from within fragments
public void changeDetailFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(null);
transaction.replace(R.id.aContainer, fragment);
transaction.commit();
}
}
An example of one of the detail fragments. There are many different Fragments that may be created in different circumstances.
public class DetailFragmentType1 extends Fragment {
private ListOfDetails parent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Activity a = getActivity();
if (a instanceof ListOfDetails) {
parent = (ListOfDetails) a;
}
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Button aButton = (Button) getActivity().findViewById(R.id.aButton);
aButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
parent.changeDetailFragment(new SubDetailFragment());
}
});
}
}
When on phone, a wrapper activity is used to hold the fragment
public class SinglePaneFragmentWrapper extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Duplicate logic must be performed to start fragment
// Performing logic to determine what fragment to start omitted
String id = getIntent().getStringExtra("id");
if(id == "DetailFragmentType1") {
Fragment fragment = new DetailFragmentType1();
getSupportFragmentManager().beginTransaction().replace(R.id.aContainer, fragment).commit();
} else {
...
}
}
}
What is the proper way to change the fragment that is open in the detail pane in this circumstance? My method feels like a hack when using two panes and doesn't even work when using only one pane because getParent() from SinglePaneFragmentWrapper returns null, making me unable to call parent.changeDetailFragment().
This is a complicated question, hopefully I explained it well. Let me know if I missed something. Thanks
There are lots of opinions around this and lots of ways of doing it. I think in this case the problem is "who is responsible for changing the fragment?" on the surface it seems that a listener on the button is the obvious place, but then the fragment shouldn't know what it is hosted in (a symptom of that is getting an undesirable result like null from getParent()).
In your case I would suggest you implement a "listener" interface in the parent and "notify" from the fragment.. when the parent is notified, it changes the fragment. This way the fragment is not changing itself (so doesn't need to know how).. so.. for your case..
Add a new interface:
public interface FragmentChangeListener {
void onFragmentChangeRequested(Fragment newFragment);
}
Implement the interface in your ListOfDetails activity
public class ListOfDetails extends FragmentActivity implements FragmentChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}
//Callback method indicating that an item with the given ID was selected.
public void onItemSelected(String id) {
// Performing logic to determine what fragment to start omitted
if (ifTwoPanes()) {
Fragment fragment = new DetailFragmentType1();
getSupportFragmentManager().beginTransaction().replace(R.id.aContainer, fragment).commit();
} else {
Intent newIntent = new Intent(this, SinglePaneFragmentWrapper.class);
newIntent.putExtra("id", id);
startActivity(newIntent);
}
}
// My attempt at making it possible to change displayed fragment from within fragments
public void changeDetailFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(null);
transaction.replace(R.id.aContainer, fragment);
transaction.commit();
}
// This is the interface implementation that will be called by your fragments
void onFragmentChangeRequested(Fragment newFragment) {
changeDetailFragment(newFragment);
}
}
Added listener to detail fragment
public class DetailFragmentType1 extends Fragment {
private FragmentChangeListener fragmentChangeListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Actually you might not have an activity here.. you should probably be
// doing this in onAttach
//Activity a = getActivity();
//if (a instanceof ListOfDetails) {
// parent = (ListOfDetails) a;
//}
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Button aButton = (Button) getActivity().findViewById(R.id.aButton);
aButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// parent.changeDetailFragment(new SubDetailFragment());
notifyFragmentChange(new SubDetailFragment());
}
});
}
#Override
public void onAttach(Activity activity) {
// This is called when the fragment is attached to an activity..
if (activity instanceof FragmentChangeListener) {
fragmentChangeListener = (FragmentChangeListener) activity;
} else {
// Find your bugs early by making them clear when you can...
if (BuildConfig.DEBUG) {
throw new IllegalArgumentException("Fragment hosts must implement FragmentChangeListener");
}
}
}
private void notifyFragmentChange(Fragment newFragment) {
FragmentChangeListener listener = fragmentChangeListener;
if (listener != null) {
listener.onFragmentChangeRequested(newFragment);
}
}
}
And implement the same interface to your single pane activity...
public class SinglePaneFragmentWrapper extends FragmentActivity implements FragmentChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Duplicate logic must be performed to start fragment
// Performing logic to determine what fragment to start omitted
String id = getIntent().getStringExtra("id");
if(id == "DetailFragmentType1") {
Fragment fragment = new DetailFragmentType1();
getSupportFragmentManager().beginTransaction().replace(R.id.aContainer, fragment).commit();
} else {
...
}
}
// My attempt at making it possible to change displayed fragment from within fragments
public void changeDetailFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(null);
transaction.replace(R.id.aContainer, fragment);
transaction.commit();
}
// This is the interface implementation that will be called by your fragments
void onFragmentChangeRequested(Fragment newFragment) {
changeDetailFragment(newFragment);
}
}
Note the similarity between your single pane and your multi-pane activities.. this suggests that you could either put all of the duplicated code (changefragment etc) into a single activity that they both extend or that in maybe they are the same activities with different layouts...
I hope that helps, Good luck.
Regards,
CJ