Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

super.onCreateView in Fragments

I finished the Coursera course on Programming Mobile Applications for Android Handheld Systems. One of the example code from the course teaches us how to us fragments. Basically what it does is it splits the screen into two fragments, one for book titles and one for quotes from the book. If a user clicks on a title in a fragment on the left, the quote associated from the book is displayed in fragment on the right.

This is the code for the mainActivity:

package course.examples.Fragments.StaticLayout;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import course.examples.Fragments.StaticLayout.TitlesFragment.ListSelectionListener;

public class QuoteViewerActivity extends Activity implements
        ListSelectionListener {

    public static String[] mTitleArray;
    public static String[] mQuoteArray;
    private QuotesFragment mDetailsFragment;

    private static final String TAG = "QuoteViewerActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mTitleArray = getResources().getStringArray(R.array.Titles);    
        mQuoteArray = getResources().getStringArray(R.array.Quotes);

        setContentView(R.layout.main);

        mDetailsFragment = (QuotesFragment) getFragmentManager()
                .findFragmentById(R.id.details);        
    }

    @Override
    public void onListSelection(int index) {
        if (mDetailsFragment.getShownIndex() != index) {        
            mDetailsFragment.showQuoteAtIndex(index);
        }
    }

This is the code for the Quote fragment:

package course.examples.Fragments.StaticLayout;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class QuotesFragment extends Fragment {

    private TextView mQuoteView = null;
    private int mCurrIdx = -1;
    private int mQuoteArrayLen;

    private static final String TAG = "QuotesFragment";

    public int getShownIndex() {
        return mCurrIdx;
    }

    public void showQuoteAtIndex(int newIndex) {
        if (newIndex < 0 || newIndex >= mQuoteArrayLen)
            return;
        mCurrIdx = newIndex;
        mQuoteView.setText(QuoteViewerActivity.mQuoteArray[mCurrIdx]);
    }
@Override
public void onAttach(Activity activity) {
    Log.i(TAG, getClass().getSimpleName() + ":entered onAttach()");
    super.onAttach(activity);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    Log.i(TAG, getClass().getSimpleName() + ":entered onCreate()");
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    **return inflater.inflate(R.layout.quote_fragment, container, false);**
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {      
    super.onActivityCreated(savedInstanceState);
    mQuoteView = (TextView) getActivity().findViewById(R.id.quoteView);
    mQuoteArrayLen = QuoteViewerActivity.mQuoteArray.length;
}

This is the code for the title fragment:

package course.examples.Fragments.StaticLayout;

import android.app.Activity;
import android.app.ListFragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class TitlesFragment extends ListFragment {
    private ListSelectionListener mListener = null;
    private static final String TAG = "TitlesFragment";

    public interface ListSelectionListener {
        public void onListSelection(int index);     
    }

    @Override
    public void onListItemClick(ListView l, View v, int pos, long id) {
        getListView().setItemChecked(pos, true);
        mListener.onListSelection(pos);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (ListSelectionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnArticleSelectedListener");
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, getClass().getSimpleName() + ":entered onCreate()");
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.i(TAG, getClass().getSimpleName() + ":entered onCreate()");

        **return super.onCreateView(inflater, container, savedInstanceState);**

    }

    @Override
    public void onActivityCreated(Bundle savedState) {
        super.onActivityCreated(savedState);

        getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        setListAdapter(new ArrayAdapter<String>(getActivity(),
                R.layout.title_item, QuoteViewerActivity.mTitleArray));
    }

MainActivity 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:baselineAligned="false"
    android:orientation="horizontal" >

    <fragment
        android:id="@+id/titles"
        android:layout_width="0px"
        android:layout_height="match_parent"
        android:layout_weight="1"
        class="course.examples.Fragments.StaticLayout.TitlesFragment" />

    <fragment
        android:id="@+id/details"
        android:layout_width="0px"
        android:layout_height="match_parent"
        android:layout_weight="2"
        class="course.examples.Fragments.StaticLayout.QuotesFragment" />

</LinearLayout>

Quote Fragments 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:orientation="vertical" >

    <TextView
        android:id="@+id/quoteView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="5dip"
        android:textSize="32sp" >
    </TextView>
</LinearLayout>

Title fragment xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:attr/activatedBackgroundIndicator"
    android:orientation="vertical"
    android:padding="5dip"
    android:textSize="32sp" >

</TextView>

My question is why does the method under onCreateView differ under Quote fragment and Title fragment? QuoteFragment is return inflater.inflate(R.layout.quote_fragment, container, false); TitleFragment is return super.onCreateView(inflater, container, savedInstanceState);

like image 298
Simon Avatar asked Mar 29 '14 09:03

Simon


People also ask

What is difference between onCreateView and onViewCreated in fragment?

onCreateView() is called by Android once the Fragment should inflate a view. onViewCreated() is called after onCreateView() and ensures that the fragment's root view is non-null .

What does the onCreateView method return if a fragment doesn't have any UI?

These files contain only the onCreateView() method to inflate the UI of the fragment and returns the root of the fragment layout. If the fragment does not have any UI, it will return null.

What is onCreateView?

onCreateView(LayoutInflater, ViewGroup, Bundle) creates and returns the view hierarchy associated with the fragment. onActivityCreated(Bundle) tells the fragment that its activity has completed its own Activity.

What are retained fragments?

Retained fragments take advantage of the fact that a fragment's view can be destroyed and recreated without having to destroy the fragment itself. During a configuration change, the FragmentManager first destroys the views of the fragments in its list.


3 Answers

Because QuotesFragment extends Fragment that doesn't have layout by default and a user has to inflate and return his own layout. This is how onCreateView method of a Fragment looks like:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
    return null;
}

TitlesFragment extends ListFragment that has a layout by default that contains ListView for items, TextView for a label when a list is empty and ProgressBar. In this case the user doesn't have to return his own view and can return an object obtained by the super call. onCreateView of the ListFragment:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    return inflater.inflate(com.android.internal.R.layout.list_content,
            container, false);
}
like image 80
makovkastar Avatar answered Nov 15 '22 15:11

makovkastar


Because a ListFragment already has a default layout containing just the ListView used by it. You can inflate a custom layout like with the other Fragment, but it is not necessary. If you just want to use a ListView than you can return super.onCreateView(...).

If you would want to use a custom layout you have to remember to use this id for your ListView:

android:id="@android:id/list"
like image 24
Xaver Kapeller Avatar answered Nov 15 '22 16:11

Xaver Kapeller


You have

return super.onCreateView(inflater, container, savedInstanceState);

ListFragment has a default layout that consists of a single list view. So there is no need to inflate a custom layout if you don't want any other views displayed on the screen.

Look at the source of ListFragment. Your Fragment class extends ListFragment.

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/android/app/ListFragment.java/

189
190    @Override
191    public View onCreateView(LayoutInflater inflater, ViewGroup container,
192            Bundle savedInstanceState) {
193        return inflater.inflate(com.android.internal.R.layout.list_content,
194                container, false);
195    }

Line 193 indicates the default layout inflated

Further you have

public class QuotesFragment extends Fragment {

and this

return inflater.inflate(R.layout.quote_fragment, container, false);

What you are doing is inflating a custom layout called quote_fragment.xml

Edit:

Suppose you want to display other views in ListFragment you need to inflate a custom layout. And that layout must have ListFragment with id @android:id/list.

like image 24
Raghunandan Avatar answered Nov 15 '22 17:11

Raghunandan