How to use BaseActivity to create navigationdrawer across all activities? - android

I am creating a BaseActivity.java class to contain a navigation view and toolbar.
BaseActivity.java
public class BaseActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
private Toolbar toolbar;
private DrawerLayout drawerLayout;
private ActionBarDrawerToggle actionBarDrawerToggle;
private NavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//OTHER CODES TO SET UP NAVIGATION VIEW...
}
}
I am creating a activity_base.xml file that contains DrawerLayout
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context="com.example.sumit.movie.MovieActivity">
<android.support.design.widget.AppBarLayout
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:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_container"> ***MY PLACEHOLDER FRAGMENT***
</FrameLayout>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_movie"
app:menu="#menu/activity_movie_drawer" />
</android.support.v4.widget.DrawerLayout>
As you can see, I have a fragment_container inside this file, which I thought I would use to plug the views from another activites. For every activity, I would create a corresponding fragment and plug that fragment into this fragment_container.
But then what would I do with the xml file of the activity itself ?
I have read other answers on how to do this.
They say to create a BaseActivity.java class and extend this class to create other activities.
But do we have to create a xml file for this activity too, which would create the navigation view and the toolbar which would remain consistent across all activities ?
And if i don't create activity_base.xml, and merely create the class, Won't I have to write REDUNDENT codes for setting the navigation drawer and toolbar in every activity's xml file ?
Please help me on how this is done. I am new to android.

For this use case you might not need to have an activity xml for every page you can just have an activity class that extends BaseActivity that customises the activity / toolbar / nav draw and then you can pull common functions up to the base activity. so the BaseActivity does the setup in it on create then customisation happen per activity class.

I faced the similar problem. But, in my case there was custom NavigationDrawer and ActivityLayout used databinding. The solution is to use the same viewModel for NavigationDrawer and create layout for each Activity. Create abstract BaseDrawerActivity, which has abstract method for getting layout resource Id. Every derived Activity will specify its own resource.

Just create one activity which will going to extend NavigationDrawerActivity and setup all functionalities to that activity like onclick listener setting textviews and all.. now If you want a activity to have Navigation Drawer You just Need to extend that activity which extended The NavigationDrawerActivity and instead of using setContentView instead You have to use
addview()
with the inflated View.. Thats all..
Hope it helps!!!

Related

How to show base activity's view in another activty

I am developing an android application. What I am want to achieve in this app is, I want to make a custom progress bar which has to be available to all the activities. So I created BaseActivity and I added one custom gif in BaseActivity's layout then I created SecondActivity which extends BaseActivity.
BaseActivity(By default gif is invisible) has two methods called showProgressBar and hideProgressBar I am calling this method from SecondActivity but it is not showing a progress bar. Then I make a BaseActivity launcher activity and to check the gif it is showing.
How should I achieve this?
You can override the setContentView in your BaseActivity and add your base layout there, that way when the child activities call the setContentView, the base layout is also set. You'll need to set a FrameLayout that will 'hold' the child activity's layout. Something along the following lines should work.
//In BaseActivity
#Override
public void setContentView(int layoutResID)
{
DrawerLayout fullView = (DrawerLayout) getLayoutInflater().inflate(R.layout.activity_base, null);
FrameLayout activityContainer = (FrameLayout) fullView.findViewById(R.id.activity_content);
getLayoutInflater().inflate(layoutResID, activityContainer, true);
super.setContentView(fullView);
}
P.S - In my above example, I used a DrawerLayout, you should be able to use it with any ViewGroup. Just replace that line with the base ViewGroup in your base activity layout.
Edit - Added xml for clarity
//activity_base.xml
<android.support.v4.widget.DrawerLayout
android:id="#+id/activity_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="#color/background_material_dark"
/>
<FrameLayout
android:id="#+id/activity_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/menu_base"/>
</android.support.v4.widget.DrawerLayout>
You can create a custom dialog class so it will be available for every Activity in your project
Create dialogClass:
public class ProgressDialog extends Dialog {
public ProgressDialog(#NonNull Context context) {
super(context);
setContentView(R.layout.progress_dialog); //this is your layout for the dialog
}
}
And all you need to do is to create dialog instant and call it like this:
ProgressDialog progressDialog = new ProgressDialog(getContext());
progressDialog.show(); // this line shows your dialog
And in your dialog class, you can put your logic, change the way your layout will look and do anything that you need to.

Using a DrawerLayout without navigation functionality

