26

tablayout を使用して 30 個のスクロール可能なタブを作成しました。

したがって、最初の 3 つのタブは画面に表示され、残りのタブは表示されず、スワイプ ジェスチャを使用してスクロールできます。

問題は、プログラムで最後のタブを選択しているときに表示されない場合です (タブ レイアウトが最後のタブにスクロールされません)。

最後のタブにスクロールするようにタブレイアウトを作成するにはどうすればよいですか?

4

13 に答える 13

61

解決策を見つけました。

最初に、タブレイアウトの幅を見つけて、その x 位置を幅にスクロールし、最後のタブの select() メソッドを呼び出しました。

そして、それはうまくいきます。

以下はコードです。

mTabLayout.setScrollX(mTabLayout.getWidth());
mTabLayout.getTabAt(lastTabIndex).select();

更新日:

上記が機能しない場合は、以下のコードも使用できます。これも正常に機能しています。

new Handler().postDelayed(
        new Runnable() {
            @Override public void run() {
                mTabLayout.getTabAt(TAB_NUMBER).select();
            }
        }, 100);
于 2015-07-16T11:22:16.267 に答える
7

このメソッドをカスタム tablayout (tablayout を拡張する独自のレイアウト) に記述します。したがって、将来的には、コードの複製の代わりに必要なときにいつでもこの方法を使用できます

public void selectTabAt(int tabIndex) {
        if (tabIndex >= 0 && tabIndex < getTabCount() && getSelectedTabPosition() != tabIndex) {
            final Tab currentTab = getTabAt(tabIndex);
            if (currentTab != null) {
                this.post(new Runnable() {
                    @Override
                    public void run() {
                        currentTab.select();
                    }
                });
            }
        }
    }

CustomLayout を使用したくない場合。あなたはこれを行うことができます

final Tab currentTab = mTabLayout.getTabAt(tabIndex);
if(currentTab != null){
     mTabLayout.post(new Runnable() {
                    @Override
                    public void run() {
                        currentTab.select();
                    }
                });
}
于 2016-05-09T10:02:12.950 に答える
6

私はこの解決策を見つけました:

    TabLayout tabLayout = activity.getTabLayout();
    tabLayout.setSmoothScrollingEnabled(true);
    tabLayout.setScrollPosition(targetChannelPosition, 0f, true);

また、「ビュー階層を作成した元のスレッドのみがそのビューにアクセスできます。」というエラーが表示された場合は、Ui スレッドで実行するために次のコードを使用できます。

    // find a way to get the activity containing the tab layout
    TabLayout tabLayout = activity.getTabLayout();
    activity.runOnUiThread(new Runnable()
    {
        @Override
        public void run()
        {
            TabLayout.Tab tab = tabLayout.getTabAt(targetChannelPosition);
            tab.select();
        }
    });
于 2016-02-17T12:09:04.027 に答える
5

tab.select()TabLayout とその子が実際に測定および描画される前に呼び出していますか? その場合、TabLayout はtab.select()(または Kayvan N の提案によるscrollTo()) で選択範囲にアニメーション化されません。ハンドラーを使用するとおそらくうまくいくでしょうが、それは理想的な解決策ではありません。

レイアウトがまだレイアウトされていない場合はViewTreeObserver、レイアウト プロセスが終了した後で、選択したタブに移動できます。

private void scrollToTabAfterLayout(final int tabIndex) {
    if (getView() != null) {
        final ViewTreeObserver observer = mTabLayout.getViewTreeObserver();

        if (observer.isAlive()) {
            observer.dispatchOnGlobalLayout(); // In case a previous call is waiting when this call is made
            observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                        observer.removeOnGlobalLayoutListener(this);
                    } else {
                        //noinspection deprecation
                        observer.removeGlobalOnLayoutListener(this);
                    }

                    mTabLayout.getTabAt(tabIndex).select();

                }
            });
        }
    }
}

何か提案があればコメントしてください。

于 2016-01-14T02:16:43.407 に答える
3

上記の答えは機能しません。最初に agirardello が述べmTabLayout.getWidth()たように、必要なもの (スクロール先の子の位置) が返されないため、使用しないでください。また、更新されたソリューションは常に機能するとは限りません。 TabLayout のバグ (ここで報告) ですが、回避策は簡単です。

tabLayout のタブは TabLayout の直接の子ではないため、次を使用して 1 レベル深くする必要があります。

