Używam TabLayout
z a ViewPager
i zastanawiam się, jak najskuteczniej zmienić kolor ikony wybranej karty w TabLayout.
Doskonałym odniesieniem do tego, jak to jest realizowane, jest aplikacja Google YouTube . Na stronie głównej znajdują się cztery ikony w kolorze ciemnoszarym. Po wybraniu określonej karty ikona karty staje się biała.
Jak mogę osiągnąć ten sam efekt bez bibliotek innych firm ?
Najwyraźniej jednym z możliwych rozwiązań są selektory. Ale w takim przypadku musiałbym znaleźć białą i szarą wersję ikony, a następnie przełączyć ikonę, gdy karta zostanie wybrana lub odznaczona. Zastanawiam się, czy istnieje bardziej skuteczna metoda, w której mogę po prostu zaznaczyć kolor ikony lub coś takiego. Nie udało mi się znaleźć tego w żadnym samouczku.
EDYTOWAĆ
Rozwiązanie, o którym wspomniałem bezpośrednio powyżej, wymaga użycia dwóch drawables dla każdej ikony karty. Zastanawiam się, czy istnieje sposób, aby zrobić to programowo z JEDNYM do rysowania dla ikony każdej karty.
źródło
android-studio
tagu tylko wtedy, gdy jest specyficzny dla IDE.Odpowiedzi:
Znalazłem sposób, który może być łatwy.
viewPager = (ViewPager) findViewById(R.id.viewpager); setupViewPager(viewPager); tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.setupWithViewPager(viewPager); tabLayout.setOnTabSelectedListener( new TabLayout.ViewPagerOnTabSelectedListener(viewPager) { @Override public void onTabSelected(TabLayout.Tab tab) { super.onTabSelected(tab); int tabIconColor = ContextCompat.getColor(context, R.color.tabSelectedIconColor); tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN); } @Override public void onTabUnselected(TabLayout.Tab tab) { super.onTabUnselected(tab); int tabIconColor = ContextCompat.getColor(context, R.color.tabUnselectedIconColor); tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN); } @Override public void onTabReselected(TabLayout.Tab tab) { super.onTabReselected(tab); } } );
źródło
Można to zrobić bardzo prosto, w całości w formacie XML.
Dodaj jedną linię do TabLayout w swoim xml
app:tabIconTint="@color/your_color_selector"
, jak poniżej:<android.support.design.widget.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabIconTint="@color/your_color_selector" app:tabIndicatorColor="@color/selected_color"/>
Następnie utwórz plik selektora kolorów (o nazwie „your_color_selector.xml” powyżej) w katalogu res / color:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/selected_color" android:state_selected="true"/> <item android:color="@color/unselected_color"/> </selector>
Zakłada się, że w pliku colors.xml masz 2 kolory, „selected_color” i „unselected_color”.
źródło
private void setupTabIcons() { tabLayout.getTabAt(0).setIcon(tabIcons[0]); tabLayout.getTabAt(1).setIcon(tabIcons[1]); tabLayout.getTabAt(2).setIcon(tabIcons[2]); tabLayout.getTabAt(3).setIcon(tabIcons[3]); tabLayout.getTabAt(0).getIcon().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN); tabLayout.getTabAt(1).getIcon().setColorFilter(Color.parseColor("#a8a8a8"), PorterDuff.Mode.SRC_IN); tabLayout.getTabAt(2).getIcon().setColorFilter(Color.parseColor("#a8a8a8"), PorterDuff.Mode.SRC_IN); tabLayout.getTabAt(3).getIcon().setColorFilter(Color.parseColor("#a8a8a8"), PorterDuff.Mode.SRC_IN); tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { tab.getIcon().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN); } @Override public void onTabUnselected(TabLayout.Tab tab) { tab.getIcon().setColorFilter(Color.parseColor("#a8a8a8"), PorterDuff.Mode.SRC_IN); } @Override public void onTabReselected(TabLayout.Tab tab) { } }); }
źródło
setCurrentItem(0)
wystąpienie viewPagera z aktywności, gdyonBackButton()
wywoływana jest metoda, a użytkownik będzie zawsze zwracany na pierwszym fragmencie, gdy spróbuje wyjść z aplikacji.Możesz użyć ColorStateList.
Najpierw utwórz plik xml (np.
/color/tab_icon.xml
), Który wygląda następująco i definiuje różne odcienie dla różnych stanów:<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/icon_light" android:state_selected="true" /> <item android:color="@color/icon_light_inactive" /> </selector>
Następnie dodaj to do swojego kodu:
ColorStateList colors; if (Build.VERSION.SDK_INT >= 23) { colors = getResources().getColorStateList(R.color.tab_icon, getTheme()); } else { colors = getResources().getColorStateList(R.color.tab_icon); } for (int i = 0; i < tabLayout.getTabCount(); i++) { TabLayout.Tab tab = tabLayout.getTabAt(i); Drawable icon = tab.getIcon(); if (icon != null) { icon = DrawableCompat.wrap(icon); DrawableCompat.setTintList(icon, colors); } }
Najpierw pobierasz ColorStateList z pliku XML (metoda bez motywu jest przestarzała, ale jest niezbędna dla urządzeń starszych niż Marshmallow). Następnie ustawiasz dla ikony każdej zakładki, to TintList na ColorStateList; użyj DrawableCompat (biblioteki wsparcia), aby obsługiwać również starsze wersje.
Otóż to!
źródło
tabLayout
).W tym celu musisz dostosować ikony kart za pomocą klasy selektora dla każdej karty, na przykład:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/advisory_selected" android:state_selected="true" /> <item android:drawable="@drawable/advisory_normal" android:state_selected="false" />
źródło
Dodaj to w
res > colors
katalogu:<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:color="@android:color/holo_orange_dark"/> <item android:color="@android:color/holo_red_light"/> </selector>
Dodaj kod w widoku karty w xml:
app:tabIconTint="@color/selector_tab"
źródło
Dlaczego nie używasz czcionek ikon (takich jak niesamowita czcionka) do swoich ikon? następnie zmień czcionkę tekstu zakładki na pożądaną ikonę .ttf i ciesz się zmianą wybranego koloru tekstu na ikony zakładek!
Ja sam użyłem tej metody i jest naprawdę ładna i czysta :)
najpierw ustaw tytuły z żądanej czcionki ikony:
w string.xml:
<string name="ic_calculator"></string> <string name="ic_bank"></string>
następnie w MainActivity.Java:
private void setupViewPager(ViewPager viewPager) { ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); adapter.addFragment(new FragmentBank(), getString(R.string.ic_bank)); adapter.addFragment(new FragmentCalculate(), getString(R.string.ic_calculator)); viewPager.setAdapter(adapter); }
Następnie powinieneś zmienić czcionkę tytułów kart na niesamowitą czcionkę:
Typeface typeFaceFont = Typeface.createFromAsset(getAssets(), "fontawesome-webfont.ttf"); TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.setupWithViewPager(viewPager); ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0); int tabsCount = vg.getChildCount(); for (int j = 0; j < tabsCount; j++) { ViewGroup vgTab = (ViewGroup) vg.getChildAt(j); int tabChildsCount = vgTab.getChildCount(); for (int i = 0; i < tabChildsCount; i++) { View tabViewChild = vgTab.getChildAt(i); if (tabViewChild instanceof TextView) { ((TextView) tabViewChild).setTypeface(typeFaceFont); } } }
i na koniec, w powiązanym pliku .xml, ustaw kolor dla swoich tabTextColor i tabSelectedTextColor:
<android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="horizontal" android:background="@color/colorPrimaryDark" app:tabSelectedTextColor="@color/colorAccent" app:tabTextColor="@color/textColorPrimary" app:tabIndicatorColor="@color/colorAccent" app:tabMode="fixed" app:tabGravity="fill"/> </android.support.design.widget.TabLayout>
oraz w colors.xml:
<resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="colorHighlight">#FFFFFF</color> <color name="textColorPrimary">#E1E3F3</color> </resources>
źródło
sprawdź poniższy kod. Dostosuj swoją ikonę, jedna to kolor, a druga bez koloru.
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/mybookings_select" android:state_selected="true"/><!-- tab is selected(colored icon)--> <item android:drawable="@drawable/mybookings" /><!-- tab is not selected(normal no color icon)-->
źródło
W odniesieniu do drugiej odpowiedzi, która pokazuje, jak ustawić kolor osobno, wiele osób może się zastanawiać, jak usunąć kolor pierwszej ikony podczas przełączania się na następną. Możesz zrobić to w ten sposób:
private void setupTabIcons() { tabLayout.getTabAt(0).setIcon(tabIcons[0]); tabLayout.getTabAt(1).setIcon(tabIcons[1]); tabLayout.getTabAt(2).setIcon(tabIcons[2]); tabLayout.getTabAt(3).setIcon(tabIcons[3]); tabLayout.getTabAt(0).getIcon().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN); tabLayout.getTabAt(1).getIcon().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN); tabLayout.getTabAt(2).getIcon().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN); tabLayout.getTabAt(3).getIcon().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN); tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { tab.getIcon().setColorFilter(Color.GREEN,PorterDuff.Mode.SRC_IN); } @Override public void onTabUnselected(TabLayout.Tab tab) { //for removing the color of first icon when switched to next tab tablayout.getTabAt(0).getIcon().clearColorFilter(); //for other tabs tab.getIcon().clearColorFilter(); } @Override public void onTabReselected(TabLayout.Tab tab) { } });}
Skomentowałbym drugą odpowiedź, ale nie miałem na to wystarczającej reputacji! Przepraszam. Ale pamiętaj, że zaoszczędzisz czas i ból głowy! Miłej nauki
źródło
Możesz użyć
addOnTabSelectedListener
, to działa dla mnie.tablayout = findViewById(R.id.viewall_tablayout); pager = findViewById(R.id.viewall_pager); adapter = new ViewPagerAdapter(getSupportFragmentManager()); adapter.addFragments(new RestFragment(),"Restaurant"); adapter.addFragments(new BarFragment(),"Bar"); adapter.addFragments(new HotelFragment(),"Hotel"); adapter.addFragments(new CoffeeFragment(),"Coffee Shop"); pager.setAdapter(adapter); tablayout.setupWithViewPager(pager); tablayout.getTabAt(0).setIcon(R.drawable.ic_restaurant); tablayout.getTabAt(1).setIcon(R.drawable.ic_glass_and_bottle_of_wine); tablayout.getTabAt(2).setIcon(R.drawable.ic_hotel_black_24dp); tablayout.getTabAt(3).setIcon(R.drawable.ic_hot_coffee); tablayout.getTabAt(0).getIcon().setTint(getResources().getColor(R.color.colorAccent,getTheme())); tablayout.getTabAt(1).getIcon().setTint(getResources().getColor(R.color.colorAccent,getTheme())); tablayout.getTabAt(2).getIcon().setTint(getResources().getColor(R.color.colorAccent,getTheme())); tablayout.getTabAt(3).getIcon().setTint(getResources().getColor(R.color.colorAccent,getTheme())); tablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { tab.getIcon().setTint(getResources().getColor(R.color.colorPrimary,getTheme())); } @Override public void onTabUnselected(TabLayout.Tab tab) { tab.getIcon().setTint(getResources().getColor(R.color.colorAccent,getTheme())); } @Override public void onTabReselected(TabLayout.Tab tab) { } });
źródło
Jednym z możliwych sposobów "Podświetlenia" ikony jest dostęp do widoku obrazu i ustawienie filtru kolorów. Spróbuj użyć metody setColorFilter (int color) ImageView i zastosować kolor biały.
źródło
tabLayout.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager) {...}
Został wycofany. Raczej używajtabLayout.addOnTabSelectedListener(new TabLayout.BaseOnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { int tabIconColor = ContextCompat.getColor(context, R.color.tabSelectedIconColor); tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN); } @Override public void onTabUnselected(TabLayout.Tab tab) { int tabIconColor = ContextCompat.getColor(context, R.color.tabUnselectedIconColor); tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN); } @Override public void onTabReselected(TabLayout.Tab tab) { } });
źródło
Aby zmienić odcień, nawet możesz ustawić ten sam kolor, co kiedykolwiek ma ikona karty do rysowania
<com.google.android.material.tabs.TabLayout android:id="@+id/tabs" android:background="@color/bgFrag" android:layout_width="match_parent" android:layout_height="?actionBarSize" android:layout_gravity="bottom" app:tabGravity="fill" app:tabTextColor="@drawable/tab_search_text_clr" app:tabIconTintMode="multiply" app:tabIconTint="#ffffff" app:tabIndicator="@null" app:tabTextAppearance="@android:style/TextAppearance.Widget.TabWidget" app:tabInlineLabel="true" app:tabMode="fixed" > </com.google.android.material.tabs.TabLayout>
<?xml version="1.0" encoding="utf-8" ?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_checked="true" android:color="#ffffff"/> <!-- checked --> <item android:state_selected="true" android:color="#ffffff"/> <!-- checked --> <item android:color="#acacac"/><!-- anything else --> </selector>
źródło
Rozszerzam moją preferowaną odpowiedź o ColorStateList stąd , możesz użyć następującego rozwiązania, jeśli używasz niestandardowych kart.
Skonfiguruj karty w pliku XML swojej aktywności
... <android.support.design.widget.TabLayout android:id="@+id/main_tablayout" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.design.widget.TabItem android:layout_width="match_parent" android:layout_height="match_parent" android:layout="@layout/nav_bar_tab_item"/> <android.support.design.widget.TabItem android:layout_width="match_parent" android:layout_height="match_parent" android:layout="@layout/nav_bar_tab_item"/> </android.support.design.widget.TabLayout> ...
I niestandardowy układ zakładek nav_bar_item.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout android:id="@+id/nav_bar_item_layout" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:paddingEnd="@dimen/_5sdp" android:paddingStart="@dimen/_5sdp"> <ImageView android:id="@+id/item_img" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <TextView android:id="@+id/item_description" android:layout_width="wrap_content" android:gravity="center" <!-- Use selector here to change the text color when selected/unselected --> android:textColor="@color/nav_bar_icons_color" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/item_img"/> </android.support.constraint.ConstraintLayout>
W Twojej działalności
tabLayout = findViewById(R.id.main_tablayout); ConstraintLayout navMyHotelLayout = (ConstraintLayout) tabLayout.getTabAt(0) .getCustomView(); tab1Icon = navMyHotelLayout.findViewById(R.id.item_img); tab1TextView = navMyHotelLayout.findViewById(R.id.item_description); tab1Icon.setImageResource(R.drawable.ic_tab1); // Use the selector here to change the color when selected/unselected tintImageViewSelector(tab1Icon, R.color.nav_bar_icons_color); tab1TextView.setText("tab 1"); ConstraintLayout navTtdLayout = (ConstraintLayout) tabLayout.getTabAt(1) .getCustomView(); tab2Icon = navTtdLayout.findViewById(R.id.item_img); tab2View = navTtdLayout.findViewById(R.id.item_description); tab2Icon.setImageResource(R.drawable.ic_tab2); tintImageViewSelector(tab2Icon, R.color.nav_bar_icons_color); tab2TextView.setText("tab 2");
I dodaj te funkcje pomocnicze do zmiany koloru
public static void tintDrawableSelector(Drawable vd, final @ColorRes int clrRes, Context context) { DrawableCompat.setTintList(vd, ContextCompat.getColorStateList(context, clrRes)); } public static void tintImageViewSelector(ImageView imgView, final @ColorRes int clrRes, Context context) { tintDrawableSelector(imgView.getDrawable(), clrRes); }
Na koniec selektor nav_bar_icons_color.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@android:color/white" android:state_checked="true"/> <item android:color="@android:color/white" android:state_selected="true"/> <item android:color="@android:color/black"/> </selector>
źródło
Sprawdź poniższy kod:
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { if(tab.getPosition() == 0){ tabLayout.getTabAt(0).setIcon(tabIcons1[0]); } if(tab.getPosition() == 1){ tabLayout.getTabAt(1).setIcon(tabIcons1[1]); } if(tab.getPosition() == 2){ tabLayout.getTabAt(2).setIcon(tabIcons1[2]); } } @Override public void onTabUnselected(TabLayout.Tab tab) { tabLayout.getTabAt(0).setIcon(tabIcons[0]); tabLayout.getTabAt(1).setIcon(tabIcons[1]); tabLayout.getTabAt(2).setIcon(tabIcons[2]); } @Override public void onTabReselected(TabLayout.Tab tab) { } });
źródło
Możesz zmienić kolor tekstu wybranej karty, korzystając z następującego atrybutu xml układu karty:
app:tabSelectedTextColor="your desired color"
Aby dostosować kolor ikony wybranej zakładki, musisz użyć selektora Utwórz plik xml w folderze do rysowania:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="selected_item_color" android:state_activated="true" /> <item android:color="unselected_item_color" /> </selector>
i dodaj ten selektor do atrybutu xml układu karty, jak poniżej:
app:tabIconTint="@drawable/name_of_file"
źródło
Wykonaj odpowiednio poniższe kroki.
app / src / main / res / values / colors.xml (dodaj do colors.xml)
<color name="icon_enabled">#F3D65F</color> <color name="icon_disabled">#FFFFFF</color>
app / src / main / res / color / custom_tab_icon.xml (Utwórz folder o nazwie color w res. Utwórz niestandardową kartę icon.xml w folderze).
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/icon_enabled" android:state_selected="true"/> <item android:color="@color/icon_disabled" android:state_selected="false"/> </selector>
app / src / main / res / drawable / ic_action_settings.png (Utwórz)
kliknij dwukrotnie action_settings, aby dodać
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="21.6" android:viewportHeight="21.6" android:tint="@color/custom_tab_icon"> <group android:translateX="-1.2" android:translateY="-1.2"> <path android:fillColor="#FF000000" android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z"/> </group> </vector>
źródło