Android - Add navigation drawer to multiple activities - java

I'm new to Android / Kotlin and I have an application with multiple activities.
So far I have created all the activities needed and the app works fine except for the fact now I need to add a Navigation Drawer.
Coming from iOS, I designed all my layouts thinking I can add the Navigation Drawer after:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/backgroundColor"
android:backgroundTint="#color/backgroundColor">
<RelativeLayout
android:id="#+id/mainRelativeLayout"
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#drawable/navbar_border"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/ivNavBarLogo"
android:layout_width="102dp"
android:layout_height="24dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:contentDescription="#string/empty_description"
app:srcCompat="#mipmap/navbar_logo"/>
<ImageButton
android:id="#+id/btnSideMenu"
android:layout_width="25dp"
android:layout_height="15dp"
android:layout_centerVertical="true"
android:layout_marginStart="15dp"
android:background="#mipmap/sidemenu_button"
android:contentDescription="#string/empty_description"
app:srcCompat="#mipmap/sidemenu_button"/>
</RelativeLayout>
<!-- STUFF TO BE ADDED THERE -->
</android.support.constraint.ConstraintLayout>
My intention was to create a NavigationDrawer activity and call it when tapping the btnSideMenu on each activity.
However, I've been trying to get around this for a few days now without any luck. I never thought such a basic feature could be so hard to implement. I tried almost every suggestion and example found here, and also this: https://developer.android.com/training/implementing-navigation/nav-drawer.html
Am I thinking this issue the wrong way? Is there any way of doing this without having to recreate all my activities based on the template provided by Android Studio or using fragments?
LE: Forgot to mention that I removed the ActionBar from all activities.

To add a navigation drawer to multiple activities without going through and re-writing every activity's layout, you can leverage a base activity class and a ViewStub tag.
Create a layout like this (I'll refer to it as navdrawer_activity.xml later):
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start">
<ViewStub
android:id="#+id/navdrawer_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<!--
your drawer here
you can use android.support.design.widget.NavigationView
or some other view if you want
-->
</android.support.v4.widget.DrawerLayout>
Then create a class for all of your activities to extend:
public class NavDrawerActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.navdrawer_activity);
}
#Override
public final void setContentView(#LayoutRes int layoutResID) {
ViewStub stub = findViewById(R.id.navdrawer_stub);
stub.setLayoutResource(layoutResID);
stub.inflate();
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// set up nav drawer as normal, using whatever
// callback methods or helper methods you want
}
}
With these in place, the only thing you have to do is change any activity where you want the nav drawer to extend NavDrawerActivity instead of AppCompatActivity.

Well as the guide you included says:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout ...>
<!-- Layout to contain contents of main body of screen (drawer will slide over this) -->
<content goes here
... />
<!-- Container for contents of drawer -->
<left pane of drawer goes here
...
android:layout_gravity="start" />
</android.support.v4.widget.DrawerLayout>
You could define the left pane of the drawer as a compound view, and the content as a compound view. Kinda like this:
your_view.xml
<YourView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button android:id="#+id/..."
android:layout_width="..."
android:layout_height="..."
android:layout_centerInParent="true"/>
</YourView>
And
public class YourView extends RelativeLayout {
public YourView(Context context) {
super(context);
}
public YourView(Context context, AttributeSet attrs) {
super(context, attrs);
}
// ... two more constructors are possible here
private Button button;
#Override
public void onFinishInflate() {
super.onFinishInflate();
button = findViewById(R.id.button);
button.setOnClickListener((view) -> {
...
}
}
}
And you can do the same thing for the view of the left pane. Make sure you include the android:layout_gravity="start" as an attribute of <YourLeftPane in its xml.
And now you can do in your activity_whatever.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout ...>
<include layout="#layout/your_view"/>
<include layout="#layout/your_left_pane" />
</android.support.v4.widget.DrawerLayout>

Related

Change TextView on content_main.xml in MainActivity.java

I'm using the Android Studio standard template "Navigation Drawer Activity" which contains the content_main.xml layout.
On this layout is my textView which I want to change the text from my MainActivity.java.
I tried following but nothing changes:
LayoutInflater inflater = (LayoutInflater)this.getSystemService (Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.content_main, null);
TextView txt = (TextView)view.findViewById(R.id.txt_head);
txt.setText("sdfsdf");
content_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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/relativelayout_for_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.example.w4ter.ledcontroldesign.MainActivity"
tools:showIn="#layout/app_bar_main"
android:orientation="vertical"
android:paddingTop="10dp">
<TextView
android:text="Presets"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#style/TextAppearance.AppCompat.Headline"
android:id="#+id/txt_head" />
<View
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#61000000" />
</LinearLayout>
there is no need of LayoutInflater. Simply use:
TextView textView = (TextView) findViewById(R.id.txt_head);
texView.setText("Hello");
Hope this helps.
You just need to access the TextView component the normal way. With that template the content_main.xml is included inside the main layout, so you sould do as follows in your main activity (maybe inside the onCreate method or wherever you need):
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
//...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView txt = (TextView)view.findViewById(R.id.txt_head);
txt.setText("sdfsdf");
}
//...
}
Assuming that you have a app_bar_main.xml inside the main layout wich contains the content_main.xml. In the end everything is accessible from the main activity directly since the layouts are included in the main layout.
Hope it helps!

Code referencing internal library not working

