How to create reusable xml wrappers for Android Layout files - android

I have several layout files that are mostly the same, except for one section. Is there a way that I can have the common XML all in one place; instead of copy/pasting, and having to update a bunch of files when I want to make 1 change?
I know that I can include XML from other XML files, but the common code isn't an internal control; it is the outer wrapper; so include doesn't work. Basically, I have a bunch of files that all look like this:
<LinearLayout
android:id="#+id/row"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<ImageView android:layout_height="26dp"
android:id="#+id/checkImage"
android:layout_width="26dp"
android:layout_alignParentTop="true"
android:scaleType="fitCenter"/>
<!-- Different types of views go here depending on which layout file it is -->
<ImageButton android:layout_height="fill_parent"
android:id="#+id/playButton"
android:layout_width="42dp"
android:src="#drawable/play_button"
android:scaleType="center"
android:background="#00000000"/>
</LinearLayout>
Basically, I want to do what ASP.Net does with Master Pages. Is there any option for this?

The solution was pretty easy.
You need to extend "Activity" Class, in onCreate() function SetContentView to your base xml layout and also need to override setContentView in base Activity Class
For Example:
1.Create base_layout.xml with the below code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/image_view_01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="50dp" />
</LinearLayout>
<LinearLayout
android:id="#+id/base_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</LinearLayout>
</LinearLayout>
Create BaseActivity.java
public class BaseActivity extends Activity {
ImageView image;
LinearLayout baseLayout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.base_layout);
this.image = (ImageView) this.findViewById(R.id.image_view_01);
this.baseLayout = (LinearLayout) this.findViewById(R.id.base_layout);
this.image.setImageResource(R.drawable.header);
}
#Override
public void setContentView(int id) {
LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(id, this.baseLayout);
}
}
and SomeActivity.java
public class SomeActivity extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.some_layout);
//rest of code
}
}
The only thing I noticed so far was that when requesting a progress bar (requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) this needs to be done before calling super.onCreate. I think this is because nothing can be drawn yet before calling this function.
This worked great for me and hopefully you will find this useful in your own coding.

Maybe you could use one main layout XML file and then add/remove other widgets dynamically through code as needed.

I was trying to do exactly this - I wanted a view that had a button on the left and a button on the right, but could have arbitrary content in the middle (depending on who was including it). Basically a custom view group that could have child view in the XML layout, and would wrap those child views with another XML layout. Here is how I did it:
top_bar.xml: This represents the common layout to wrap things with. Note the LinearLayout (could be any layout) with an ID "addChildrenHere" - it is referenced later.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/topBarLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="left" />
<LinearLayout
android:id="#+id/addChildrenHere"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="#+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="right" />
</LinearLayout>
main.xml: The main layout. This includes a custom viewgroup (WrappedLayout) with a few children. Note how it declares a custom XML namespace, and sets two custom attributes on the WrappedLayout tag (these say which layout to wrap the children with, and where within that layout the children of this node should be placed).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:karl="http://schemas.android.com/apk/res/karl.test"
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<karl.test.WrappedLayout
android:id="#+id/topBarLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
karl:layoutToInflate="#layout/top_bar"
karl:childContainerID="#+id/addChildrenHere">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is a child of the special wrapper."
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is another child; you can put anything here."
android:textAppearance="?android:attr/textAppearanceMedium" />
</karl.test.WrappedLayout>
</LinearLayout>
attrs.xml: This goes in res/values. This defines the custom XML attributes used in the XML above.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="WrappedLayout">
<attr name="layoutToInflate" format="integer"/>
<attr name="childContainerID" format="integer"/>
</declare-styleable>
</resources>
Finally, WrappedLayout.java: This handles reading the custom attributes, and doing a bit of hackery to make addView() actually add the views in a different place.
package karl.test;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
public class WrappedLayout extends FrameLayout
{
///Attempts to add children to this layout will actually get forwarded through to mChildContainer.
///This would be final, but it's actually used indirectly by the constructor before it's initialised.
private ViewGroup mChildContainer;
public WrappedLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
//read the custom attributes
final int layoutToInflate;
final int childContainerID;
{
final TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.WrappedLayout);
layoutToInflate = styledAttributes.getResourceId(R.styleable.WrappedLayout_layoutToInflate, 0);
childContainerID = styledAttributes.getResourceId(R.styleable.WrappedLayout_childContainerID, 0);
styledAttributes.recycle();
}
if(layoutToInflate == 0
|| childContainerID == 0)
{
Log.e("Error", "WrappedLayout.WrappedLayout(): Error reading custom attributes from XML. layoutToInflate = " + layoutToInflate + ", childContainerID =" + childContainerID);
}
else
{
//inflate the layout and (implicitly) add it as a child view
final View inflatedLayout = View.inflate(context, layoutToInflate, this);
//grab the reference to the container to pass children through to
mChildContainer = (ViewGroup)inflatedLayout.findViewById(childContainerID);
}
}
///All the addView() overloads eventually call this method.
#Override
public void addView(View child, int index, ViewGroup.LayoutParams params)
{
if(mChildContainer == null)
{
//still inflating - we're adding one of the views that makes up the wrapper structure
super.addView(child, index, params);
}
else
{
//finished inflating - forward the view through to the child container
mChildContainer.addView(child, index, params);
}
}
}
This works, as far as I can tell. It doesn't work very well with the Eclipse layout editor (I'm not quite sure what the problem is), but you can view the layout fine. Changing the children of the WrappedLayout seems to require editing the XML manually.

