ฉันกำลังพยายามทำสิ่งใหม่TabLayout
จากไลบรารีการออกแบบของ Android
ฉันต้องการที่จะเปลี่ยนข้อความแท็บอักษรที่กำหนดเอง และผมพยายามที่จะค้นหาจัดแต่งทรงผมที่เกี่ยวข้องกับTabLayout
แต่จบลงไปนี้
โปรดชี้แนะวิธีการเปลี่ยนแบบอักษรของแท็บ
คำตอบ:
สร้าง TextView จาก Java Code หรือ XML แบบนี้
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:textSize="15sp"
android:textColor="@color/tabs_default_color"
android:gravity="center"
android:layout_height="match_parent"
/>
ตรวจสอบให้แน่ใจว่าได้เก็บ id ไว้เหมือนเดิมเพราะ TabLayout จะตรวจสอบ ID นี้หากคุณใช้ textview ที่กำหนดเอง
จากนั้นโค้ดจะขยายเลย์เอาต์นี้และตั้งค่าแบบกำหนดเองTypeface
ในมุมมองข้อความนั้นและเพิ่มมุมมองแบบกำหนดเองนี้ลงในแท็บ
for (int i = 0; i < tabLayout.getTabCount(); i++) {
//noinspection ConstantConditions
TextView tv = (TextView)LayoutInflater.from(this).inflate(R.layout.custom_tab,null)
tv.setTypeface(Typeface);
tabLayout.getTabAt(i).setCustomView(tv);
}
tabTextColor
และtabSelectedTextColor
ทรัพย์สินในสถานการณ์นี้ได้อย่างไร?
หากคุณกำลังใช้TabLayout
และต้องการเปลี่ยนแบบอักษรคุณต้องเพิ่มใหม่สำหรับลูปในโซลูชันก่อนหน้านี้ดังนี้:
private void changeTabsFont() {
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(Font.getInstance().getTypeFace(), Typeface.NORMAL);
}
}
}
}
โปรดดูการเปลี่ยนรูปแบบตัวอักษรในแท็บแถบการทำงานโดยใช้ sherlock
TabLayout
setTypeFace
คือ a TypeFace
ในกรณีที่คุณไม่พบFont
คลาส (ซึ่งดูเหมือนจะไม่มีสำหรับฉัน)
สร้างสไตล์ที่คุณกำหนดเองและใช้สไตล์หลักเป็น parent="@android:style/TextAppearance.Widget.TabWidget"
และในเค้าโครงแท็บของคุณให้ใช้ลักษณะนี้เป็น app:tabTextAppearance="@style/tab_text"
ตัวอย่าง: สไตล์:
<style name="tab_text" parent="@android:style/TextAppearance.Widget.TabWidget">
<item name="android:fontFamily">@font/poppins_regular</item>
</style>
ตัวอย่าง: องค์ประกอบเค้าโครงแท็บ:
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:tabTextAppearance="@style/tab_text" />
parent="TextAppearance.Design.Tab"
ในกรณีของฉัน
TextAppearance.Widget.TabWidget
ผมได้รับข้อยกเว้นแปลกผิดปกติเมื่อใช้ คำตอบของ @Javatar แก้ไขให้ฉัน
คำตอบที่ยอดเยี่ยมจาก praveen Sharma เพียงเล็กน้อยเพิ่มเติม: แทนที่จะใช้changeTabsFont()
ทุกที่ที่คุณต้องการTabLayout
คุณสามารถใช้ของคุณเองCustomTabLayout
ได้
import android.content.Context;
import android.graphics.Typeface;
import android.support.design.widget.TabLayout;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class CustomTabLayout extends TabLayout {
private Typeface mTypeface;
public CustomTabLayout(Context context) {
super(context);
init();
}
public CustomTabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mTypeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/Roboto-Regular.ttf");
}
@Override
public void addTab(Tab tab) {
super.addTab(tab);
ViewGroup mainView = (ViewGroup) getChildAt(0);
ViewGroup tabView = (ViewGroup) mainView.getChildAt(tab.getPosition());
int tabChildCount = tabView.getChildCount();
for (int i = 0; i < tabChildCount; i++) {
View tabViewChild = tabView.getChildAt(i);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(mTypeface, Typeface.NORMAL);
}
}
}
}
และอีกสิ่งหนึ่ง
TabView
เป็นLinearLayout
กับTextView
ภายใน (มันยังสามารถเลือกที่จะมีImageView
) ดังนั้นคุณสามารถทำให้โค้ดง่ายขึ้น:
@Override
public void addTab(Tab tab) {
super.addTab(tab);
ViewGroup mainView = (ViewGroup) getChildAt(0);
ViewGroup tabView = (ViewGroup) mainView.getChildAt(tab.getPosition());
View tabViewChild = tabView.getChildAt(1);
((TextView) tabViewChild).setTypeface(mTypeface, Typeface.NORMAL);
}
แต่ฉันจะไม่แนะนำวิธีนี้ หากTabLayout
การนำไปใช้งานมีการเปลี่ยนแปลงโค้ดนี้อาจทำงานไม่ถูกต้องหรืออาจผิดพลาดได้
อีกวิธีหนึ่งในการปรับแต่งTabLayout
คือการเพิ่มมุมมองแบบกำหนดเองเข้าไป นี่คือที่ดีตัวอย่างเช่น
addTab(Tab tab, int position, boolean setSelected)
แทนaddTab(Tab tab)
ไฟล์.
หากต้องการใช้XML
ฟีเจอร์การรองรับแบบอักษรบนอุปกรณ์ที่ใช้งานAndroid 4.1
(API ระดับ 16) ขึ้นไปให้ใช้ Support Library 26+
myfont.ttf
ไฟล์ของคุณในโฟลเดอร์ฟอนต์ที่สร้างขึ้นใหม่เมื่อres/values/styles.xml
เพิ่ม:
<style name="customfontstyle" parent="@android:style/TextAppearance.Small">
<item name="android:fontFamily">@font/myfont</item>
</style>
ในไฟล์รูปแบบเพิ่มแอป: tabTextAppearance = "@ style / customfontstyle",
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabTextAppearance="@style/customfontstyle"
app:tabMode="fixed" />
โปรดดูที่ [แบบอักษรใน xml] ( https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml )
วิธีการต่อไปนี้จะเปลี่ยนแบบอักษรแบบViewGroup
วนซ้ำทั้งหมด ฉันเลือกวิธีนี้เพราะคุณไม่ต้องสนใจโครงสร้างภายในของTabLayout
. ฉันใช้ไลบรารีการประดิษฐ์ตัวอักษรเพื่อตั้งค่าแบบอักษร
void changeFontInViewGroup(ViewGroup viewGroup, String fontPath) {
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
if (TextView.class.isAssignableFrom(child.getClass())) {
CalligraphyUtils.applyFontToTextView(child.getContext(), (TextView) child, fontPath);
} else if (ViewGroup.class.isAssignableFrom(child.getClass())) {
changeFontInViewGroup((ViewGroup) viewGroup.getChildAt(i), fontPath);
}
}
}
สำหรับการสนับสนุนการออกแบบ 23.2.0 โดยใช้ setupWithViewPager คุณจะต้องย้ายโค้ดจาก addTab (แท็บแท็บ) ไปยัง addTab (แท็บแท็บบูลีน setSelected)
คุณสามารถใช้สิ่งนี้ได้ผลสำหรับฉัน
private void changeTabsFont() {
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) {
AssetManager mgr = getActivity().getAssets();
Typeface tf = Typeface.createFromAsset(mgr, "fonts/Roboto-Regular.ttf");//Font file in /assets
((TextView) tabViewChild).setTypeface(tf);
}
}
}
}
ฉันพบว่ามันง่ายใน 23.4.0 โดยไม่ต้องใช้ลูป เพียงแค่แทนที่ addTab (แท็บ @NonNull, boolean setSelected) ตามที่ @ejw แนะนำ
@Override
public void addTab(@NonNull Tab tab, boolean setSelected) {
CoralBoldTextView coralTabView = (CoralBoldTextView) View.inflate(getContext(), R.layout.coral_tab_layout_view, null);
coralTabView.setText(tab.getText());
tab.setCustomView(coralTabView);
super.addTab(tab, setSelected);
}
และนี่คือ XML
<?xml version="1.0" encoding="utf-8"?>
<id.co.coralshop.skyfish.ui.CoralBoldTextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
android:textColor="@color/graylove"
android:textSize="@dimen/tab_text_size" />
หวังว่ามันจะช่วยได้ :)
android:textColor="@color/graylove"
ควรมีตัวเลือกรายการสถานะสำหรับสิ่งนั้นโดยระบุสี
ดังที่Andreiตอบคุณสามารถเปลี่ยนแบบอักษรได้โดยการขยายคลาสTabLayout และอย่างที่Penzzzกล่าวไว้คุณไม่สามารถทำได้ในวิธีการaddTab แทนที่เมธอดonLayoutเป็นร้อง:
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom){
super.onLayout(changed, left, top, right, bottom);
final ViewGroup tabStrip = (ViewGroup)getChildAt(0);
final int tabCount = tabStrip.getChildCount();
ViewGroup tabView;
int tabChildCount;
View tabViewChild;
for(int i=0; i<tabCount; i++){
tabView = (ViewGroup)tabStrip.getChildAt(i);
tabChildCount = tabView.getChildCount();
for(int j=0; j<tabChildCount; j++){
tabViewChild = tabView.getChildAt(j);
if(tabViewChild instanceof AppCompatTextView){
if(fontFace == null){
fontFace = Typeface.createFromAsset(context.getAssets(), context.getString(R.string.IranSans));
}
((TextView) tabViewChild).setTypeface(fontFace, Typeface.BOLD);
}
}
}
}
ต้องเขียนทับเมธอด onLayout เนื่องจากเมื่อคุณใช้เมธอดsetupWithViewPagerเพื่อผูก TabLayout กับ ViewPager คุณต้องตั้งค่าข้อความแท็บด้วยเมธอด setText หรือใน PagerAdapter หลังจากนั้นและเมื่อเกิดเหตุการณ์นี้เมธอด onLayout จะถูกเรียกบน ViewGroup หลัก ( TabLayout) และเป็นที่สำหรับตั้งค่า fontface (การเปลี่ยนข้อความ TextView ทำให้เกิดการเรียก onLayout method ของผู้ปกครอง - tabView มีลูกสองคนคนหนึ่งคือ ImageView อีกอันคือ TextView)
ทางออกอื่น:
ขั้นแรกบรรทัดของรหัสเหล่านี้:
if(fontFace == null){
fontFace = Typeface.createFromAsset(context.getAssets(), context.getString(R.string.IranSans));
}
ในวิธีแก้ปัญหาข้างต้นควรเขียนนอกสองลูป
แต่ทางออกที่ดีกว่าสำหรับAPI> = 16ใช้android: fontFamily :
สร้างแบบอักษรของไดเรกทอรีทรัพยากร Androidและคัดลอกแบบอักษรที่คุณต้องการไปยังไดเร็กทอรี
จากนั้นใช้รูปแบบเหล่านี้:
<style name="tabLayoutTitles">
<item name="android:textColor">@color/white</item>
<item name="android:textSize">@dimen/appFirstFontSize</item>
<item name="android:fontFamily">@font/vazir_bold</item>
</style>
<style name="defaultTabLayout">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">@dimen/defaultTabLayoutHeight</item>
<item name="android:gravity">right</item>
<item name="tabTextAppearance">@style/tabLayoutTitles</item>
<item name="tabSelectedTextColor">@color/white</item>
<item name="tabIndicatorColor">@color/white</item>
<item name="tabIndicatorHeight">@dimen/accomTabIndicatorHeight</item>
<item name="tabMode">fixed</item>
<item name="tabGravity">fill</item>
<item name="tabBackground">@drawable/rectangle_white_ripple</item>
<item name="android:background">@color/colorPrimary</item>
</style>
onLayout()
ได้รับการเรียกร้องให้มีการเปลี่ยนแปลงทุกรูปแบบเช่นการสลับแท็บหรือแม้แต่การเลื่อนรายการด้านล่างแท็บโดยที่for
s ที่ซ้อนกันในTabLayout
แอปหลายแท็บจะล้า
onLayout()
จะถูกเรียกหลายครั้งเมื่อเปลี่ยนแท็บ (ไม่แน่ใจว่าทำไมกันแน่) แต่สำหรับบัญชีนี้ฉันจะตั้งค่าแบบอักษรเมื่อboolean changed
เป็นจริงเท่านั้น การทำเช่นนั้นจะป้องกันการตั้งค่าฟอนต์หลาย ๆ ครั้ง
วิธีการแก้ไขของฉันเช่นนี้เปลี่ยนข้อความแท็บที่ระบุ
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
ViewGroup vgTab = (ViewGroup) vg.getChildAt(1);
View tabViewChild = vgTab.getChildAt(1);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setText(str);
}
I think this is easier way.
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
app:tabTextColor="@color/lightPrimary"
app:tabSelectedTextColor="@color/white"
style="@style/CustomTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<style name="CustomTabLayout" parent="Widget.Design.TabLayout">
<item name="tabMaxWidth">20dp</item>
<item name="tabMode">scrollable</item>
<item name="tabIndicatorColor">?attr/colorAccent</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabPaddingStart">12dp</item>
<item name="tabPaddingEnd">12dp</item>
<item name="tabBackground">?attr/selectableItemBackground</item>
<item name="tabTextAppearance">@style/CustomTabTextAppearance</item>
<item name="tabSelectedTextColor">?android:textColorPrimary</item>
</style>
<style name="CustomTabTextAppearance" parent="TextAppearance.Design.Tab">
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">?android:textColorSecondary</item>
<item name="textAllCaps">false</item>
</style>
ส่วนขยาย Kotlin ที่เหมาะกับฉัน:
fun TabLayout.setFont(font: FontUtils.Fonts) {
val vg = this.getChildAt(0) as ViewGroup
for (i: Int in 0..vg.childCount) {
val vgTab = vg.getChildAt(i) as ViewGroup?
vgTab?.let {
for (j: Int in 0..vgTab.childCount) {
val tab = vgTab.getChildAt(j)
if (tab is TextView) {
tab.typeface = FontUtils.getTypeFaceByFont(FontUtils.Fonts.BOLD, context)
}
}
}
}
}
2p ของฉัน Kotlin พร้อมการตรวจสอบอ้างอิงใช้ได้ทุกที่เพราะจะหยุดหากมีสิ่งผิดปกติ
private fun setTabLayouFont(tabLayout: TabLayout) {
val viewGroupTabLayout = tabLayout.getChildAt(0) as? ViewGroup?
(0 until (viewGroupTabLayout?.childCount ?: return))
.map { viewGroupTabLayout.getChildAt(it) as? ViewGroup? }
.forEach { viewGroupTabItem ->
(0 until (viewGroupTabItem?.childCount ?: return))
.mapNotNull { viewGroupTabItem.getChildAt(it) as? TextView }
.forEach { applyDefaultFontToTextView(it) }
}
}
และนี่คือการใช้งานของฉันใน Kotlin ที่อนุญาตให้เปลี่ยนแบบอักษรสำหรับแท็บที่เลือกและไม่ได้เลือก
class FontTabLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0
) : TabLayout(context, attrs, defStyleAttr) {
private var textSize = 14f
private var defaultSelectedPosition = 0
private var selectedTypeFace: Typeface? = ResourcesCompat.getFont(context, R.font.muli_bold)
private var normalTypeFace: Typeface? = ResourcesCompat.getFont(context, R.font.muli_regular)
@ColorInt private var selectedColor = 0
@ColorInt private var normalTextColor = 0
init {
attrs?.let { initAttrs(it) }
addOnTabSelectedListener()
}
private fun initAttrs(attrs: AttributeSet) {
val a = context.obtainStyledAttributes(attrs, R.styleable.FontTabLayout)
textSize = a.getDimensionPixelSize(R.styleable.FontTabLayout_textSize, 14).toFloat()
defaultSelectedPosition = a.getInteger(R.styleable.FontTabLayout_defaultSelectedPosition, 0)
val selectedResourceId = a.getResourceId(R.styleable.FontTabLayout_selectedTypeFace, R.font.muli_bold)
val normalResourceId = a.getResourceId(R.styleable.FontTabLayout_normalTypeFace, R.font.muli_regular)
selectedColor = a.getColor(com.google.android.material.R.styleable.TabLayout_tabSelectedTextColor, 0)
normalTextColor = a.getColor(R.styleable.FontTabLayout_normalTextColor, 0)
selectedTypeFace = ResourcesCompat.getFont(context, selectedResourceId)
normalTypeFace = ResourcesCompat.getFont(context, normalResourceId)
a.recycle()
}
private fun addOnTabSelectedListener() {
addOnTabSelectedListener(object : OnTabSelectedListenerAdapter() {
override fun onTabUnselected(tab: Tab?) {
getCustomViewFromTab(tab)?.apply {
setTextColor(normalTextColor)
typeface = normalTypeFace
}
}
override fun onTabSelected(tab: Tab?) {
getCustomViewFromTab(tab)?.apply {
setTextColor(selectedColor)
typeface = selectedTypeFace
}
}
private fun getCustomViewFromTab(tab: Tab?) = tab?.customView as? AppCompatTextView
})
}
override fun setupWithViewPager(viewPager: ViewPager?, autoRefresh: Boolean) {
super.setupWithViewPager(viewPager, autoRefresh)
addViews(viewPager)
}
private fun addViews(viewPager: ViewPager?) {
for (i in 0 until tabCount) {
val customTabView = getCustomTabView(i).apply {
typeface = if (i == defaultSelectedPosition) selectedTypeFace else normalTypeFace
val color = if (i == defaultSelectedPosition) selectedColor else normalTextColor
setTextColor(color)
text = viewPager?.adapter?.getPageTitle(i)
}
getTabAt(i)?.customView = customTabView
}
}
private fun getCustomTabView(position: Int): AppCompatTextView {
return AppCompatTextView(context).apply {
gravity = Gravity.CENTER
textSize = this@FontTabLayout.textSize
text = position.toString()
}
}
}
ใน attrs.xml:
<declare-styleable name="FontTabLayout">
<attr name="normalTextColor" format="reference|color" />
<attr name="textSize" format="dimension" />
<attr name="defaultSelectedPosition" format="integer" />
<attr name="selectedTypeFace" format="reference" />
<attr name="normalTypeFace" format="reference" />
</declare-styleable>
ด้วยฟังก์ชั่นการขยาย kotlin ใช้สิ่งนี้:
fun TabLayout.setFontSizeAndColor(typeface: Typeface, @DimenRes textSize: Int, @ColorRes textColor: Int) {
val viewGroup: ViewGroup = this.getChildAt(0) as ViewGroup
val tabsCount: Int = viewGroup.childCount
for (j in 0 until tabsCount) {
val viewGroupTab: ViewGroup = viewGroup.getChildAt(j) as ViewGroup
val tabChildCount: Int = viewGroupTab.childCount
for (i in 0 until tabChildCount) {
val tabViewChild: View = viewGroupTab.getChildAt(i) as View
if ( tabViewChild is TextView) {
tabViewChild.typeface = typeface
tabViewChild.gravity = Gravity.FILL
tabViewChild.maxLines = 1
tabViewChild.setTextSize(TypedValue.COMPLEX_UNIT_PX, this.resources.getDimension(textSize))
tabViewChild.setTextColor(ContextCompat.getColor(this.context, textColor))
}
}
}
}
เปลี่ยน
if (tabViewChild instanceof TextView) {
สำหรับ
if (tabViewChild instanceof AppCompatTextView) {
เพื่อให้ใช้งานได้กับ android.support.design.widget.TabLayout (อย่างน้อยจาก com.android.support:design:23.2.0)