Android中App控制字體大小

Android中App字體不隨系統字體大小的改變而改變

通常是在Application或Activity中複寫getResources方法 ,下面的代碼就實現了app字體不隨系統字體大小改變.

	override fun getResources(): Resources {
        val res = super.getResources()
        if(res != null && res.configuration.fontScale != 1f){
            val config = res.configuration
            config.setToDefaults()
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 ){
                createConfigurationContext(config)
            }else
              res.updateConfiguration(config, res.displayMetrics)

        }
        return super.getResources()
    }

還可以將textView的單位設置爲dp,這樣也不會跟隨系統字體大小改變,但是這裏有個不好的地方,如果app中要求可以調節app全局的字體大小功能,這時候用dp作爲單位就不太好了.

一般上面重寫getResources函數,是在app啓動的時候纔會生效,假設app在運行的時候~用戶跑去系統設置裏更改字體大小,這時候上面的配置不就不會生效了,而app裏的文字會跟着系統設置的字體大小而改變. 怎麼解決呢? 重寫Application的onConfigurationChanged函數做監聽操作,當系統字體大小發生變化,會觸發這個函數的調用,所以可以在該函數內重啓應用或主Activity,使得上面的getResources會被調用,從而app裏的文字不就不會跟着系統設置的字體大小而改變

	@Override
    public void onConfigurationChanged(Configuration newConfig) {

        if(newConfig.fontScale > 1){
            Intent intent = new Intent(this, MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
        }
        super.onConfigurationChanged(newConfig);
    }

遇到的問題:

  1. 在Android7.0中,調用Configuration類的setToDefaults函數,會使得Dialog彈框不顯示(半透明背景顯示),這是因爲在Android7.0中,Configuration類的setToDefaults函數內將screenWidthDp和screenHeightDp都置爲0 (SCREEN_WIDTH_DP_UNDEFINED和SCREEN_HEIGHT_DP_UNDEFINED的值都爲0), 從而造成dialog顯示不了,怎麼解決? 不調用setToDefaults函數,而單獨設置Configuration類的屬性,例如需要設置fontScale,代碼如下

    	override fun getResources(): Resources {
        	val res = super.getResources()
        	if(res != null && res.configuration.fontScale != 1f){
            	val config = res.configuration
            	config.fontScale = 1f
            	if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 ){
                	createConfigurationContext(config)
            	}else
              	res.updateConfiguration(config, res.displayMetrics)
        	}
        return super.getResources()
    }
    
  2. 在Android7.x中,重寫getResources並不能使得app裏的文字不會跟着系統設置的字體大小而改變,需要重寫activity的attachBaseContext才能生效,代碼如下

    	override fun attachBaseContext(newBase: Context?) {
    
        	if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
            	val res = newBase?.getResources()
            	val config = res?.configuration
            	config?.fontScale = 1
            	val newContext = newBase?.createConfigurationContext(config)
            	super.attachBaseContext(newContext)
            	return
        	}
        	super.attachBaseContext(newBase)
    	}
    

app中要求可以調節app全局的字體大小功能實現

通過設置configuration類的fontScale來控制字體的縮放比例,從而實現app全局的字體大小控制. 建議一般標準字體按照 “1” 這個值來取,大字體可以設置爲1.3.

	fun setFontScale(fontScale: Float) {
        val res = resources
        val configuration = res.configuration
        configuration.fontScale = fontScale
        res.updateConfiguration(configuration, res.displayMetrics)
    }

注意:通過代碼取當前頁面textView,其字體大小值的單位是px,需要轉化爲sp,才能乘以上面的fontScale,從而拿到放大之後的字體大小值

Autosizing TextViews

當app文字大小需要根據系統文字大小,或app中設置fontScale值進行調整時,可能會導致TextView文字溢出,部分不能顯示的問題,因爲TextView是無法根據字體大小來動態控制寬高的,所以這時候Android8.0新增用來動態改變TextView字體大小的新特性 Autosizing TextViews 就上場了,Autosizing TextViews使得TextView可以動態調整其文字的大小,使得不會出現溢出或部分顯示這種問題.

	<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <TextView
        android:layout_width="340dp"
        android:layout_height="50dp"
        android:background="@drawable/shape_bg_008577"
        android:gravity="center_vertical"
        android:maxLines="1"
        android:text="Autosizing TextViews 用來動態改變TextView字體大小"
        android:textSize="18sp"
        android:autoSizeTextType="uniform"
        android:autoSizeMaxTextSize="18sp"
        android:autoSizeMinTextSize="10sp"
        android:autoSizeStepGranularity="1sp"/>
	</LinearLayout>

主要通過上面4個auto開頭的屬性來控制,具體屬性意義自行查閱官方文檔.當需要兼容8.0以下設備,則需要用AppCompatTextView代替TextView,並且上面幾個屬性的命名空間需要用app命名空間.

	<android.support.v7.widget.AppCompatTextView
        android:layout_width="wrap_content"
        android:layout_height="@dimen/dimen_size_30"
        android:text="Autosizing TextViews 用來動態改變TextView字體大小"
        app:autoSizeTextType="uniform"
        app:autoSizeMaxTextSize="@dimen/textsize_16"
        app:autoSizeMinTextSize="@dimen/textsize_12"
        android:autoSizeStepGranularity="@dimen/textsize_2"/>

注意: 在AppCompatTextView使用android命名空間的auto開頭的屬性," 動態改變TextView字體大小 " 無效果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章