Have you looked at Applying Styles and Themes?

Related

Can't add TextView to LinearLayout

I'm doing summer lab assignment for my Android class.
In layout_main.xml I have:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/main_menu" />
<fragment
android:name="tests.tinyplanner.ActivityFragment"
android:id="#+id/mainActivityFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
In main_menu.xml I have:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<tests.tinyplanner.ThemeButton
android:id="#+id/todoButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/todo_button_title" />
<tests.tinyplanner.ThemeButton
android:id="#+id/calendarButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/calendar_button_title" />
<tests.tinyplanner.ThemeButton
android:id="#+id/notesButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/notes_button_title" />
</LinearLayout>
For layout_main.xml I have a class:
package tests.tinyplanner;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
public class MainLayout extends LinearLayout {
private View todoButton;
private View calendarButton;
private View notesButton;
private LayoutInflater inflater_;
private View inflateView_;
private void doInflate(Context context) {
this.inflater_ = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.inflateView_ = this.inflater_.inflate(R.layout.layout_main, this);
this.todoButton = this.inflateView_.findViewById(R.id.todoButton);
this.calendarButton = this.inflateView_.findViewById(R.id.calendarButton);
this.notesButton = this.inflateView_.findViewById(R.id.notesButton);
}
public MainLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.doInflate(context);
}
public MainLayout(Context context) {
this(context, null);
}
public View getTodoButton() {
return this.todoButton;
}
public View getCaldendarButton() {
return this.calendarButton;
}
public View getNotesButton() {
return this.notesButton;
}
}
I use this layout in MainActivity
this.layout = new MainLayout(this);
TextView logoTextView = (TextView)((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.logo_layout, null);
((MainLayout) this.layout).addView(logoTextView);
this.setContentView(this.layout);
this.todoButton = ((MainLayout)this.layout).getTodoButton();
this.todoButton.setOnClickListener(this);
this.calendarButton = ((MainLayout)this.layout).getCaldendarButton();
this.calendarButton.setOnClickListener(this);
this.notesButton = ((MainLayout)this.layout).getNotesButton();
this.notesButton.setOnClickListener(this);
All buttons are displayed correctly. The problem is that logoTextView is not displayed at all. logo_layout is like this:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:text="#string/logo_title"
android:id="#+id/logoTextView"
android:theme="#style/LogoTheme"
android:layout_height="wrap_content" >
</TextView>
LogoTheme is like this:
<style name="LogoTheme">
<item name="android:textStyle">bold</item>
<item name="android:textColor">#color/colorFontButtonDefault</item>
<item name="android:textAllCaps">true</item>
<item name="android:ems">80</item>
<item name="android:textSize">18sp</item>
<item name="android:gravity">center</item>
<item name="android:textAlignment" tools:targetApi="17">center</item>
</style>
Why is logoTextView not displayed?
Couple of things went wrong in your code. Before jumping into it, let me clear some concept
1) By default, orientation for Linear layout will be Horizontal. It means that all child view will be stack horizontally inside linear layout based on width defined for each child.
| ChildA | ChildB | ChildC |
2) If Any one child defines width as "MATCH_PARENT" then it will not allow to show other child underneath it, just like below
| ChildA | (Not visible) childB | (Not visible) childC|
Based on this information, Let try to understand your issue
First thing: Inside MainActivity, where you try to create a MainLayout, you need to specify Orientation for MainLayout
this.layout = new MainLayout(this);
((MainLayout)this.layout).setOrientation(LinearLayout.VERTICAL);
This will allow to stack all children vertically so that we can see all children
Second thing:, Inside layout_main.xml, please define layout_height of Linear layout as "wrap_content". This will allow your logotext to be seen on screen
<?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:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="#layout/main_menu" />
<fragment
android:name="tests.tinyplanner.ActivityFragment"
android:id="#+id/mainActivityFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
EDIT: (Why need to add orientation even though setting it from XML)
Lets check how MainLayout is created. First we created instance of MainLayout inside Activity. which in turn call doInflatelayout() inside main layout.
By doing so what we are doing is, we create a linear layout and inside inflate new linear layout (with orientation set from XML)
By looking at the View Hierarchy:
MainLayout (Parent)
LinearLayout (with Orientation inside XML)
Linear Layout ( with ThemeButton and Orientation set from XML)
Now You have Orientation set for first child of MainLayout. But you are not setting orientation for MainLayout.
So we need to set Orientation for MainLayout when we create it.
I hope this will help you

