web-dev-qa-db-de.com

Wie programmiere ich Tablayout - Android

Ich habe mit Tabayout 30 scrollbare Registerkarten erstellt.

Die ersten drei Registerkarten sind daher auf dem Bildschirm sichtbar und die restlichen Registerkarten sind unsichtbar. Sie können mit der Wischgeste gescrollt werden.

Das Problem ist, wenn ich die letzte Registerkarte programmgesteuert auswähle, diese aber nicht sichtbar wird (das Layout der Registerkarten wird nicht auf die letzte Registerkarte verschoben).

Wie kann ich Tablayout zum letzten Tab bewegen lassen?

17
Mohit Charadva

Ich habe die Lösung gefunden.

Zuerst hatte ich die Breite des Tablayouts gefunden und es wurde die x-Position zur Breite gescrollt und dann die select () -Methode der letzten Registerkarte genannt.

Und es funktioniert gut.

Unten ist der Code.

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

Aktualisierte :

Wenn oben nicht funktioniert, können Sie auch den unten stehenden Code verwenden, es funktioniert auch einwandfrei.

new Handler().postDelayed(
        new Runnable() {
            @Override public void run() {
                mTabLayout.getTabAt(TAB_NUMBER).select();
            }
        }, 100);
37
Mohit Charadva

Ich habe diese Lösung für mich gefunden:

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

Wenn Sie diesen Fehler erhalten: "Nur der ursprüngliche Thread, der eine Ansichtshierarchie erstellt hat, kann seine Ansichten berühren."

    // 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();
        }
    });
5
sunlover3

schreiben Sie diese Methode in Ihr benutzerdefiniertes Tablayout (Ihr eigenes Layout, das Tablayout erweitert). Daher können Sie diese Methode in Zukunft immer dann verwenden, wenn Sie Code-Duplizierungen benötigen

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();
                    }
                });
            }
        }
    }

Wenn Sie nicht möchten, verwenden Sie CustomLayout. Sie können das einfach tun

final Tab currentTab = mTabLayout.getTabAt(tabIndex);
if(currentTab != null){
     mTabLayout.post(new Runnable() {
                    @Override
                    public void run() {
                        currentTab.select();
                    }
                });
}
3
Ashok Varma

Die obige Antwort würde nicht funktionieren, da Sie, wie bereits erwähnt, nicht mTabLayout.getWidth() verwenden sollten, da sie nicht das zurückgibt, was wir benötigen (was die Position des Kindes ist, zu dem Sie scrollen möchten) und die aktualisierte Lösung nicht immer funktioniert eines Fehlers in TabLayout (gemeldet hier ), aber eine Problemumgehung ist einfach.

Die Registerkarten im tabLayout sind keine direkten untergeordneten Elemente des TabLayouts, daher müssen wir eine Ebene tiefer gehen 

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

das einzige untergeordnete Element von tabLayout ist ein TabLayout.SlidingTabStrip, der auch eine ViewGroup ist, und getRight() gibt uns die rechte Position der gewünschten Tabulatoransicht. Das Scrollen zu dieser Position gibt uns das, was wir wünschen. Hier ist ein vollständiger Code:

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

HINWEIS: Stellen Sie sicher, dass Sie diese Methoden aufrufen, nachdem das Layout ertrunken ist (wie onResume und nicht onCreate).

Hoffe das hilft.

2
Kayvan N

Um die letzte Registerkarte auszuwählen, verwenden Sie TabLayout.getTabAt (X) .select (); Dabei ist X der letzte Tabulatorindex

1
jomartigcal
new Handler().postDelayed(
    new Runnable() {
        @Override public void run() {
            mTabLayout.getTabAt(TAB_NUMBER).select();
        }
    }, 100);
1
Hai Rom

Rufen Sie tab.select() auf, bevor das TabLayout und seine untergeordneten Elemente tatsächlich gemessen und gezeichnet wurden? Wenn ja, wird Ihr TabLayout nicht mit tab.select() (oder Kayvan Ns Vorschlag von scrollTo()) zur Auswahl animiert. Die Verwendung eines Handlers wird wahrscheinlich funktionieren, aber das ist keine ideale Lösung.

Wenn das Layout noch nicht angelegt wurde, können Sie mit einer ViewTreeObserver zum ausgewählten Tab wechseln, nachdem der Layoutprozess abgeschlossen ist.

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();

                }
            });
        }
    }
}

Bitte kommentieren Sie, wenn Sie Vorschläge haben.

1
Matthew Sisinni
tab = tabLayout.getSelectedTabPosition();
            tab++;
            TabLayout.Tab tabs = tabLayout.getTabAt(tab);
            if (tabs != null) {
                tabs.select();
            }
            else {
                tabLayout.getTabAt(0).select();
            }

Wenn Sie den nächsten Tab auf ein Klickereignis setzen möchten, verwenden Sie diesen Code, um seine Arbeit perfekt auszuführen

0
RanaUmer

Ich frage mich, ob diese Antwort relevant ist, da sie sehr spät kommt. Ich habe es tatsächlich in C # mit Xamarin erreicht.

tabs.GetChildAt(0).Selected = true;
 viewPager.SetCurrentItem(0, true);
0
Uchenna Nnodim

viewpager.setItem(position) sollte auch die Position der Registerkarte festlegen

0
locomain

Diese Lösung hat für mich funktioniert. Meine Situation ist etwas anders; In meinem Fall verwende ich das TabLayout mit einem ViewPager, füge weitere Ansichten hinzu und rufe notifyDataSetChange () auf.

Die Lösung besteht darin, einen Callback auf dem Observer von TabLayout zu setzen und zu scrollen, wenn die untergeordneten Elemente tatsächlich dem TabLayout hinzugefügt werden. Hier ist mein Beispiel:

/**
    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;
            }
        }
    });
}

Hier ist mein Code für den PagerAdapter, wenn Sie ihn zu lol brauchen:

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;
    }
}
0
Tyler

Wenn Ihre TabLayout in Verbindung mit einer ViewPager verwendet wird, die üblich ist, fügen Sie einfach Folgendes in die onCreate()-Methode Ihrer Aktivität ein:

tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout);

Dass einige Ihrer Registerkarten nicht angezeigt werden, zeigt an, dass das tabMode-Attribut auf app:tabMode="scrollable" gesetzt ist.

0
barnabas

Der Code-Ausschnitt unten funktioniert für mich

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) } ) }
}

Ich tauchte in Tab.select () ein und fand, dass Android Tablayout.setScrollPosition () verwendet, um diesen Bildlauf durchzuführen. In onCreate () wurden die Widgets nicht gemessen. Sie müssen den Aufruf verschieben, bis das Layout abgeschlossen ist.

0
Kun Zhang