TabLayout 获取Tab的宽度_解决点击Tab从头滑动问题

该博客主要介绍如何解决TabLayout在点击Tab时,导致的从头开始滑动的问题。作者通过设置布局参数、监听滚动变化以及反射调用TabLayout的方法来实现修复。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.tablayout;

import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import static android.support.v4.view.ViewPager.SCROLL_STATE_DRAGGING;
import static android.support.v4.view.ViewPager.SCROLL_STATE_IDLE;
import static android.support.v4.view.ViewPager.SCROLL_STATE_SETTLING;
/**
 * 计算不准确
 * tab点击滑动,重新滑动问题
 * 线问题
 */
public class MainActivity extends AppCompatActivity{
    TabLayout tabLayout;
    ViewPager viewPager;
    View lineSeprator;
    String[] tabTitles = new String[]{"Actions", "Living-room", "Actions", "Living-room", "Actions", "Actions", "Living-room", "Actions", "Living-room", "Actions"};
    Method tabLayoutSetScrollPosition;
    Method tabLayoutSelectTab;
    boolean clickSelectable = false;
    boolean scrollSelectable = false;

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

        tabLayout = (TabLayout) findViewById(R.id.tabLayout);
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        lineSeprator = findViewById(R.id.line_seprator);

        ViewGroup.LayoutParams params = lineSeprator.getLayoutParams();
        params.width = this.getResources().getDisplayMetrics().widthPixels / tabTitles.length;
        lineSeprator.setLayoutParams(params);

        viewPager.setAdapter(new TextFragAdapter(this.getSupportFragmentManager()));
        tabLayout.setupWithViewPager(viewPager);

        try {
            tabLayoutSetScrollPosition = tabLayout.getClass().getDeclaredMethod("setScrollPosition", int.class, float.class, boolean.class, boolean.class);
            tabLayoutSelectTab = tabLayout.getClass().getDeclaredMethod("selectTab", TabLayout.Tab.class, boolean.class);
            tabLayoutSetScrollPosition.setAccessible(true);
            tabLayoutSelectTab.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }


        for (int i = 0; i < tabTitles.length; i++) {
            tabLayout.getTabAt(i).setCustomView(getCustomView(tabTitles[i], i));
        }

        tabLayout.setOnScrollChangeListener(new View.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                FV.log("scrollX:" + scrollX);
            }
        });

        tabLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {

                int tabCount = tabLayout.getTabCount();
                for (int i = 0; i < tabCount; i++) {
                    View customView = tabLayout.getTabAt(i).getCustomView();
                    try {
                        TabLayout.Tab tabGet = tabLayout.getTabAt(i);
                        Field field = tabGet.getClass().getDeclaredField("mView");
                        field.setAccessible(true);
                        LinearLayout obj = (LinearLayout) field.get(tabGet);
                        FV.log("obj:" + obj.getMeasuredWidth());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) customView.getLayoutParams();
                    FV.log(tabTitles[i] + ",width:" + customView.getMeasuredWidth() + ",leftMargin:" + params.leftMargin + ",rightMargin:" + params.rightMargin);
                }
            }
        });

        viewPager.clearOnPageChangeListeners();
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            private final WeakReference<TabLayout> mTabLayoutRef = new WeakReference<>(tabLayout);
            private int mPreviousScrollState;
            private int mScrollState;

            @Override
            public void onPageScrollStateChanged(final int state) {
                mPreviousScrollState = mScrollState;
                mScrollState = state;
            }

            @Override
            public void onPageScrolled(final int position, final float positionOffset,
                                       final int positionOffsetPixels) {
                FV.log("onPageScrolled11111111:" + position + ",clickable:" + clickSelectable + ",positionOffset:" + positionOffset);
                setLineParams(position, positionOffset);
                if (clickSelectable)
                    scrollSelectable = false;
                else
                    scrollSelectable = true;

                FV.log("onPageScrolled:" + position + ",clickable:" + clickSelectable);
                final TabLayout tabLayout = mTabLayoutRef.get();
                if (tabLayout != null) {
                    // Only update the text selection if we're not settling, or we are settling after
                    // being dragged
                    final boolean updateText = mScrollState != SCROLL_STATE_SETTLING ||
                            mPreviousScrollState == SCROLL_STATE_DRAGGING;
                    // Update the indicator if we're not settling after being idle. This is caused
                    // from a setCurrentItem() call and will be handled by an animation from
                    // onPageSelected() instead.
                    final boolean updateIndicator = !(mScrollState == SCROLL_STATE_SETTLING
                            && mPreviousScrollState == SCROLL_STATE_IDLE);
//                    tabLayout.setScrollPosition(position, positionOffset, updateText, updateIndicator);
                    try {
                        if (!clickSelectable)
                            tabLayoutSetScrollPosition.invoke(tabLayout, position, positionOffset, updateText, updateIndicator);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                if (positionOffset == 0) {
                    clickSelectable = false;
                    scrollSelectable = false;
                }
            }

            @Override
            public void onPageSelected(final int position) {
                FV.log("onPageSelected:" + position);
                if (!scrollSelectable)
                    clickSelectable = true;
                final TabLayout tabLayout = mTabLayoutRef.get();
                if (tabLayout != null && tabLayout.getSelectedTabPosition() != position
                        && position < tabLayout.getTabCount()) {
                    // Select the tab, only updating the indicator if we're not being dragged/settled
                    // (since onPageScrolled will handle that).
                    final boolean updateIndicator = mScrollState == SCROLL_STATE_IDLE
                            || (mScrollState == SCROLL_STATE_SETTLING
                            && mPreviousScrollState == SCROLL_STATE_IDLE);
                    try {
                        tabLayoutSelectTab.invoke(tabLayout, tabLayout.getTabAt(position), updateIndicator);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    public View getCustomView(String title, int position) {
        View mView = LayoutInflater.from(this).inflate(R.layout.tab_title_item_layout, null);
        ((TextView) mView.findViewById(R.id.title)).setText(title);
        return mView;
    }

    private void setLineParams(int position, float positionOffset) {
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) lineSeprator.getLayoutParams();
        params.leftMargin = (int) (params.width * (position + positionOffset));
        lineSeprator.setLayoutParams(params);
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值