Common Header with click events of Header from all Activities in Xamarin android

I am developing a xamarin android application, where I used to call a Header activity in all Activities. My code is as Fallows
My Main.axml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- Header aligned to top -->
<include layout="#layout/Header"
android:id="#+id/includeheader"
android:layout_alignParentTop="true" />
<!-- Content below header and above footer -->
<include layout="#layout/Content"
android:id="#+id/includecontent" />
<!-- Footer aligned to bottom -->
<include layout="#layout/Footer"
android:id="#+id/includefooter"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
My Header.axml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:minHeight="50dip">
<TableRow
android:background="#2c2c2c"
android:padding="10dip">
<TextView
android:id="#+id/scanHome"
android:layout_width="0dip"
android:layout_weight="2.5"
android:textSize="22sp"
android:textStyle="bold"
android:gravity="center"
android:text="" />
<Button
android:id="#+id/Settings"
android:layout_width="0dip"
android:layout_height="30dip"
android:layout_marginLeft="10dip"
android:layout_weight="0.17"
android:gravity="center"
android:width="35dip"
android:clickable="true"
android:onClick="SettingsClick"/>
<Button
android:id="#+id/logout"
android:layout_width="0dip"
android:layout_height="40dip"
android:layout_weight="0.27"
android:gravity="center"
android:width="40dip" />
</TableRow>
</TableLayout>
</LinearLayout>
MainActivity.class
namespace LayoutApp
{
[Activity(Label = "LayoutApp", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Header
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
setHeading("Scan Home");
}
}
}
Header.class
[Activity(Label = "LayoutApp", MainLauncher = false)]
public abstract class Header : Activity , View.IOnClickListener
{
private TextView HeaderText;
private Button Settings;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Header);
Settings = FindViewById<Button>(Resource.Id.Settings);
Settings.Click += delegate
{
};
}
protected void setHeading(string text)
{
if (HeaderText == null)
HeaderText = FindViewById<TextView>(Resource.Id.scanHome);
if (HeaderText != null)
HeaderText.Text = text;
}
public void SettingsClick()
{
}
}
Hence I am using Header Activity in MainActivity like in native android using include Property. When I load Main Launcher, Header is also displaying but click events are not working from the MainActivity where as text is applying from setHeading method.
When debugging , error is populating as 'java.lang.illegalistateexception: could not find a method SettingsClick(View) in the activityclass for onclick handler on view class'.
So, my issue here is I would like to get click events of Header.
The layout files (AXML) are not linked to Activities with the same names as theirs.
In your Main.axml code, you are including (adding) the layout code from Header.axml; however, your MainActivity.cs code has no relations with the Main.axml, just like the HeaderActivity.cs code has no relations with the Header.axml code.
In the MainActivity.cs code, the SetContentView(Resource.Layout.Main) applies the Main.axml layout (which contains the Header.axml code) to your MainActivity, but does not apply the methods from HeaderActivity.cs.
If you want an app with Toolbar and Bottom Bar in your app, there is a good tutorial here: http://mateoj.com/2015/06/21/adding-toolbar-and-navigation-drawer-all-activities-android/
You should also take a look on Android Fragments.
#kumar Sudheer, I don't know the xamarin development, but I can understand what you want to do by looking at the code and exception you get.
Just pass the View object as parameter in the SettingClick method of your header activity
public void SettingsClick(View v)
{
}
In android when you define the click handler in layout file then the signature of that method would be public void <clickHandler>(View v) {}.
You've not passed the View parameter in the method that's why system is unable to find your method in Activity and that's why you are getting the java.lang.IllegaliStateException

