24

I am aware of the following post: Using Multiple Fragments in an single activity

What I am looking for is a specific answer to a specific problem. The result of the following code is a blank FragmentActivity. What am I missing in my following code to get it to render an activity with two fragments. One is a empty list fragment, the other is a fragment which contains a input box and a button in a horizontal layout, (this layout can be found at http://developer.android.com/training/basics/firstapp/starting-activity.html) that I want to be placed absolutely at the bottom of the screen with a fixed height of about 25 dip.

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.my.package"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.my.package.Application"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

My main activity and its associated application.xml file.

package com.my.package;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;

public class Application  
extends FragmentActivity 
implements MessageListViewFragment.OnLineSelectedListener, 
SendMessageFragment.OnSendButtonPressed {

    MessageListViewFragment mMessageListFragment;
    SendMessageFragment mSendMessageFragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.application);

        mMessageListFragment = new MessageListViewFragment();
        mSendMessageFragment = new SendMessageFragment();

        FragmentTransaction transaction = 
                getSupportFragmentManager().beginTransaction();

        transaction.add(R.id.message_fragment, mMessageListFragment);
        transaction.add(R.id.send_fragment, mSendMessageFragment);

        transaction.commit();
    }

    @Override
    public void onListItemSelected(int position) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onSendButtonPressed() {
        // TODO Auto-generated method stub

    }
}

Layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="vertical" >

    <fragment
        android:id="@+id/message_fragment"
        android:name="com.example.android.fragments.MessageListViewFragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="top" />

    <fragment
        android:id="@+id/send_fragment"
        android:name="com.example.android.fragments.SendMessageFragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="bottom" />

</LinearLayout>

And now for the two fragments and their associated xml files: First Fragment (list fragment at top)

package com.my.package;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MessageListViewFragment extends ListFragment {
    OnLineSelectedListener mCallback;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnLineSelectedListener)activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnLineSelectedListener");
        }
    }

    // Container Activity must implement this interface
    public interface OnLineSelectedListener {
        public void onListItemSelected(int position);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, 
            ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(R.layout.list_fragment, null);
    }
}

Layout:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

second fragment (at bottom)

package com.my.package;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SendMessageFragment extends Fragment {
    OnSendButtonPressed mCallback;

    // Container Activity must implement this interface
    public interface OnSendButtonPressed {
        public void onSendButtonPressed();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, 
            ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(R.layout.input_fragment, null);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnSendButtonPressed)activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }
}

Layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <EditText android:id="@+id/edit_message"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send" />
</LinearLayout>
Community
  • 1
  • 1
Matthew Hoggan
  • 7,402
  • 16
  • 75
  • 140

1 Answers1

29

Do the following:

  1. Change Fragment to FrameLayout in the main activity XML, for both.
  2. Change layout_width from fill_parent to match_parent, for both FrameLayout in the main XML file, (ones created in step 1).
  3. Change layout_height from fill_parent to wrap_content, for both FrameLayout in the main XML file, (ones created in step 1).
  4. Change FrameLayout to ListView in the List Fragment XML because it is a List.
  5. Change the id of this LisView to @android:id/list, because it is needed for the ListFragment.

Then let me know, Cheers.

Edit, also these:

  1. Change return inflater.inflate(R.layout.list_fragment, null); to return inflater.inflate(R.layout.list_fragment, container, false);.
  2. Change return inflater.inflate(R.layout.input_fragment, null); to return inflater.inflate(R.layout.input_fragment, container, false);

Edit:

Make your main activity XML file like this:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/message_fragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <FrameLayout
        android:id="@+id/send_fragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true" />

</RelativeLayout>

I took out the android:name"..." because I don't know what that is nor able to find out what it is, if you know what it does for sure, just add it back, should be okay.

LuckyMe
  • 3,820
  • 2
  • 27
  • 35
  • The button now appears toward the top of the activitie's view no line edit. How does changing the main activity xml files from Fragments to FrameLayouts preserve them as Fragments. This differs from the tutorial at http://developer.android.com/training/basics/fragments/index.html – Matthew Hoggan Jul 10 '13 at 21:53
  • FrameLayout is more general, in any case it shouldn't effect much, google have used FrameLayout in another tutorial. I added an edit to the answer for putting the second layout at the bottom. – LuckyMe Jul 10 '13 at 22:22
  • In here http://developer.android.com/training/implementing-navigation/nav-drawer.html#DrawerLayout a more complex layout, they have used FrameLayout to be a window for a Fragment. – LuckyMe Jul 10 '13 at 22:26
  • Your solution seems to work on a Nexus Tablet but it does not seem to work on my Samsung S3. Is there a reason for this? – Matthew Hoggan Jul 10 '13 at 22:31
  • Not that I know of, what are you getting on the S3? Also, try to rebuild the app, and possibly uninstall it and reinstall it on the S3, it might make a difference. – LuckyMe Jul 10 '13 at 22:35
  • It laaks like a blank activity. Rebuilt and reinstalled and it still looks like a blank activity. – Matthew Hoggan Jul 10 '13 at 22:40
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/33233/discussion-between-luckyme-and-matthew-hoggan) – LuckyMe Jul 10 '13 at 22:45