I am trying to make my first library to learn and see how things work. What is supposed to happen is that my main activity (in the sample or whatever app uses the local library) will show a loading animation from the library. But when I add in the code, it does not show in the sample. I'm not getting any errors or anything. What could be going on?
Sample Main Activity:
public class MainActivity extends AppCompatActivity {
private ProgressBar spinner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//This is what isnt working. The spinner
spinner = (ProgressBar)findViewById(com.marlonjones.ezloadanimlibrary.R.id.main_progress);
library XML:
<RelativeLayout
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:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="#+id/main_progress"
android:layout_height="50dp"
android:layout_width="60dp"
android:layout_centerInParent="true"
android:indeterminate="true"
android:indeterminateDrawable="#drawable/main_ind_progress"/>
</RelativeLayout>
main_ind_progress:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#drawable/loader_main"
android:pivotX="50%"
android:pivotY="50%"/>
The drawable main_ind_progress, and the drawable loader_main are both inside of the library.
All code: https://github.com/MJonesDev/EZLoadAnimLibrary
The ProgressBar view isn't added to your current Activity i.e. you have no view of the type ProgressBar that is why it isn't showing anything
You can assign an id to the root RelativeLayout in the content_main layout file of your current Activity then in the OnCreate() method
RelativeLayout rL = (RelativeLayout) findViewById(R.id.your_id);
// and then add your spinner to the relative layout
rL.addView(snipper);
or what you can do is make a ProgressBar in your current app's content_main.xml file
<ProgressBar
android:id="#+id/my_progress_bar"
android:layout_height="50dp"
android:layout_width="60dp"
android:layout_centerInParent="true"
android:indeterminate="true"
/>
and assign it the main_ind_progress to it from your library
ProgressBar spinner=(ProgressBar) findViewById(R.id.your_progress_bar_id);
spinner.setIntermediateDrawable(com.marlonjones.ezloadanimlibrary.R.drawable.main_ind_progress);

Navigation Drawer below Status Bar

I'm tring to make a Navigation Drawer using Design Support Library. In my activity_main i wrote this code.
<?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">
<LinearLayout
android:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar"/>
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/header_layout"
app:menu="#menu/menu_drawer"/>
</android.support.v4.widget.DrawerLayout>
When i run my application it works and show the Navigation Drawer but it's below the Status Bar and not above. How can i move it to stay above the StatusBar?
Simply adding android:fitsSystemWindows="false" to DrawerLayout will solve the problem.
Make your activity as full screen to overcome status bar as below or any other method as available on WWW: but it's not good to have drawer over status bar.
public class ActivityName extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// remove title
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
}
}
use this on navigation view xml :
app:insetForeground="#ffffff"

How can i access fragment layout in parent activity?

I have got a tabpager and fragments. And a frament has got a "GridView". I am using a basedapter innerclass in the fragment parent activity.
But when i want to set adapter to my gridview i m getting nullpointerexception. Because GridView variable is always null.how can solve this issue?
Fragment Parent MainActivity OnCreate Method;
GridView gv = (GridView)findViewById(R.id.gridview); // debugging and always null
gv.setAdapter(new AdapterB(this,WallPaperList));
Fragment xml
<!-- TODO: Update blank fragment layout -->
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:columnWidth="90dp"
android:stretchMode="columnWidth"
android:gravity="center"
/>
MyGrid.xml (For populate with adapter)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="#+id/imagepart"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SeƧ"
android:id="#+id/checkBox" />
</LinearLayout>
You cant acces fragment views like that, becouse they could be not yet in the activity view hierarchy.
You have to add some method to your fragment, like
myCustomFragment.setGridAdapter(MyCustomGridViewAdapter adapter)
and in this method in your custom fragment:
public void setGridAdapter(){
this.myCustomGridAdapter = adapter;
GridView gv = (GridView)findViewById(R.id.gridview);
if(gv != null)
gv.setAdapter(this.myCustomGridAdapter);
}
This code:
GridView gv = (GridView)findViewById(R.id.gridview); // debugging and always null
gv.setAdapter(new AdapterB(this,WallPaperList));
should be inside of your fragment's onCreateView. You should create fragments that are independent from the activity they're attached to.
If you absolutely need to access the fragment's layout from your activity you need to delay the findViewById because the fragment's layout is not yet inflated when you call it:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
GridView gv = (GridView)findViewById(R.id.gridview);
gv.setAdapter(new AdapterB(this, WallPaperList));
}
}, 1000);
Although this code would work, I highly discourage you from using it!

How do I hide or show layout elements when an Android Activity goes out of focus?

I am trying to hide certain elements in a layout when Android goes out of focus, such that when viewed in the "View recent applications" display, the layout elements will not be visible. Upon selecting the application and going into focus, these elements will be visible again.
My implementation below attempts to show the "content" layout when the application is in focus, and show the "overlay" layout when out of focus, via onWindowFocusChanged().
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is the content page"/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is the overlay"/>
</RelativeLayout>
</FrameLayout>
MainActivity.java
public class MainActivity extends ActionBarActivity {
FrameLayout layoutContainer;
RelativeLayout layoutContent;
RelativeLayout layoutOverlay;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layoutContainer = (FrameLayout) findViewById(R.id.container);
layoutContent = (RelativeLayout) findViewById(R.id.content);
layoutOverlay = (RelativeLayout) findViewById(R.id.overlay);
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
if (hasFocus) {
layoutContent.setVisibility(View.VISIBLE);
layoutOverlay.setVisibility(View.GONE);
} else {
layoutOverlay.setVisibility(View.VISIBLE);
layoutContent.setVisibility(View.GONE);
}
}
}
enter code here
However, my implementation does not work. Anyone with any suggestion as to solve this? Thanks!
If you want to hide views in your layout in recent apps try like this
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,WindowManager.LayoutParams.FLAG_SECURE);

Categories

Resources