I have been looking into DrawerLayout for my project's slideout menu. It seems to behave the way I want, except for one thing.
I've run a few sample projects and they all seem to have one thing in common: the DrawerLayout is always the main part of the application, as in:
setContentView(R.layout.activity_main);
Where activity_main is:
<android.support.v4.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
Also, DrawerLayout seems to have strong ties to navigation, where it's used to jump between fragments.
My problem is, I do not wish to use this slideout menu for navigation, nor do I have any desire to make my app's current main page a Fragment. I want a slideout menu, but I will be using it for settings mostly, not to move around the app.
Is there any way to have a simple slideout menu, which behaves visually and tactically like DrawerLayout, but without the need to have all my views set as fragments of it?
I have recently done this using 1. a custom RelativeLayout class with a ViewTreeObserver referencing a custom X or Y property (for drawer you would use X) 2. objectAnimator XML referencing same custom property 3. Fragment class for the UI itself, using the custom Layout class 4. use setCustomAnimations method of getFragmentManager to show / hide the menu.
Here's an example, just change it to horizontal
Fragment Translation Animation for a Menu

How to make hide/show toolbar when our list scrolling to the top

How to make hide/show toolbar when our list scrolling to the top, knowing that the toolbar view is described inside activity_main.xml but recyclerView is described in another fragmet nomed Fragment_main.xml
sorry for my english :)
Since your activity which has the toolbar within its content view is starting the fragment, you can always get a hold of it from your fragment.
MainActivity mainActivity = (MainActivity)getActivity();
I would recommend doing a method for it in your MainActivity:
public void showToolbar(boolean show) {
// If you have your toolbar as a private member of MainActivity
toolbar.setVisiblity(show ? View.VISIBLE : View.GONE);
// But you can also do this
if (show) {
getSupportActionBar().show();
}
else {
getSupportActionBar().hide();
}
}
And then when you actually want to hide it from your fragment, call it:
((MainActivity)getActivity()).showToolbar(false);
To make the UI change more smooth, I recommend translating it instead of just instantly hiding it. Take a look at the top answer here for inspiration:
android lollipop toolbar: how to hide/show the toolbar while scrolling?
If you don't know how to take care of when to actually show or hide it via scroll logic, take a look at this library which handles a lot for you and also gives examples:
https://github.com/ksoichiro/Android-ObservableScrollView
This is kind of simple.
Just put this code in your toolbar
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"/>
This will do the magic : app:layout_scrollFlags="scroll|enterAlways"
remember to add in your xml the app call xmlns:app="http://schemas.android.com/apk/res-auto"
Check this tutorial: https://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout
Use below code:
<android.support.design.widget.CoordinatorLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
...>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"/>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/rvToDoList"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</android.support.design.widget.CoordinatorLayout>
If RecyclerView is in another fragment, then add below line to the View which contain RecyclerView in this CoordinatorLayout.
app:layout_behavior="#string/appbar_scrolling_view_behavior"
Must Use CoordinatorLayout.

dynamically change the drawer layout

