SmartTabLayout 自定义选项卡视图膨胀

SmartTabLayout custom tab view inflate

想法是,使用 SmartTabLabyout 库 (https://github.com/ogaclejapan/SmartTabLayout),为每个选项卡扩展自定义视图。由于某种原因,它不想工作。基础代码如下:

Activity:

public class MainActivity extends AppCompatActivity {

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

        ViewPager mViewPager = (ViewPager) findViewById(R.id.pager);
        SmartTabLayout viewPagerTab = (SmartTabLayout) findViewById(R.id.viewpagertab);

        MainActivityViewPagerAdapter mPagerAdapter = new MainActivityViewPagerAdapter(getSupportFragmentManager(), this);
        viewPagerTab.setCustomTabView(mPagerAdapter);

        mViewPager.setAdapter(mPagerAdapter);
        viewPagerTab.setViewPager(mViewPager);
    }
}

适配器:

public class MainActivityViewPagerAdapter extends FragmentPagerAdapter implements SmartTabLayout.TabProvider {

    public enum MainActivityPages {
        TAB_1(0, "Tab #1", R.drawable.tab_icon_1, TabFragment1.newInstance()),
        TAB_2(1, "Tab #2", R.drawable.tab_icon_2, TabFragment2.newInstance()),
        TAB_3(2, "Tab #3", R.drawable.tab_icon_3, TabFragment3.newInstance());

        public int index;
        public String title;
        public int resourceId;
        public Fragment fragment;

        MainActivityPages(int index, String title, int resourceId, Fragment fragment) {
            this.index = index;
            this.title = title;
            this.resourceId = resourceId;
            this.fragment = fragment;
        }
    }

    public MainActivityViewPagerAdapter(FragmentManager fm, Context context) {
        super(fm);
        this.context = context;
    }

    @Override
    public Fragment getItem(int position) {
        return MainActivityPages.values()[position].fragment;
    }

    @Override
    public int getCount() {
        return MainActivityPages.values().length;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return MainActivityPages.values()[position].title;
    }

    @Override
    public View createTabView(ViewGroup container, int position, PagerAdapter adapter) {
        View v = LayoutInflater.from(this.context).inflate(R.layout.activity_main_tab, null);

        if(v != null) {
            ImageView icon = (ImageView) v.findViewById(R.id.activity_main_tab_icon);
            icon.setImageResource(MainActivityPages.values()[position].resourceId);
        }

        return v;
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF">

    <com.ogaclejapan.smarttablayout.SmartTabLayout
        android:id="@+id/viewpagertab"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        app:stl_indicatorAlwaysInCenter="false"
        app:stl_indicatorWithoutPadding="false"
        app:stl_indicatorInFront="false"
        app:stl_indicatorInterpolation="smart"
        app:stl_indicatorGravity="bottom"
        app:stl_indicatorColor="#40C4FF"
        app:stl_indicatorThickness="4dp"
        app:stl_indicatorWidth="auto"
        app:stl_indicatorCornerRadius="2dp"
        app:stl_overlineColor="#4D000000"
        app:stl_overlineThickness="0dp"
        app:stl_underlineColor="#FFFFFF"
        app:stl_underlineThickness="0dp"
        app:stl_dividerColor="#FFFFFF"
        app:stl_dividerThickness="0dp"
        app:stl_defaultTabBackground="?attr/selectableItemBackground"
        app:stl_defaultTabTextAllCaps="true"
        app:stl_defaultTabTextColor="#FC000000"
        app:stl_defaultTabTextSize="12sp"
        app:stl_defaultTabTextHorizontalPadding="16dp"
        app:stl_defaultTabTextMinWidth="0dp"
        app:stl_distributeEvenly="true"
        app:stl_clickable="true"
        app:stl_titleOffset="24dp"
        app:stl_drawDecorationAfterTab="false" />

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:context=".MainActivity" />

</LinearLayout>

activity_main_tab.xml:

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main_tab_icon"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

上面的代码产生了这个

java.lang.RuntimeException: Unable to start activity ComponentInfo{.activities.MainActivity}: java.lang.NullPointerException
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
   at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3724)
   at android.app.ActivityThread.access0(ActivityThread.java:135)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1202)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:136)
   at android.app.ActivityThread.main(ActivityThread.java:5001)
   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:785)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
   at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
   at com.ogaclejapan.smarttablayout.SmartTabLayout.populateTabStrip(SmartTabLayout.java:398)
   at com.ogaclejapan.smarttablayout.SmartTabLayout.setViewPager(SmartTabLayout.java:327)
   at com.insertcoin.apps.vindr.activities.MainActivity$override.onCreate(MainActivity.java:63)
   at com.insertcoin.apps.vindr.activities.MainActivity$override.access$dispatch(MainActivity.java)
   at com.insertcoin.apps.vindr.activities.MainActivity.onCreate(MainActivity.java:0)
   at android.app.Activity.performCreate(Activity.java:5231)
   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233) 
   at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3724) 
   at android.app.ActivityThread.access0(ActivityThread.java:135) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1202) 
   at android.os.Handler.dispatchMessage(Handler.java:102) 
   at android.os.Looper.loop(Looper.java:136) 
   at android.app.ActivityThread.main(ActivityThread.java:5001) 
   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:785) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 
   at dalvik.system.NativeStart.main(Native Method)

我错过了什么?

好的,明白了...

SmartTabLayout.class 在设置宽度和高度时,在膨胀视图上调用 getLayoutParams() 后抱怨空值 LinearLayout.LayoutParams。

所以要解决这个问题,膨胀的内容必须用LinearLayout包裹起来。 activity_main_tab.xml 看起来像:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/activity_main_tab_icon"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

然而,还不够…… 在 createTabView 中膨胀视图后,需要以下行:

v.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

感谢您的宝贵时间