作为一个新手,我试图在滑动标签中使用图标代替文本视图。问题是,当我更改选项卡时,我的片段之一(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