I have a navigation bar in my app, the thing is that I want the navbar to be available in all activities. I suppose that I have to set contentView two times, but that doesn't work, of course.
I've been looking at and but I dont get it to work. I have a super class, can I set this second layout from my super class?
You should include the nav bar via <include> tag from the other layouts. Setting the content layout twice will not work, as Android is in the callbacks basically always using what the user has told last. So
setContentLayout(R.layout.nav);
setContentLayout(R.layout.main);
will result in only the main layout being used.
Have a look at this article which gives an example of using the include tag.
You can extend standard activities (Activity, ListActivity, etc.. if you use any others) and use them as a base for including a nav_bar.
For example:
Define a layout with nabar like this
<LinearLayout
...
android:orientation="vertical"
>
<YourNavBarComponent
...
/>
<FrameLayout
android:id="#+id/nav_content"
...
>
// Leave this empty for activity content
</FrameLayout>
</LinearLayout>
This will be your base layout to contain all other layouts in the nav_content frame.
Next, in create a base activity class, and do the following:
public abstract class NavActivity extends Activity {
protected LinearLayout fullLayout;
protected FrameLayout navContent;
#Override
public void setContentView(final int layoutResID) {
fullLayout= (LinearLayout) getLayoutInflater().inflate(R.layout.nav_layout, null); // Your base layout here
navContent= (FrameLayout) fullLayout.findViewById(R.id.nav_content);
getLayoutInflater().inflate(layoutResID, navContent, true); // Setting the content of layout your provided in the nav_content frame
setContentView(fullLayout);
// here you can get your navigation buttons and define how they should behave and what must they do, so you won't be needing to repeat it in every activity class
}
}
And now, when you create a new activity, where you need a nav bar, just extend NavActivity instead. And your nav bar will be placed where you need it, without repeating it in every layout over and over again, and polluting the layouts (not to mention repeating a code to control navigation in every activity class).
Try merging layouts, as described on Android Developers Blog.
Related
I have activity_main which is default layout in my activity, there i have framelayout which display fragment whit different layout, is it possible to connect the different layout textview to setText() from my activity? How to connect from activity to this fragment xml layout?
activity_main
frameLayout
fragment 1 xml
fragment 2 xml
/frameLayout
Activit.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dirShow("a");
}
void dirShow(String s) {
setContentView(R.layout.fragment1);
textPath = (TextView) findViewById(R.id.path_text);
textPath.setText(s);
}
You shouldn't be calling setContentView more than once in an activity. The content view is the entire activity layout. If you want to change the layout the proper way to do it is to change the fragment or activity, and have the new activity or fragment show the new layout.
If you're not trying to change layouts, then just put the TextView you need in the first layout that you set. Posting your layout files and telling us what you're trying to do may allow us to help you achieve what you want.
EDIT:
If I understand your updated question correctly, you're using Fragments. If that's the case, call the dirShow() function in the Fragments onCreateView() function instead of the activity's onCreate() function.
If you're just incorrectly using the term fragment in your question, I suggest you switch to using them.
You want to include another xml into your main xml usin include tag, and set text on textview as you want.
I had written a simple Hello World application with a single Activity.
Class:
public class HelloWorld extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.helloworld);
}
}
helloworld.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/textview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="#string/hello"/>
I have required resources and 'AndroidManifest.xml' in place, the application is running fine.
In 'View Hierarchy window' of 'hierarchyviewer' tool, I notice that TextView widget's parent is FrameLayout whose parent is LinearLayout (for brevity, I had cut only required screen shot). Screen shot:
In my 'helloworld.xml', I had not declared FrameLayout as parent for TextView widget. Please help me understand:
1. In general, how runtime decides on a layout if it is not explicitly declared in layout resource (xml file)?
2. In the diagram, why LinearLayout is parent of FrameLayout?
Thanks much in advance.
With the help of a hint from link posted by Vikram Bodicherla and some effort, I found answers to my questions.
The answers to my questions lie in Android 3.0 release - "when the application is installed on a device running Android 3.0 or greater,
the system applies the holographic theme to each activity, and thus, each activity includes the Action Bar.", from documentation.
1 In general, how runtime decides on a layout if it is not explicitly declared in layout resource (xml file)?
- See below answer.
2 In the diagram, why LinearLayout is parent of FrameLayout?
- LineraLayout divides UI into two sections - top and bottom which represent ActionBar and activity's UI (components, other than
ActionBar components) respectively. Bottom section has FrameLayout which is an apt layout to contain any layout. So, if you do
not explicitly specify any layout in your layout resource, such as mine (see above - helloworld.xml), components will always be placed
in FrameLayout. If you declare ANY layout, say GridLayout or even LinearLayout or FrameLayout, it will still be included in FrameLayout which will be included in LinearLayout. This also explains why "...the parent of an activity's content view is always a FrameLayout." from link posted by Vikram Bodicherla.
#Vikram Bodicherla - I had given a point for your link post, thanks again.
If a set contentview is not called than ALL views that are found in the R.java will be null. Specifically this is because views don't get created until setContentView(xx) is called. There is no "default layout."
These are the options available to configuring a layout in an Activity:
void setContentView(int layoutResID)
Set the activity content from a layout resource.
void setContentView(View view)
Set the activity content to an explicit view.
void setContentView(View view, ViewGroup.LayoutParams params)
Set the activity content to an explicit view.
Upon the calling of these one of these methods, you will instantiate your views onto your activity, so when retrieving them from the R.java they will be non-null.
want to make an Android app that starts with a main layout and when you push a button (called stateButton) that is in this layout the layout changes to a main2 layout containing another button (called boton2), and when you push this one you get back to the first main.
I want to do this in the same activity without creating or starting another one.
Here I show you part of the code:
public class NuevoshActivity extends Activity
implements SensorEventListener, OnClickListener {
private Button stateButton;
private Button boton2;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.stateButton = (Button) this.findViewById(R.id.boton);
this.boton2 = (Button) this.findViewById(R.id.boton2);
stateButton.setOnClickListener(this);
boton2.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v==stateButton) {
setContentView(R.layout.main2);
}
else if(v==boton2) {
setContentView(R.layout.main);
}
}
}
The mains only have some images, text views and the buttons.
But I've some troubles. Can't it just be as simple as that or what am I missing or what is wrong?
When you use findViewById, you are actually trying to find a view inside the layout you specified by the setContentView. So using setContentView again and again might bring problems when you are trying to check for buttons.
Instead of using a setContentView, I would add the 2 layouts for the screen as child's for a view-flipper which only shows one child at a time. And you can specify the index of which child to show. The benefit of using a view flipper is that you can easily specify a 'in' and 'out' animation for the view if you need an animation when you switch between views. This is a lot cleaner method then recalling setContentView again and again.
The FrameLayout handles this wonderfully... Use this with the <include... contstruct to load multiple other layouts, then you can switch back and forth between them by using setvisibility(View.VISIBLE); and setVisibility(View.INVISIBLE); on the individual layouts.
For example:
Main XML including two other layouts:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="#+id/frameLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
<include android:id="#+id/buildinvoice_step1_layout" layout="#layout/buildinvoice_step1" android:layout_width="fill_parent" android:layout_height="fill_parent"></include>
<include android:id="#+id/buildinvoice_step2_layout" android:layout_width="fill_parent" layout="#layout/buildinvoice_step2" android:layout_height="fill_parent"></include>
</FrameLayout>
Code to switch between layouts:
findViewById(R.id.buildinvoice_step1_layout).setVisibility(View.VISIBLE);
findViewById(R.id.buildinvoice_step2_layout).setVisibility(View.INVISIBLE);
You will also need to set the visibility of the individual layouts when the activity starts (or in XML) otherwise you will see them both - one on top of the other.
Your boton2 button will be NULL because the definition of the button is in main2.xml.
The only views you will be able to find are the views which are defined in main.xml.
Thanks!!! All the info was usefull to understand a lot of things and as C0deAttack commented I've got troubles with the button on the main2. What I've done is to set View.VISIBLE and View.GONE to the TextViews and Buttons that I wanted in each layout. Thank you very much.
I am developing an application that contains many activities
and i created my own menu (i don't want to use the built in menu button) with the Sliding Drawer
as the sliding drawer is at the bottom of the screen and contains my menu buttons
what i need is to make that sliding drawer to appear in all my activities
i tried to create an activity and set it's content view to the xml file that includes the drawer and then extends that activity in all other activities but this solution doesn't work
so any suggestions ?
Extending is the right way. Just override setContentView in the right way.
Here's the working example, but instead of drawer, I use a created a custom tabbar:
Define a layout with your drawer like this:
this is act_layout.xml
<LinearLayout
...
android:orientation="vertical"
>
<YourDrawer
...
/>
<FrameLayout
android:id="#+id/act_content"
...
>
// Here will be all activity content placed
</FrameLayout>
</LinearLayout>
This will be your base layout to contain all other layouts in the act_content frame.
Next, create a base activity class, and do the following:
public abstract class DrawerActivity extends Activity {
protected LinearLayout fullLayout;
protected FrameLayout actContent;
#Override
public void setContentView(final int layoutResID) {
// Your base layout here
fullLayout= (LinearLayout) getLayoutInflater().inflate(R.layout.act_layout, null);
actContent= (FrameLayout) fullLayout.findViewById(R.id.act_content);
// Setting the content of layout your provided to the act_content frame
getLayoutInflater().inflate(layoutResID, actContent, true);
super.setContentView(fullLayout);
// here you can get your drawer buttons and define how they
// should behave and what must they do, so you won't be
// needing to repeat it in every activity class
}
}
What we do, is basically intercept all calls to setContentView(int resId), inflate our layout for drawer from xml, inflate our layout for activity (by reId provided in method call), combine them as we need, and set as the contentView of the activity.
EDIT:
After you've created the stuff above, just proceed to write an app as usual, create layouts (without any mention of a drawer) create activities, but instead of extending simple activity, extend DrawerActivity, like so:
public abstract class SomeActivity extends DrawerActivity {
protected void onCreate(Bundle bundle) {
setContentView(R.layout.some_layout);
}
}
What happens, is that setContentView(R.layout.some_layout) is intercepted. Your DrawerActivity loads the layout you provided from xml, loads a standart layout for your drawer, combines them and then sets it as contentView for the activity.
Finally after 3 years, here's the complete solution to this important question for whom may have not been completely guided by Mr. Orlov's answer.
His method for making a hierarchy view was completely OK but there was some small mistakes that may mislead beginner developers.
As Gabe also mentioned, you can get rid of abstract in declaration.
There's no need to wrap both child with a FrameLayout. The parent could be anything RelativeLayout, LinearLayout, etc. But the most important part is that you must declare the FrameLayout before the Slider.
So the 100% working soloution would be like this :
activity_drawer.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/drawer_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<YourDrawer
android:id="#+id/drawer_drawer"
android:layout_width="match_parent"
android:layout_height="fill_parent" >
</YourDrawer>
</RelativeLayout>
DrawerActivity.java
public class DrawerActivity extends Activity {
protected RelativeLayout fullLayout;
protected FrameLayout frameLayout;
#Override
public void setContentView(int layoutResID) {
fullLayout = (RelativeLayout) getLayoutInflater().inflate(R.layout.activity_drawer, null);
frameLayout = (FrameLayout) fullLayout.findViewById(R.id.drawer_frame);
getLayoutInflater().inflate(layoutResID, frameLayout, true);
super.setContentView(fullLayout);
//Your drawer content...
}
}
MainActivity.java
public class MainActivity extends DrawerActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Don't forget to declare DrawerActivity in manifest.
Hope it helped.
I know this is two years late but for those who would like an answer here it is. Mr Orlov had an appropriate response, just a few adjustments needed.
delete the abstract after public. (this is what causes an error)
wrap BOTH your sliding drawer and FrameLayout with another FrameLayout and set the width and height to match_parent. (This allows BOTH layouts to appear).
ALSO: If you want your sliding drawer to appear on top of your layout (duh!) then place the frameLayout that is after the slidingDrawer before the slidingDrawer.
I'm new to android,I'm using tabHost adding some tabs to it,its working quite fine but when i rotate my device in landscape mode it also work there fine but i don't need tab bar there because it covers much space and i also have google ads so both of them cover half of the screen and leave a little space for user to interact.All i need is a solution to somehow hide tab bar just like we can do it in iphone to make a bit room for user to interact.I need some solution urgent.Thanks
I think you should wrap your tab widget in any ViewGroup such as LinearLayout or RelativeLayout, and create a static function in your tabActivity to show/hide this wrapper, Here's a little code might be helpful for you.
<LinearLayout
android:id="#+id/popupTabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<TabWidget android:id="#android:id/tabs"
android:layout_height="wrap_content"
android:layout_width="fill_parent"></TabWidget>
</LinearLayout>
Now your tab activity should do something like this.
public class TabsView extends TabActivity {
public static LinearLayout popupTabs ;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
popupTabs = (LinearLayout) findViewById(R.id.popupTabs);
// Your other code
//............
//............
}
// Show Tabs method
public static void showTabs(){
popupTabs.setVisibility(ViewGroup.VISIBLE);
}
// Hide Tabs method
public static void hideTabs(){
popupTabs.setVisibility(ViewGroup.GONE);
}
}
Now you can call this method statically from any location in your code like this
// hide tab from any activity
TabsView.showTabs();
// hide tab from any activity
TabsView.hideTabs()
For Hide
mTabHost.getTabWidget().setVisibility(View.GONE);
For Visible
mTabHost.getTabWidget().setVisibility(View.VISIBLE);
The simplest way would be to create a second version of your layout.xml file which doesn't include the TabHost and put it in a resource folder named 'layout-land' (the 'land' suffix is short for 'landscape'). Please see this SDK article for more information.
Apart from doing what Reuben is telling you would be to animate the transition between both so that the change would be a bit smoother.