Android : ViewPager inside DialogFragment : Fragment does not have a view

有些话、适合烂在心里 提交于 2020-01-15 03:11:50

问题


I am trying to create an alertDialog with a pageView inside with a cancel and ok button.

The problem is when I set the adapter in the method onCreateDialog, I got:

"java.lang.IllegalStateException : Fragment does not have a view".

If I comment out this line, I don't have an exception.

I have tried also by override the method onCreateView() in the class MyDialog, the problem is the same.

Someone have an idea?

MainActivity.java

public class MainActivity  extends FragmentActivity {

    private Button button;

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

        button = (Button) findViewById(R.id.button);

        // Capture button clicks
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                MyDialog alertdFragment = new MyDialog();
                alertdFragment.show(getSupportFragmentManager(), "Alert Dialog Fragment");
            }
        });
    }
}

MyDialog.java

public class MyDialog extends DialogFragment implements OnTabChangeListener, OnPageChangeListener {

    private ViewPager viewPager;
    private View view;
    private TabHost tabHost;

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

    private List<Fragment> getFragments(){
        List<Fragment> fList = new ArrayList<Fragment>();

        // TODO Put here your Fragments
        fList.add(DetailsFragment.newInstance(1,"S1"));
        fList.add(DetailsFragment.newInstance(2,"S2"));
        fList.add(DetailsFragment.newInstance(3,"S3"));

        return fList;
    }

    // Method to add a TabHost
    private static void AddTab(FragmentActivity fragmentActivity, TabHost tabHost, TabHost.TabSpec tabSpec) {
        tabSpec.setContent(new MyTabFactory(fragmentActivity));
        tabHost.addTab(tabSpec);
    }

    // Manages the Tab changes, synchronizing it with Pages
    public void onTabChanged(String tag) {
        int pos = this.tabHost.getCurrentTab();
        this.viewPager.setCurrentItem(pos);
    }

    // Manages the Page changes, synchronizing it with Tabs
    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
        int pos = this.viewPager.getCurrentItem();
        this.tabHost.setCurrentTab(pos);
    }


    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Builder builder = new Builder(getActivity());
        view = getActivity().getLayoutInflater().inflate(R.layout.dialog, null);
        viewPager = (ViewPager) view.findViewById(R.id.viewpager);

        tabHost = (TabHost) view.findViewById(android.R.id.tabhost);
        tabHost.setup();

        // TODO Put here your Tabs
        AddTab(getActivity(), this.tabHost, this.tabHost.newTabSpec("Tab1").setIndicator("Tab1"));
        AddTab(getActivity(), this.tabHost, this.tabHost.newTabSpec("Tab2").setIndicator("Tab2"));
        AddTab(getActivity(), this.tabHost, this.tabHost.newTabSpec("Tab3").setIndicator("Tab3"));

        tabHost.setOnTabChangedListener(this);

        // Fragments and ViewPager Initialization
        List<Fragment> fragments = getFragments();
        viewPager.setAdapter(new FragmentAdapter(getChildFragmentManager(), fragments));
        viewPager.setOnPageChangeListener(this);

        // Positive button
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                // Do something else
            }
        });

        // Negative Button
        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                // Do something else
            }
        });
        builder.setView(view);
        return builder.create();
    }

    @Override
    public void onPageScrollStateChanged(int arg0) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onPageSelected(int arg0) {
        // TODO Auto-generated method stub
    }

}

FragmentAdapter.java

public class FragmentAdapter  extends FragmentPagerAdapter {

    private List<Fragment> fragments;

    public FragmentAdapter(FragmentManager fm) {
        super(fm);
    }

    public FragmentAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }

    @Override
    public Fragment getItem(int position) {
        return this.fragments.get(position);
    }

    @Override
    public int getCount() {
        return this.fragments.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return "Page " + position;
    }

    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

}

DetailsFragment.java

public class DetailsFragment extends Fragment {

