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


我认为问题出在SlidingTabLayout中,我们将提供所有帮助和反馈。


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)

最佳答案

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

07-24 09:27