Search code examples
android-fragmentstabsclasscastexceptionfragmentpageradapterpagerslidingtabstrip

java.lang.ClassCastException: android.widget.LinearLayout cannot be cast to android.support.v4.app.Fragment


I get this error java.lang.ClassCastException: android.widget.LinearLayout cannot be cast to android.support.v4.app.Fragment when I try to open my activity CuteCollection.java in my app. The strange part is that when I click on the first line (FragmentPagerAdapter.java:122) in the logcat error, it shows me a line from a file in the v4.support library. I cannot edit that code, so there must be something in my code I can change.

To get to this activity, I click a button in my HomeFragment.java fragment, which is a fragment in my navigation drawer, which also has the android.support.v4.app.Fragment extension, just like all items do in my navigation drawer.

I think it might be something to do with my FragmentPagerAdpater. Although I did change all of my android.app.Fragment to android.support.v4.app.Fragment, but still the same error.

UPDATE: When I click on the first line in the support.v4 library, called FragmentPagerAdapter, it brings up that class and shows Fragment fragment = (Fragment)object; highlighted, which is part of this method (although I can't edit this, since it's from Android):

@Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment)object;
        if (fragment != mCurrentPrimaryItem) {
            if (mCurrentPrimaryItem != null) {
                mCurrentPrimaryItem.setMenuVisibility(false);
                mCurrentPrimaryItem.setUserVisibleHint(false);
            }
            if (fragment != null) {
                fragment.setMenuVisibility(true);
                fragment.setUserVisibleHint(true);
            }
            mCurrentPrimaryItem = fragment;
        }
    }

Any tips or advice? Thanks.

CuteCollectionFragment.java

    package org.azurespot.cutecollection;

import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.astuetz.PagerSlidingTabStrip;

import org.azurespot.R;

/**
 * Created by mizu on 1/26/15.
 */
public class CuteCollection extends ActionBarActivity {

    private static final int PHOTO_TAB = 0;
    private static final int VIDEO_TAB = 1;
    private static final int AUDIO_TAB = 2;
    private static final int TEXT_TAB = 3;

    PhotoTab photoTab;
    TextTab textTab;
    VideoTab videoTab;
    AudioTab audioTab;


    public CuteCollection(){}

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

        // Instantiate tabs
        photoTab = new PhotoTab();
        textTab = new TextTab();
        videoTab = new VideoTab();
        audioTab = new AudioTab();

        // Initialize the ViewPager and set an adapter
        ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
        pager.setAdapter(new TabsAdapter(getSupportFragmentManager()));

        // Bind the tabs to the ViewPager
        PagerSlidingTabStrip tabs = (PagerSlidingTabStrip)
                                            findViewById(R.id.tabs);
        tabs.setViewPager(pager);

    }

    private class TabsAdapter extends FragmentPagerAdapter {

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

        /**
         * @return the number of pages (tabs) to display
         */
        @Override
        public int getCount() {
            return 4;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "Photos";
                case 1:
                    return "Videos";
                case 2:
                    return "Sounds";
                case 3:
                    return "Poems";
            }

            return null;
        }

        /**
         * @return true if the value returned from
         *         {@link #instantiateItem(ViewGroup, int)} is the same object
         *         as the {@link View} added to the {@link ViewPager}.
         */
        @Override
        public boolean isViewFromObject(View view, Object o) {
            return o == view;
        }

        @Override
        public android.support.v4.app.Fragment getItem(int position) {

            switch(position){
                case PHOTO_TAB:
                    Bundle photoBundle = new Bundle();
                    photoBundle.putInt("page_position", position + 1);
                    PhotoTab pt = new PhotoTab();
                    pt.setArguments(photoBundle);
                    return pt;
                case VIDEO_TAB :
                    Bundle videoBundle = new Bundle();
                    videoBundle.putInt("page_position", position + 1);
                    VideoTab vt = new VideoTab();
                    vt.setArguments(videoBundle);
                    return new VideoTab();
                case AUDIO_TAB:
                    Bundle audioBundle = new Bundle();
                    audioBundle.putInt("page_position", position + 1);
                    AudioTab at = new AudioTab();
                    at.setArguments(audioBundle);
                    return new AudioTab();
                case TEXT_TAB:
                    Bundle textBundle = new Bundle();
                    textBundle.putInt("page_position", position + 1);
                    TextTab tt = new TextTab();
                    tt.setArguments(textBundle);
                    return new TextTab();
            }

            return null;

        }

        /**
         * Instantiate the {@link View} which should be displayed at
         * {@code position}. Here we inflate a layout from the apps resources
         * and then change the text view to signify the position.
         */
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            // Inflate a new layout from our resources

            View view = getLayoutInflater().inflate(R.layout.pager_item,
                    container, false);
            // Add the newly created View to the ViewPager
            container.addView(view);

            // Retrieve a TextView from the inflated View, and update it's text
            TextView title = (TextView) view.findViewById(R.id.item_title);
            title.setText(String.valueOf(position));

            // Return the View
            return view;
        }

        /**
         * Destroy the item from the {@link ViewPager}. In our case this is
         * simply removing the {@link View}.
         */
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }
}

fragment_cute_collection.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#2198bb" >

    <com.astuetz.PagerSlidingTabStrip
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        custom:pstsTextColorSelected="#ffffff"
        custom:pstsUnderlineColor="#ffffff"
        custom:pstsIndicatorColor="#ffffff"
        android:textColor="#2198bb"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:background="@android:color/white" />

</RelativeLayout>

Logcat

03-07 18:35:42.669    6340-6340/org.azurespot E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: org.azurespot, PID: 6340
java.lang.ClassCastException: android.widget.LinearLayout cannot be cast to android.support.v4.app.Fragment
        at android.support.v4.app.FragmentPagerAdapter.setPrimaryItem(FragmentPagerAdapter.java:122)
        at android.support.v4.view.ViewPager.populate(ViewPager.java:1071)
        at android.support.v4.view.ViewPager.populate(ViewPager.java:919)
        at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1441)
        at android.view.View.measure(View.java:17619)
        at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:719)
        at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:455)
        at android.view.View.measure(View.java:17619)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
        at android.view.View.measure(View.java:17619)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
        at android.support.v7.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:453)
        at android.view.View.measure(View.java:17619)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
        at android.view.View.measure(View.java:17619)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1410)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
        at android.view.View.measure(View.java:17619)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2588)
        at android.view.View.measure(View.java:17619)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2317)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1412)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1613)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1270)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6691)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:813)
        at android.view.Choreographer.doCallbacks(Choreographer.java:613)
        at android.view.Choreographer.doFrame(Choreographer.java:583)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:799)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:146)
        at android.app.ActivityThread.main(ActivityThread.java:5731)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
        at dalvik.system.NativeStart.main(Native Method)

Solution

  • Your current code seems to run into trouble unless you fix the Exception error. There is a working sample code from Google, and this is quite similar to your code design and meets your vision. I have tried it, and it works. Link at SlidingTabsBasic . One warning is that you will have to change your Gradle build file. If you choose this route, then I can post my build file.

    Another similar sample on the same webpage is SlidingTabsColors, which sounds good since I end up in customizing colors for any GUI I make. The SDKs are possibly available on your local drive if you installed it. If you decide on this route, just accept it as best answer, and post whatever issues you may come up with. At least, I know the sample code works.

    Just to let you know, there is an interesting reading at Creating Swipe Views with Tabs, which meets your vision also, and the code seems simpler than what I recommend above. But...it uses ActionBar.TabListener which is deprecated for Lollipop, API version 21. Your choice...