((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(YOUR_DESIRED_TAB_INDEX).getRight()

tabLayout の唯一の子は であり、TabLayout.SlidingTabStripこれも でありViewGroupgetRight()目的のタブ ビューの最も右の位置を提供します。したがって、その位置までスクロールすると、必要なものが得られます。完全なコードは次のとおりです。

int right = ((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(4).getRight();
mTabLayout.scrollTo(right,0);
mTabLayout.getTabAt(4).select();

注: レイアウトが取り消された後にこれらのメソッドを呼び出していることを確認してください (onResume ではなく onCreate など)。

お役に立てれば。

于 2015-09-21T21:09:32.817 に答える
2

以下のコードスニペットは私にとってはうまくいきます

class TriggerOnceListener(private val v: View, private val block: () -> Unit) : ViewTreeObserver.OnPreDrawListener {
    override fun onPreDraw(): Boolean {
        block()
        v.viewTreeObserver.removeOnPreDrawListener(this)
        return true
    }
}

fun onCreate() {
    val position = ***The tab position you want to scroll to, 29 for your case here***
    tabLayout.let { it.viewTreeObserver.addOnPreDrawListener(TriggerOnceListener(it)
    { it.setScrollPosition(position, 0f, true) } ) }
}

私は Tab.select() に飛び込み、Android が Tablayout.setScrollPosition() を使用してこのスクロールを行うことを発見しました。また、onCreate() ではウィジェットが測定されていないため、レイアウトが完了するまで呼び出しを延期する必要があります。

于 2019-02-28T11:46:00.477 に答える
1

最後のタブを選択するには、tabLayout.getTabAt(X).select(); を使用します。ここで、X は最後のタブ インデックスです

于 2015-07-16T08:15:31.737 に答える
0

viewpager.setItem(position)タブの位置も設定する必要があります

于 2016-05-09T10:53:54.520 に答える
0

非常に遅れて来るので、これは答えが関連するかどうか疑問に思います。私は実際にXamarinを使用してC#でそれを達成しました。

tabs.GetChildAt(0).Selected = true;
 viewPager.SetCurrentItem(0, true);
于 2017-01-03T22:52:37.160 に答える
0

このソリューションは私にとってはうまくいきました。ただし、私の状況は少し異なります。私の場合、ViewPager で TabLayout を使用し、さらにビューを追加して、notifyDataSetChange() を呼び出しています。

解決策は、TabLayout のオブザーバーにコールバックを設定し、子が実際に TabLayout に追加されたときにスクロールすることです。これが私の例です:

/**
    Keep in mind this is how I set my TabLayout up...

    PagerAdapter pagerAdapter = new PagerAdapter(...);
    ViewPager pager = (ViewPager)findViewById(...);
    pager.setAdapter(pagerAdapter);

    TabLayout tabLayout = (TabLayout)findViewById(...);
    tabLayout.setupWithViewPager(pager);
*/
public void loadTabs(String[] topics) {
    animateTabsOpen(); // Irrelevant to solution

    // Removes fragments from ViewPager
    pagerAdapter.clear();

    // Adds new fragments to ViewPager
    for (String t : topics)
         pagerAdapter.append(t, new TestFragment());

    // Since we need observer callback to still animate tabs when we
    // scroll, it is essential to keep track of the state. Declare this
    // as a global variable
    scrollToFirst = true;

    // Alerts ViewPager data has been changed
    pagerAdapter.notifyOnDataSetChanged();

    // Scroll to the beginning (or any position you need) in TabLayout
    // using its observer callbacks
    tabs.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            /**
                 We use onGlobalLayout() callback because anytime a tab
                 is added or removed the TabLayout triggers this; therefore,
                 we use it to scroll to the desired position we want. In my
                 case I wanted to scroll to the beginning position, but this
                 can easily be modified to scroll to any position.
             */
            if (scrollToFirst) {
                tabs.getTabAt(0).select();
                tabs.scrollTo(0, 0);
                scrollToFirst = false;
            }
        }
    });
}

あなたもそれが必要な場合は、これがPagerAdapterの私のコードです笑:

public class PagerAdapter extends FragmentStatePagerAdapter {
    private List<Fragment> fragments;
    private List<String> titles;


    public PagerAdapter(FragmentManager fm) {
        super(fm);
        this.fragments = new ArrayList<>();
        this.titles = new ArrayList<>();
    }

    /**
     * Adds an adapter item (title and fragment) and
     * doesn't notify that data has changed.
     *
     * NOTE: Remember to call notifyDataSetChanged()!
     * @param title Fragment title
     * @param frag Fragment
     * @return This
     */
    public PagerAdapter append(String title, Fragment frag) {
        this.titles.add(title);
        this.fragments.add(frag);
        return this;
    }

    /**
     * Clears all adapter items and doesn't notify that data
     * has changed.
     *
     * NOTE: Rememeber to call notifyDataSetChanged()!
     * @return This
     */
    public PagerAdapter clear() {
        this.titles.clear();
        this.fragments.clear();
        return this;
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }

    @Override
    public int getItemPosition(Object object) {
        int position = fragments.indexOf(object);
        return (position >= 0) ? position : POSITION_NONE;
    }
}
于 2016-06-03T20:17:31.393 に答える