How to extract current Android layout segments into their own custom control?

OK, I have a complete layout built; however, I am not really pleased with the long xml file that has resulted. I have a shorted version of the xml outline and designer view below. And I was wondering how I can abstract out each group of similar components into their own custom control.
For example, in the picture below, I have highlighted one such control that I would like to abstract out. Instead of it being a LinearLayout with 2 TextView's inside with their own properties and attributes set. I would like to reference it via <package-name.individual_song_item
android:layout...> ... </>. All I would have to do is set the first TextView's text along with the second one via attributes in the top-level component.
How can this be done? I have the layout done and complete, but I don't like that nothing is abstracted away.
So the expected results that I am looking for are (if you look at the right-side of the image. there would only be one LinearLayout below the image, and the rest would be <package-name.individual_song_item>)
I have tried to just create a new layout xml with just the subsets of components, but I was not able to make it work when combining it back.
OLD WAY
<LinearLayout >
<ImageView />
<LinearLayout >
<LinearLayout >
<TextView />
<TextView />
</LinearLayout>
<LinearLayout >
<TextView />
<TextView />
</LinearLayout>
<LinearLayout >
<TextView />
<TextView />
</LinearLayout>
....
</LinearLayout>
</LinearLayout>
POSSIBLE PROPOSED WAY
<LinearLayout >
<ImageView />
<LinearLayout >
<com.example.individual_song_item />
<com.example.individual_song_item />
<com.example.individual_song_item />
....
<com.example.individual_song_item <!-- example (possible!?!?) -->
....
app:label="Group"
app:value="Group Name" />
</LinearLayout>
</LinearLayout>
Create a custom layout eg.
public class IndividualSongItem extends LinearLayout {
private String mSong;
private String mSongName;
public IndividualSongItem(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public IndividualSongItem(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IndividualSongItem);
try {
// Read in your custom layout's attributes,
// for example song and songName text attributes
CharSequence s = a.getString(R.styleable.IndividualSongItem_song);
if (s != null) {
setSong(s.toString());
}
s = a.getString(R.styleable.IndividualSongItem_songName);
if (s != null) {
setSongName(s.toString());
}
} finally {
a.recycle();
}
}
....etc
You will also need to create an attributes XML for your new layout class.
For a full example of how to do what you're after look at the LabelView example in the ApiDemos.
It's also very well explained here.

How to implement Custom View as part of MVC?

So I'm experimenting with implementing an MVC pattern in Android where my views are subclassed from RelativeLayout, LinearLayout, ScrollView, etc... It's working until I try to get a hold of a view within my view. I get an NPE. I've tried accessing the view in order to set the onClickListener in the constructor and also in onAttachedToWindow(), but I get the NPE in both places.
For example, here's a view class:
public class ViewAchievements extends LinearLayout
{
private RelativeLayout mRelativeLayoutAchievement1;
public ViewAchievements(Context context, AttributeSet attrs)
{
super(context, attrs);
mRelativeLayoutAchievement1 = (RelativeLayout) findViewById(R.id.relativeLayout_achievement1);
mRelativeLayoutAchievement1.setOnClickListener((OnClickListener) context); //NPE on this line
}
#Override
protected void onAttachedToWindow()
{
super.onAttachedToWindow();
mRelativeLayoutAchievement1.setOnClickListener(mOnClickListener); //Also get NPE on this line
}
}
Can someone please tell me the proper way to get a hold of my subviews, in this case mRelativeLayoutAchievement1?
Here's an XML snippet:
<com.beachbody.p90x.achievements.ViewAchievements xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/gray_very_dark"
android:orientation="vertical" >
<!-- kv Row 1 -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:layout_weight="1"
android:baselineAligned="false">
<RelativeLayout
android:id="#+id/relativeLayout_achievement1"
style="#style/linearLayout_achievement"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_margin="#dimen/margin_sm"
android:layout_weight="1" >
<TextView
android:id="#+id/textView_achievement1"
style="#style/text_small_bold_gray"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="#dimen/margin_large"
android:text="1/20" />
</RelativeLayout>
...
And here's how I'm creating the view from my Activity:
public class ActivityAchievements extends ActivitySlidingMenu
{
private ViewAchievements mViewAchievements;
#Override
public void onCreate(Bundle savedInstanceState)
{
mViewAchievements = (ViewAchievements) View.inflate(this, R.layout.view_achievements, null);
setContentView(mViewAchievements);
...
You're trying to get the child views during the view's constructor. Since they are child views, they haven't been inflated yet. Can you move this code out of the constructor, possibly into View.onAttachedToWindow()?
http://developer.android.com/reference/android/view/View.html#onAttachedToWindow()

How to use the xml setting in a view of a activity?

I want to show two views in one activity. If I clicked on button in the first view I want to see the second and other way round.
The views should not have the same size as the screen so I want e.g. to center it, like you see in first.xml.
But if I add the views with
addContentView(mFirstView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
the views are not centered. They are shown at top left.
How can I use the xml settings to e.g. center it?
first.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:background="#drawable/background"
android:layout_gravity="center"
android:minWidth="100dp"
android:minHeight="100dp"
android:paddingBottom="5dp"
>
<LinearLayout android:id="#+id/head"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageButton android:id="#+id/first_button"
android:src="#drawable/show_second"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#null" />
</LinearLayout>
second.xml same as first.xml but with
<ImageButton android:id="#+id/second_button"
android:src="#drawable/show_first"
... />
ShowMe.java
public class ShowMe extends Activity {
View mFirstView = null;
View mSecondView = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initFirstLayout();
initSecondLayout();
showFirst();
}
private void initFirstLayout() {
LayoutInflater inflater = getLayoutInflater();
mFirstView = inflater.inflate(R.layout.first, null);
getWindow().addContentView(mFirstView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
ImageButton firstButton = (ImageButton)mMaxiView.findViewById(R.id.first_button);
firstButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ShowMe.this.showSecond();
}
});
}
private void initSecondLayout() {
// like initMaxiLayout()
}
private void showFirst() {
mSecondView.setVisibility(View.INVISIBLE);
mFirstView.setVisibility(View.VISIBLE);
}
private void showSecond() {
mFirstView.setVisibility(View.INVISIBLE);
mSecondView.setVisibility(View.VISIBLE);
}}
Hope someone can help.
Thanks
Why don't you use setContentView(R.layout.yourlayout)? I believe the new LayoutParams you're passing in addContentView() are overriding those you defined in xml.
Moreover, ViewGroup.LayoutParams lacks the layout gravity setting, so you would have to use the right one for the layout you're going to add the view to (I suspect it's a FrameLayout, you can check with Hierarchy Viewer). This is also a general rule to follow. When using methods that take layout resources as arguments this is automatic (they might ask for the intended parent).
With this consideration in mind, you could set your layout params with:
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(/* wrap wrap */);
lp.setGravity(Gravity.CENTER);
addContentView(mYourView, lp);
But I would recommend setContentView() if you have no particular needs.
EDIT
I mean that you create a layout like:
~~~/res/layout/main.xml~~~
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="....."
android:id="#+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
then in your onCreate() or init...Layout():
setContentView(R.layout.main);
FrameLayout mainLayout = (FrameLayout)findViewById(R.id.mainLayout);
// this version of inflate() will automatically attach the view to the
// specified viewgroup.
mFirstView = inflater.inflate(R.layout.first, mainLayout, true);
this will keep the layout params from xml, because it knows what kind it needs. See reference.

Categories

Resources