Android之解決TabLayout裏面每個Tab項的間距和修改指示線的長度(非反射)和修改選中字體大小

1 問題

1)由於TabLayout設置了可滑動Tab參數

app:tabMode="scrollable"

導致每個Tab之間的間距很大,但是UI設計圖裏面的字體之間的間距很小,我們改怎麼解決?

2)修改TabLayout指示線的長度(非反射)

3)修改選中的字體大小並且加粗

 

 

 

 

 

 

 

 

2 解決辦法

問題1解決辦法:

對TabLayout進行自定義,然後反射下面字段進行修改

scrollableTabMinWidth


import android.content.Context;
import android.util.AttributeSet;

import com.appsinnova.android.keepdrop.R;
import com.google.android.material.tabs.TabLayout;

import java.lang.reflect.Field;

public class MyTabLayout extends TabLayout {
    // 一屏顯示多少個tab
    private static final int TabViewNumber = 8;
    // support 低版本可能不一樣
    private static final String SCROLLABLE_TAB_MIN_WIDTH = "scrollableTabMinWidth";

    public MyTabLayout(Context context) {
        super(context);
        initTabMinWidth();
    }

    public MyTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        initTabMinWidth();
    }

    public MyTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initTabMinWidth();
    }

    private void initTabMinWidth() {
//        int screenWidth = getResources().getDisplayMetrics().widthPixels;
//        int tabMinWidth = screenWidth / TabViewNumber;
        // scrollable模式時,tab的最小寬度
        int tabMinWidth = (int) getResources().getDimension(R.dimen.value_25_dp);

        Field field;
        try {
            field = TabLayout.class.getDeclaredField(SCROLLABLE_TAB_MIN_WIDTH);
            field.setAccessible(true);
            field.set(this, tabMinWidth);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

 

 

問題2解決辦法:

網上很多反射,感覺不靠譜,提供簡單粗暴的方法

在drawable下面創建一個xml文件layer_tab_indicator.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:width="15dp"
        android:gravity="center">
        <shape>
            <corners android:radius="90dp" />
            <size android:height="4dp" />
            <solid android:color="#ff0000" />
        </shape>
    </item>
</layer-list>

然後放到MyTabLayout裏面去

                <**********************.MyTabLayout
                    android:layout_marginStart="@dimen/value_10_dp"
                    android:id="@+id/vedioTabLayout"
                    android:layout_weight="1"
                    android:layout_width="match_parent"
                    app:tabRippleColor = "@android:color/transparent"
                    app:elevation="0dp"
                    android:layout_height="match_parent"
                    app:tabGravity="fill"
                    app:tabIndicatorHeight="4dp"
                    app:tabIndicator="@drawable/layer_tab_indicator"
                    app:tabIndicatorColor="@color/rocket_backgroud"
                    app:tabMode="scrollable"
                    app:tabSelectedTextColor="@color/rocket_backgroud"
                    app:tabTextColor="@color/t9" />

 

 

 

 

問題3解決辦法:

自定義選項卡內容

關鍵代碼如下

tab_vedio_item_view.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="@dimen/sp18" />
</LinearLayout>
    var viewPager: ViewPager? = null
    var tabLayout: TabLayout? = null
    var isShow = false
    var fragmentSize = 0
    var vedioTitleTabs = ArrayList<String>()
    //切換
    var fragment: Fragment? = null
    constructor() {}

    var gameView: View? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        gameView = LayoutInflater.from(getContext()).inflate(R.layout.fragment_recommend_vedio, null)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        vedioTitleTabs = getTitleTabs()
        fragmentSize = vedioTitleTabs.size
        LogUtil.i(TAG,"vedioTitleTabs is: ${vedioTitleTabs}")
        LogUtil.i(TAG,"fragmentSize is: ${fragmentSize}")

        viewPager = gameView?.findViewById(R.id.viewpagerContentView) as ViewPager
        tabLayout = gameView?.findViewById(R.id.vedioTabLayout) as TabLayout
        viewPager?.adapter = MyAdapter(fragmentManager)
        //將TabLayout與ViewPager綁定
        tabLayout!!.setupWithViewPager(viewPager)

        for (i in vedioTitleTabs.indices) {
            tabLayout?.getTabAt(i)?.setCustomView(getTabView(vedioTitleTabs[i]))
        }
        if (fragmentSize > 0) {
            changeTabSelect(tabLayout?.getTabAt(0)!!)
        }
        tabLayoutListener()
        return gameView
    }

    fun getTitleTabs():ArrayList<String> {
        var recommendVedioModel = SPHelper.getInstance().getObject(SpConstants.RECOMMEND_VEDIO_CATETGORY, RecommendVedioModel().javaClass)
        LogUtil.i(TAG,"recommendVedioModel爲${recommendVedioModel?.items?.toString()}")
        var titleTabs = ArrayList<String>()
        if (recommendVedioModel == null || recommendVedioModel.items == null || recommendVedioModel.items.size == 0) {
            return titleTabs
        }
        recommendVedioModel.items.forEach {
            titleTabs.add(it.name)
        }
        return titleTabs;
    }

    private fun tabLayoutListener() { //TabLayout切換時導航欄圖片處理
        tabLayout!!.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            override fun onTabSelected(tab: TabLayout.Tab) { //選中圖片操作
                Log.i(TAG, "onTabSelected start")
                changeTabSelect(tab)
            }

            override fun onTabUnselected(tab: TabLayout.Tab) { //未選中圖片操作
                Log.i(TAG, "onTabUnselected start");
                changeTabNormal(tab)
            }

            override fun onTabReselected(tab: TabLayout.Tab) {
                Log.i(TAG, "onTabReselected start")
            }
        })
    }

    // Tab自定義view
    fun getTabView(title: String?): View? {
        val v: View =
            LayoutInflater.from(activity).inflate(R.layout.tab_vedio_item_view, null)
        val textView: TextView = v.findViewById<View>(R.id.textview) as TextView
        textView.setText(title)
        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP,18f);
        return v
    }

    private fun changeTabSelect(tab: TabLayout.Tab) {
        val view = tab.customView
        (view?.findViewById<View>(R.id.textview))?.let {
            val txt_title = it as TextView
            txt_title.setTextSize(TypedValue.COMPLEX_UNIT_SP,20f);
            txt_title?.paint.isFakeBoldText = true
        }
    }

    private fun changeTabNormal(tab: TabLayout.Tab) {
        val view = tab.customView
        (view?.findViewById<View>(R.id.textview))?.let {
            val txt_title = it as TextView
            txt_title.setTextSize(TypedValue.COMPLEX_UNIT_SP,18f);
            txt_title?.paint.isFakeBoldText = false
        }
    }

    inner class MyAdapter(fm: FragmentManager?) : FragmentPagerAdapter(fm!!) {
        override fun getCount(): Int {
            return fragmentSize
        }
        override fun getItem(position: Int): Fragment {
            Log.i(TAG, "getItem position is:" + position)
            return GameFragment()
        }
        override fun getPageTitle(position: Int): CharSequence? {
            Log.i(TAG, "getPageTitle position is:" + position)
            return ""
        }
    }

 

 

 

 

 

3 效果如下

滑動起來刷刷的

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章