    // Store instance variables
    private String title;
    private int page;

    // newInstance constructor for creating fragment with arguments
    public static DetailsFragment newInstance(int page, String title) {
        DetailsFragment fragmentFirst = new DetailsFragment();
        Bundle args = new Bundle();
        args.putInt("someInt", page);
        args.putString("someTitle", title);
        fragmentFirst.setArguments(args);
        return fragmentFirst;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        page = getArguments().getInt("someInt", 0);
        title = getArguments().getString("someTitle");
    }

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

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.details, container,false);
        TextView textView = (TextView) view.findViewById(R.id.detailsText);
        textView.setText(page + " -- " + title);
        return view;
    }
}

activity_main.xml

<RelativeLayout 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"
    tools:context=".Main" >

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="dialog" />

</RelativeLayout>

dialog.xml

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TabHost
        android:id="@android:id/tabhost"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <TabWidget
                android:id="@android:id/tabs"
                android:orientation="horizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_weight="0" />

                <FrameLayout
                    android:id="@android:id/tabcontent"
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    android:layout_weight="0" />

                    <android.support.v4.view.ViewPager
                        android:id="@+id/viewpager"
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:layout_gravity="bottom" />

            </LinearLayout>
    </TabHost>
</RelativeLayout>

details.xml

<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/detailsText"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal|center_vertical"
        android:layout_marginTop="20dip"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textSize="30dip" />

</LinearLayout>

Edit : Track list error

11-21 20:12:56.224: E/AndroidRuntime(2864): FATAL EXCEPTION: main
11-21 20:12:56.224: E/AndroidRuntime(2864): java.lang.IllegalStateException: Fragment does not have a view
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.support.v4.app.Fragment$1.findViewById(Fragment.java:1443)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:917)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:472)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.support.v4.view.ViewPager.populate(ViewPager.java:1068)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.support.v4.view.ViewPager.populate(ViewPager.java:914)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1436)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.view.View.measure(View.java:15848)
11-21 20:12:56.224: E/AndroidRuntime(2864):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5012)

回答1:


I haven't tried this, but based on the error my guess would be that you are trying to configure your pager adapter too soon. Since your code is in onCreateDialog, you haven't yet told Android about the view that will go into your dialog, and maybe it needs your view hierarchy to be in place before you work with the child fragment manager.

Try moving all the code having to do with the view pager and tab host into onResume:

@Override
public void onResume() {
    super.onResume();
    if (viewPager != null) {
        return;
    }

    viewPager = (ViewPager) findViewById(R.id.viewpager);

    tabHost = (TabHost) findViewById(android.R.id.tabhost);
    tabHost.setup();

    // TODO Put here your Tabs
    AddTab(getActivity(), this.tabHost, this.tabHost.newTabSpec("Tab1").setIndicator("Tab1"));
    AddTab(getActivity(), this.tabHost, this.tabHost.newTabSpec("Tab2").setIndicator("Tab2"));
    AddTab(getActivity(), this.tabHost, this.tabHost.newTabSpec("Tab3").setIndicator("Tab3"));

    tabHost.setOnTabChangedListener(this);

    // Fragments and ViewPager Initialization
    List<Fragment> fragments = getFragments();
    viewPager.setAdapter(new FragmentAdapter(getChildFragmentManager(), fragments));
    viewPager.setOnPageChangeListener(this);
}

EDIT: Hmmm. Maybe the issue is that you need to let the fragments get built earlier in the life cycle, and then call setAdapter later. Try moving all the code except the actual call to setAdapter back where you had it in onCreateDialog, including saving the FragmentAdapter in a field, and then JUST call setAdapter in your onResume:

@Override
public void onResume() {
    super.onResume();
    viewPager.setAdapter(fragmentAdapter);
}


来源:https://stackoverflow.com/questions/27041764/android-viewpager-inside-dialogfragment-fragment-does-not-have-a-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!