如何在Android滑动选项卡布局中将活动标签居中对齐

8
我在安卓滑动标签布局和视图分页器中有12个项目。在从左至右滑动时,选定的标签应该像Play商店一样位于中心。请帮忙解决如何实现。在我的应用中,活动标签始终在屏幕左侧。
图片链接略。

你的项目中是否使用了 PagerTabStrip(这是 Google Play 应用正在使用的)。看起来你正在使用普通标签替代。 - Marko
不,我使用了由Google提供的SlidingTabLayout类作为滑动选项卡布局的示例类。我还尝试过PagerTabStrip,但它不允许您像Play Store一样滑动选项卡标题。SlidingTabLayout是扩展的HorizontalScrollView。 - Shripad Bhat
我明白了。从Android开发者的这个视频中可以看出,这不是预期的行为。为了获得Google Play的效果,您必须使用PagerTabStrip。它非常容易实现,请查看这个教程 - Marko
谢谢Mark。我已经解决了这个问题,以下是我的答案。 - Shripad Bhat
SmartTabLayout非常好地完成了这个任务。 - M. Reza Nasirloo
3个回答

13

我的方法与Shripad Bhat的解决方案略有不同,他在幻灯片末尾弹跳标签。

这是我的解决方法...

onPageScrolled方法的更改:

@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 selectedOffset = (selectedTitle == null) ? 0 : selectedTitle.getWidth();
    int nextTitlePosition = position + 1;
    View nextTitle = mTabStrip.getChildAt(nextTitlePosition);
    int nextOffset = (nextTitle == null) ? 0 : nextTitle.getWidth();
    int extraOffset = (int)(0.5F * (positionOffset * (float)(selectedOffset + nextOffset)));
    scrollToTab(position, extraOffset);

    if (mViewPagerPageChangeListener != null) {
        mViewPagerPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
    }
}

scrollToTab 方法的更改:

private int mLastScrollTo;

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 && selectedChild.getMeasuredWidth() != 0) {

        int targetScrollX = ((positionOffset + selectedChild.getLeft()) - getWidth() / 2) + selectedChild.getWidth() / 2;

        if (targetScrollX != mLastScrollTo) {
            scrollTo(targetScrollX, 0);
            mLastScrollTo = targetScrollX;
        }
    }
}

3
谢谢你,真的很棒。但是如何将第一个选项卡置于中心位置? - NickUnuchek
我找不到 onPageScrolled,我正在使用带有设计库的 FragmentStatePagerAdapterTabLayout - Lavekush Agrawal
你好@NickUnuchek,你成功把第一个选项卡放在中间了吗?请帮忙。 - Harry Sharma

3

谷歌提供了滑动选项卡布局的示例。但在实现SlidingTabLayout类时,它并没有设计使选定的选项卡居中对齐。我已经修改了滚动方法,使选定/活动选项卡位于屏幕中央。以下是代码更改:

类名:SlidingTabLayout

行号:241, scrollToTab{}

更新后的方法:

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 -= (getWidth()-selectedChild.getWidth())/2;
        }

        scrollTo(targetScrollX, 0);
    }
}

1
你不需要获取显示器来测量scrollview的宽度,只需调用getWidth() ;) 即:targetScrollX -= (getWidth()-selectedChild.getWidth())/2; - Yuri Heupa
Yuri Heupa,已更新答案。感谢您的建议。 - Shripad Bhat
+1 它可以工作 :) 但是在努力将其放置在中心时,末尾会有轻微的抖动。以下修复它。:) 不过做得很好。 - Atul O Holic

2

我也遇到了这个问题。tabLayout只提供了tabContentStart选项,但需要两边都有:

public class CenteringTabLayout extends TabLayout {
public CenteringTabLayout(Context context) {
    super(context);
}

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

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

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    View firstTab = ((ViewGroup)getChildAt(0)).getChildAt(0);
    View lastTab = ((ViewGroup)getChildAt(0)).getChildAt(((ViewGroup)getChildAt(0)).getChildCount()-1);
    ViewCompat.setPaddingRelative(getChildAt(0), (getWidth()/2) - (firstTab.getWidth()/2),0,(getWidth()/2) - (lastTab.getWidth()/2),0);
}
}

你的代码在使用ViewCompat的行上抛出了异常,能否请你解释一下你的代码,以便我能够理解你真正想要做什么。 - eyadMhanna
1
我扩展了android.support.design.widget.TabLayout。第一个子元素是SlidingTabStrip,每个选项卡都是它的子元素,我正在尝试为这个SlidingTabStrip设置填充。 但即使我的代码也无法正确地将最后几个选项卡居中。我仍然没有找到原因。 - Lubos Horacek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接