How to initialize a Fragements with attributes as a Bundle at runtime and from attributes in a layout?

By | June 6, 2013

This post Demonstrates a fragment that can be configured through both Bundle arguments
and layout attributes.

Fragments

You can click on the links to download the source code.

Here there are two fragments in the layout, one is directly in the layout and the other is created dynamically with arguments at runtime.
Here is how we do it.
At first I will show you layout that contains the fragments.
fragment_arguments.xml

<?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:gravity="center_horizontal"
    android:orientation="vertical"
    android:padding="4dip" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal"
        android:layout_weight="0"
        android:gravity="top|center_horizontal"
        android:padding="4dip"
        android:text="@string/fragment_arguments_msg"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="4dip" >

        <fragment
            android:id="@+id/embedded"
            android:layout_width="0px"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            class="com.example.argumentsfragment.FragmentArguments$MyFragment"
            android:label="@string/fragment_arguments_embedded" />

        <FrameLayout
            android:id="@+id/created"
            android:layout_width="0px"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>

</LinearLayout>

Now the layout for each fragment.
hello_world.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical|center_horizontal"
    android:text="@string/hello_world"
    android:textAppearance="?android:attr/textAppearanceMedium" />

OK layouts are now complete.

Now the activity that does the thing that we want to do.
FragmentArguments.java

package com.example.argumentsfragment;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * Demonstrates a fragment that can be configured through both Bundle arguments
 * and layout attributes.
 */
public class FragmentArguments extends Activity {

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_arguments);

        if (savedInstanceState == null) {
            // First-time init; create fragment to embed in activity.
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            Fragment newFragment = MyFragment.newInstance("From Arguments");
            ft.add(R.id.created, newFragment);
            ft.commit();
        }
    }



    public static class MyFragment extends Fragment {
        CharSequence mLabel;

        /**
         * Create a new instance of MyFragment that will be initialized
         * with the given arguments.
         */
        static MyFragment newInstance(CharSequence label) {
        	System.out.println("newInstance");
            MyFragment f = new MyFragment();
            Bundle b = new Bundle();
            b.putCharSequence("label", label);
            f.setArguments(b);
            return f;
        }

        /**
         * Parse attributes during inflation from a view hierarchy into the
         * arguments we handle.
         */
        @Override public void onInflate(Activity activity, AttributeSet attrs,
                Bundle savedInstanceState) {
        	System.out.println("onInflate");
            super.onInflate(activity, attrs, savedInstanceState);

            TypedArray a = activity.obtainStyledAttributes(attrs,
                    R.styleable.FragmentArguments);
            mLabel = a.getText(R.styleable.FragmentArguments_android_label);
            a.recycle();
        }

        /**
         * During creation, if arguments have been supplied to the fragment
         * then parse those out.
         */
        @Override public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            System.out.println("onCreate");
            Bundle args = getArguments();
            if (args != null) {
                mLabel = args.getCharSequence("label", mLabel);
            }
        }

        /**
         * Create the view for this fragment, using the arguments given to it.
         */
        @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
        	System.out.println("onCreateView");
            View v = inflater.inflate(R.layout.hello_world, container, false);
            View tv = v.findViewById(R.id.text);
            ((TextView)tv).setText(mLabel != null ? mLabel : "(no label)");
            tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb));
            return v;
        }
    }

}

Now create a file named “attr.xml” inside the res/values folder and copy this code into it.
It contains the styelable attribute.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="FragmentArguments">
        <attr name="android:label" />
    </declare-styleable>

</resources>

and copy these code to the strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">ArgumentsFragment</string>
    <string name="hello_world">Hello world!</string>
    <string name="menu_settings">Settings</string>
    <string name="fragment_arguments_msg">Demonstrates a fragment that takes arguments
        as a Bundle at runtime (on the right) or from attributes in a layout (on the left).</string>
    <string name="fragment_arguments_embedded">From Attributes</string>

</resources>

All code is now complete. Go on and run the project.

You can download the complete source code from here.

One thought on “How to initialize a Fragements with attributes as a Bundle at runtime and from attributes in a layout?

  1. Pingback: Use of custom animations in a FragmentTransaction when pushing and popping a stack. or How to apply animations in Fragments when pushing on to a stack? | Android Forever

Leave a Reply

Your email address will not be published. Required fields are marked *