ViewPager,SlidingTabs和MapFragment

时间:2015-08-10 12:56:14

标签: android android-viewpager

作为一个新手,我试图在滑动标签中使用图标而不是文本视图。问题是,当我更改标签时,我的一个片段(MapFragment)会崩溃应用程序。我知道我可以创建 onDestroy 方法,每次删除片段,但这会导致此片段的奇怪行为。这很奇怪,因为当我使用文本视图而不是图标时,应用程序运行得非常好。

  1. 我认为问题出在SlidingTabLayout,每个帮助和反馈都将受到赞赏。
  2. SlidingTabLayout.java

    public class SlidingTabLayout extends HorizontalScrollView {
    
        public interface TabColorizer {
    
            int getIndicatorColor(int position);
    
        }
    
        private static final int TITLE_OFFSET_DIPS = 24;
        private static final int TAB_VIEW_PADDING_DIPS = 16;
        private static final int TAB_VIEW_TEXT_SIZE_SP = 12;
    
        private int mTitleOffset;
    
        private int mTabViewLayoutId;
        private int mTabViewTextViewId;
        private boolean mDistributeEvenly;
    
        private ViewPager mViewPager;
        private SparseArray<String> mContentDescriptions = new SparseArray<String>();
        private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;
    
        private final SlidingTabStrip mTabStrip;
    
        public SlidingTabLayout(Context context) {
            this(context, null);
        }
    
        public SlidingTabLayout(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
            // Disable the Scroll Bar
            setHorizontalScrollBarEnabled(false);
            // Make sure that the Tab Strips fills this View
            setFillViewport(true);
    
            mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
    
            mTabStrip = new SlidingTabStrip(context);
            addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        }
    
        public void setCustomTabColorizer(TabColorizer tabColorizer) {
            mTabStrip.setCustomTabColorizer(tabColorizer);
        }
    
        public void setDistributeEvenly(boolean distributeEvenly) {
            mDistributeEvenly = distributeEvenly;
        }
    
        public void setSelectedIndicatorColors(int... colors) {
            mTabStrip.setSelectedIndicatorColors(colors);
        }
    
        public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
            mViewPagerPageChangeListener = listener;
        }
    
        public void setCustomTabView(int layoutResId, int textViewId) {
            mTabViewLayoutId = layoutResId;
            mTabViewTextViewId = textViewId;
        }
    
        public void setViewPager(ViewPager viewPager) {
            mTabStrip.removeAllViews();
    
            mViewPager = viewPager;
            if (viewPager != null) {
                viewPager.setOnPageChangeListener(new InternalViewPagerListener());
                populateTabStrip();
            }
        }
    
        private void populateTabStrip() {
            final HomePagerAdapter adapter = (HomePagerAdapter) mViewPager.getAdapter();
            final View.OnClickListener tabClickListener = new TabClickListener();
    
            for (int i = 0; i < adapter.getCount(); i++) {
                View tabView = null;
                ImageView tabIconView = null;
    
                if (tabView == null) {
                    tabView = createDefaultImageView(getContext());
                }
    
                if (tabIconView == null && ImageView.class.isInstance(tabView)) {
                    tabIconView = (ImageView) tabView;
                }
    
                tabIconView.setImageDrawable(getResources().getDrawable(adapter.getIcon(i)));
                if (mViewPager.getCurrentItem() == i) {
                    tabIconView.setSelected(true);
                }
                tabView.setOnClickListener(tabClickListener);
    
                mTabStrip.addView(tabView);
            }
        }
    
        protected ImageView createDefaultImageView(Context context) {
            ImageView imageView = new ImageView(context);
    
            int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
            imageView.setPadding(padding, padding, padding, padding);
    
            int width = (int) (getResources().getDisplayMetrics().widthPixels / mViewPager.getAdapter().getCount());
            imageView.setMinimumWidth(width);
    
            return imageView;
        }
    
    
        @Override
        protected void onAttachedToWindow() {
            super.onAttachedToWindow();
    
            if (mViewPager != null) {
                scrollToTab(mViewPager.getCurrentItem(), 0);
            }
        }
    
        private void scrollToTab(int tabIndex, int positionOffset) {
            final int tabStripChildCount = mTabStrip.getChildCount();
            if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
                return;
            }
    
            View selectedChild = mTabStrip.getChildAt(tabIndex);
            if (selectedChild != null) {
                int targetScrollX = selectedChild.getLeft() + positionOffset;
    
                if (tabIndex > 0 || positionOffset > 0) {
                    // If we're not at the first child and are mid-scroll, make sure we obey the offset
                    targetScrollX -= mTitleOffset;
                }
    
                scrollTo(targetScrollX, 0);
            }
        }
    
        private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
            private int mScrollState;
    
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                int tabStripChildCount = mTabStrip.getChildCount();
                if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
                    return;
                }
    
                mTabStrip.onViewPagerPageChanged(position, positionOffset);
    
                View selectedTitle = mTabStrip.getChildAt(position);
                int extraOffset = (selectedTitle != null)
                        ? (int) (positionOffset * selectedTitle.getWidth())
                        : 0;
                scrollToTab(position, extraOffset);
    
                if (mViewPagerPageChangeListener != null) {
                    mViewPagerPageChangeListener.onPageScrolled(position, positionOffset,
                            positionOffsetPixels);
                }
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
                mScrollState = state;
    
                if (mViewPagerPageChangeListener != null) {
                    mViewPagerPageChangeListener.onPageScrollStateChanged(state);
                }
            }
    
            @Override
            public void onPageSelected(int position) {
                if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
                    mTabStrip.onViewPagerPageChanged(position, 0f);
                    scrollToTab(position, 0);
                }
                for (int i = 0; i < mTabStrip.getChildCount(); i++) {
                    mTabStrip.getChildAt(i).setSelected(position == i);
                }
                if (mViewPagerPageChangeListener != null) {
                    mViewPagerPageChangeListener.onPageSelected(position);
                }
            }
    
        }
    
        private class TabClickListener implements View.OnClickListener {
            @Override
            public void onClick(View v) {
                for (int i = 0; i < mTabStrip.getChildCount(); i++) {
                    if (v == mTabStrip.getChildAt(i)) {
                        mViewPager.setCurrentItem(i);
                        return;
                    }
                }
            }
        }
    
    }
    

    HomePagerAdapter.java

    public class HomePagerAdapter extends FragmentPagerAdapter {
    
        private Pages mPages;
        private int mItemId;
    
        public HomePagerAdapter(FragmentManager fm) {
            super(fm);
        }
    
        public HomePagerAdapter(FragmentManager fm, Pages pages) {
            super(fm);
            mPages = pages;
        }
    
        public HomePagerAdapter(FragmentManager fm, Pages pages, int itemId) {
            super(fm);
            mPages = pages;
            mItemId = itemId;
        }
    
        @Override
        public Fragment getItem(int pos) {
            if(mPages.getCount() == 3) {
                if (pos == 0) {
                    NewestFragment newest = new NewestFragment();
                    return newest;
                } else if (pos == 1) {
                    BestFragment mBest = new BestFragment();
                    return mBest;
                } else {
                    MapFragment map = new MapFragment();
                    return map;
                }
            } else { //number of pages = 2
                if (pos == 0) {
                    if(mPages.getTypes()[0] == Page.TAG) {
                        TagFragment mTagFragment = new TagFragment(mItemId);
                        return mTagFragment;
                    } else { // Page.LOC
                        LocFragment mLocFragment = new LocFragment(mItemId);
                        return mLocFragment;
                    }
                } else {
                    if(mPages.getTypes()[0] == Page.TAG) {
                        BestFragment best = new BestFragment();
                        return best;
                    } else { // PAGE.LOC
                        MapFragment map = new MapFragment();
                        return map;
                    }
                }
            }
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return mPages.getTitles()[position];
        }
    
        @Override
        public int getCount() {
            return mPages.getCount();
        }
    
        public int getIcon(int pos) {
            Page page = mPages.getTypes()[pos];
            if(page == Page.NEWEST)
                return R.drawable.newest_tab;
            if(page == Page.BEST)
                return R.drawable.best_tab;
            if(page == Page.MAP)
                return R.drawable.map_tab;
            if(page == Page.TAG)
                return R.drawable.tag_tab;
            return R.drawable.loc_tab;
        }
    
    }
    

    导致错误片段的声明:

    public class MapFragment extends Fragment implements OnMapReadyCallback{
    
        private GoogleMap mGoogleMap;
        LatLng mMyCoordinates;
        MarkerOptions mCurrentMarker;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.map_fragment, container, false);
            return view;
        }
        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            initilizeMap();
        }
    
        private void initilizeMap() {
            if (mGoogleMap == null) {
                ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)).getMapAsync(this);
            }
        }
    
        @Override
        public void onMapReady(GoogleMap mGoogleMap) {
            this.mGoogleMap = mGoogleMap;
            this.mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mMyCoordinates, 15));
            this.mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
            mCurrentMarker = new MarkerOptions()
                    .position(mMyCoordinates).title("Your location").snippet("This is your place dude")
                    .icon(BitmapDescriptorFactory
                            .fromResource(R.drawable.ic_marker_small));
            this.mGoogleMap.addMarker(mCurrentMarker);
    
        }
    
    }
    

    map_fragment.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=".MapActivity" >
    
        <fragment xmlns:map="http://schemas.android.com/apk/res-auto"
            android:id="@+id/map"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical"
            class="com.google.android.gms.maps.SupportMapFragment"/>
    
    </RelativeLayout>
    

    错误:

     android.view.InflateException: Binary XML file line #7: Error inflating class fragment
                at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:763)
                at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
                at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
                at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
                at the.vizimir.moment.fragments.MapFragment.onCreateView(MapFragment.java:38)
                at android.support.v4.app.Fragment.performCreateView(Fragment.java:1789)
                at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:955)
                at android.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1314)
                at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:730)
                at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)
                at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:490)
                at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
                at android.support.v4.view.ViewPager.populate(ViewPager.java:1105)
                at android.support.v4.view.ViewPager.populate(ViewPager.java:951)
                at android.support.v4.view.ViewPager$3.run(ViewPager.java:250)
                at android.view.Choreographer$CallbackRecord.run(Choreographer.java:792)
                at android.view.Choreographer.doCallbacks(Choreographer.java:596)
                at android.view.Choreographer.doFrame(Choreographer.java:556)
                at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:778)
                at android.os.Handler.handleCallback(Handler.java:739)
                at android.os.Handler.dispatchMessage(Handler.java:95)
                at android.os.Looper.loop(Looper.java:155)
                at android.app.ActivityThread.main(ActivityThread.java:5696)
                at java.lang.reflect.Method.invoke(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:372)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
         Caused by: java.lang.IllegalArgumentException: Binary XML file line #7: Duplicate id 0x7f0d008a, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.SupportMapFragment
                at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2175)
                at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
                at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:177)
                at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:725)
                at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
                at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
                at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
                at the.vizimir.moment.fragments.MapFragment.onCreateView(MapFragment.java:38)
                at android.support.v4.app.Fragment.performCreateView(Fragment.java:1789)
                at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:955)
                at android.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1314)
                at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:730)
                at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)
                at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:490)
                at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
                at android.support.v4.view.ViewPager.populate(ViewPager.java:1105)
                at android.support.v4.view.ViewPager.populate(ViewPager.java:951)
                at android.support.v4.view.ViewPager$3.run(ViewPager.java:250)
                at android.view.Choreographer$CallbackRecord.run(Choreographer.java:792)
                at android.view.Choreographer.doCallbacks(Choreographer.java:596)
                at android.view.Choreographer.doFrame(Choreographer.java:556)
                at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:778)
                at android.os.Handler.handleCallback(Handler.java:739)
                at android.os.Handler.dispatchMessage(Handler.java:95)
                at android.os.Looper.loop(Looper.java:155)
                at android.app.ActivityThread.main(ActivityThread.java:5696)
                at java.lang.reflect.Method.invoke(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:372)
    

1 个答案:

答案 0 :(得分:1)

您应该使用MapView而不是SupportMapFragment。 it`s a good example from google