I have this situation: when launching the app, the first fragment (A) displayed has a list of some users. When clicking a user, another fragment (B)is displayed and, together, the drawer menu will be different for each user.
As you can see, I can NOT set up the DrawerLayout when launching the app (the main activity or Launcher) since I don't have the data for the listView yet, but have to set it up when clicking a user in the list in fragment A after the app finishes launching (That's when I can retrieve the data for the listView of the drawer menu, which is indicated by the id: fragment_drawer in below xml file).
Here's the xml file for "MainActivity":
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- The main content view -->
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer, listView is inside MyDrawerFragment's layout-->
<fragment android:id="#+id/fragment_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:name="mypackage.com.MyDrawerFragment"
tools:layout="#layout/drawer_layout" />
</android.support.v4.widget.DrawerLayout>
How can I achieve the goal in fragment B? Is this achievable at all in fragment B?
If not possible doing this in fragment B, I am thinking to launch a second activity, say Activity2, and the above xml layout file will be applied to this new activity, when clicking the user in fragment A, I just keeps doing this: closing the existing Acitvity2 by calling finish() and create a new Activity2 instance with new data for drawer menu? Is this approach feasible at all?
Any hints are highly appreciated!
Thanks,
Shawn
I had to do an app where I had to make an Activity with 4 fragments and a ViewPager, where only in 2 I would open a different Drawer.
The Activity's layout must contain the DrawerLayout*, but since the Drawer itself depends on which Fragment I'm on, I figured that it should be the Fragment the one in charge of rendering (or not) the Drawer.
*If the Activity doesn't contain the DrawerLayout, it wouldn't be displayed filling the whole screen!
I did something like this, though it does need some refactoring and clean up :)
Working on the idea that the Fragment is in charge of rendering the Drawer, but it is the Activity the one that has access to it, I made two interfaces to communicate Fragment and Activity:
/**
* should be implemented by any fragment interested in communicating
* with a {#link FragmentListener} Activity
*/
public interface ActivityListener {
/**
* called from {#link FragmentListener} requestOpenDrawer
* the fragment is in charge of rendering its drawer's layout
*/
public void renderDrawer(DrawerLayout mDrawerLayout,
NavigationView viewById, Activity activity);
}
-
/**
* used to communicate FROM fragments, to its parent Activity
* implemented by {#link MainTabbedActivity}
*/
public interface FragmentListener {
/**
* call from a fragment to request opening the drawer
* note that if the drawer isn't opened by the activity,
* it wouldn't cover the whole screen
*/
void requestOpenDrawer(Fragment requester);
void requestCloseDrawer();
DrawerLayout getDrawerLayout();
}
Implementation
#Override
public void requestOpenDrawer(Fragment requester) {
mDrawerLayout.openDrawer(Gravity.RIGHT); //Edit Gravity.End need API 14
if (requester instanceof ActivityListener) {
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
//let fragment render the drawer
((ActivityListener) requester).renderDrawer(mDrawerLayout, navigationView, this);
}
}
-
#Override
public void renderDrawer(DrawerLayout mDrawerLayout, NavigationView viewById, Activity activity) {
View child = activity.getLayoutInflater().inflate(R.layout.credit_fragment_drawer, null);
navigationView.addView(child);
}
Layouts
Both the Activity layout and the Fragments layout don't have anything more than the standard Drawer implementation:
Activity layout with Drawer:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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_tabbed_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="right">
<include
layout="#layout/activity_main_tabbed_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:fitsSystemWindows="true" />
</android.support.v4.widget.DrawerLayout>
Where activity_main_tabbed_content is whatever the content you want to put in the Activity.
The fragments really don't have anything more than a common Fragment.
Example:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- whatever views you want -->
</RelativeLayout>

How to implement in an android application Navigation Drawer + the brand-new Toolbar?

I've started to develop an android application, which consist of the following:
MainActivity: extends FragmentActivity.
Several fragments: extending android.support.v4.app.Fragment each one.
MainActivity starts with the application and it has an ActionBarDrawer (it was a requirement of the client to implement a drawer-like menu). Besides, MainActivity makes fragment transaction: when X option within the drawer is clicked, MainActivity replaces and sets the desired Fragment (a default fragment is set when the application starts).
This picture ilustrates it:
My classes:
public class MainActivity extends FragmentActivity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
// that is the one which is deprecated: ActionBarDrawerToggle mDrawerToggle:
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence mDrawerTitle;
private CharSequence mTitle;
private String[] mDrawerMenuTitles;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
public class FragmentEuskalmet extends Fragment implements android.widget.AdapterView.OnItemSelectedListener {
activity_main.xml layout:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
drawer_list_item.xml layout:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="#fff"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeightSmall"/>
I've realised that with the release of Android 5.0, ActionBar has been deprecated. So my question is the following: how to change my application to support the new Toolbar, using its new navigation drawer (replacing the deprecated one) and maintaining my Fragment usage within the MainActivity (using FragmentActivity)?
Thanks in advance for your appreciated help!
The ActionBar is not deprecated in Android 5.0.
Beginning with Android 5.0 (API level 21), the action bar may be represented by any Toolbar widget within the application layout.
Said that, to replace the ActionBar with the new Toolbar and the new appcompat v21 you have to:
extend the AppCompatActivity instead of FragmentActivity
use getSupportActionBar() instead of getActionBar() when you need
use a theme which inherits from Theme.AppCompat.(for example Light or NoActionBar)
put the Toolbar view inside your layout
More info here:
Then to integrate the navDrawer you can do:
Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(toolbar);
mDrawerToggle= new ActionBarDrawerToggle(this, mDrawerLayout,mToolbar, R.string.app_name,
R.string.app_name);
mDrawerLayout.setDrawerListener(mDrawerToggle);

Categories

Resources