片段中的 super.onCreateView

Posted

技术标签:

【中文标题】片段中的 super.onCreateView【英文标题】:super.onCreateView in Fragments 【发布时间】:2014-05-08 21:19:51 【问题描述】:

我完成了有关 android 手持系统的移动应用程序编程的 Coursera 课程。 该课程的示例代码之一教我们如何使用片段。基本上它所做的是将屏幕分成两个片段,一个用于书名,另一个用于书名。如果用户点击左侧片段中的标题,则与该书关联的引用将显示在右侧片段中。

这是 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);
        
    

这是引用片段的代码:

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;

这是标题片段的代码:

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

    <fragment
        android:id="@+id/titles"
        android:layout_
        android:layout_
        android:layout_weight="1"
        class="course.examples.Fragments.StaticLayout.TitlesFragment" />

    <fragment
        android:id="@+id/details"
        android:layout_
        android:layout_
        android:layout_weight="2"
        class="course.examples.Fragments.StaticLayout.QuotesFragment" />

</LinearLayout>

引用片段 xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical" >

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

标题片段 xml

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

</TextView>

我的问题是为什么 onCreateView 下的方法在引用片段和标题片段下不同? QuoteFragment 是 return inflater.inflate(R.layout.quote_fragment, container, false); TitleFragment 是 return super.onCreateView(inflater, container, savedInstanceState);

【问题讨论】:

grepcode.com/file/repository.grepcode.com/java/ext/…。检查源代码 Raghunandan,你知道android怎么知道它必须将标题片段膨胀到main.xml中吗?在 Quote 片段的代码中,我们有 mDetailsFragment = (QuotesFragment) getFragmentManager().findFragmentById(R.id.details)。标题片段没有类似的代码。我的猜测是主要的 activity.xml 通过 class="course.examples.Fragments.StaticLayout.TitlesFragment" 引用它,因此它膨胀了它,但我不确定...... 是的,请提出一个我会回答的新问题 【参考方案1】:

因为QuotesFragment 扩展了Fragment,默认情况下没有布局,用户必须膨胀并返回自己的布局。这就是FragmentonCreateView 方法的样子:

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

TitlesFragment 扩展了 ListFragment,其默认布局包含 ListView 用于项目,TextView 用于列表为空时的标签和ProgressBar。在这种情况下,用户不必返回自己的视图,可以返回通过 super 调用获得的对象。 onCreateViewListFragment

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) 
    return inflater.inflate(com.android.internal.R.layout.list_content,
            container, false);

【讨论】:

非常感谢您的解释,这很有意义! @Simon 实际上你可以在 ListFragment 中删除 onCreateView【参考方案2】:

因为ListFragment 已经有一个默认布局,其中只包含它使用的ListView。您可以像使用其他 Fragment 一样扩展自定义布局,但这不是必需的。如果您只想使用 ListView,则可以返回 super.onCreateView(...)

如果您想使用自定义布局,您必须记住将此 ID 用于您的 ListView

android:id="@android:id/list"

【讨论】:

【参考方案3】:

你有

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

ListFragment 具有由单个列表视图组成的默认布局。因此,如果您不希望屏幕上显示任何其他视图,则无需扩充自定义布局。

查看ListFragment的来源。您的 Fragment 类扩展了 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    

第 193 行表示默认布局膨胀

你还有

public class QuotesFragment extends Fragment 

还有这个

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

你正在做的是膨胀一个名为quote_fragment.xml的自定义布局

编辑:

假设您想在ListFragment 中显示其他视图,您需要扩展自定义布局。并且该布局必须具有 ListFragment 和 id @android:id/list

【讨论】:

感谢您的解释,这很有意义! @Simon 实际上你可以在ListFragment 中去掉onCreateView,这无论如何都不会影响代码 嗯...你是对的 Raghunandan!我只是在 AVD 上测试了它,它对应用程序没有影响。我想知道为什么课程协调员把它放在代码中......可能是为了向我们展示片段类的生命周期以及迷惑新手哈哈。

以上是关于片段中的 super.onCreateView的主要内容,如果未能解决你的问题,请参考以下文章

操作栏标签片段中的片段?

片段对话框中的片段膨胀引发错误“片段未创建视图”

当前一个片段中的某些任务完成时如何通知另一个片段中的适配器

如何处理片段和活动中的后压

从另一个片段中的目录更新片段中的列表视图元素

ViewPager2 中的片段在返回父片段时被重新创建