亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺扒Android動(dòng)態(tài)設(shè)置字體大小的示例

 更新時(shí)間:2017年12月07日 10:17:26   作者:JarvanMo  
本篇文章主要介紹了淺扒Android動(dòng)態(tài)設(shè)置字體大小的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

說(shuō)點(diǎn)廢話

Android開(kāi)發(fā)中,TextView類的控件應(yīng)該說(shuō)是很常用了。一般來(lái)說(shuō)我們是通過(guò)android:textSize="20sp"

來(lái)設(shè)置字體大小,但是很多時(shí)候也需要?jiǎng)討B(tài)設(shè)置字體大小,調(diào)用也很簡(jiǎn)單:

textView.setTextSize(textSize);

為了適配各種各樣的型號(hào),我們一般會(huì)將字體大小定義到dimens.xml之中:

<dimen name="text_size">16sp</dimen>

然后在java代碼中設(shè)置定義好的字體大小:

float dimen = getResources().getDimension(R.dimen.text_size);
textView.setTextSize(dimen);

滿心歡喜的運(yùn)行一下,看一效果,結(jié)果發(fā)現(xiàn)字體奇大無(wú)比!??!遠(yuǎn)非16sp?。。‰y道不應(yīng)該通過(guò)getDimension()取值嗎?通過(guò)logcat我發(fā)現(xiàn),在Nexus 6p并且<dimen name="text_size">16sp</dimen>下,在通過(guò)getDimension(R.dimen.text_size)得到返回值是56.0!

實(shí)際上,在java代碼中取在dimens.xml中定義的值一共有三種:

  1. getDimension()
  2. getDimensionPixelOffset()
  3. getDimensionPixelSize()

看到這三個(gè)函數(shù)的名稱時(shí),還是會(huì)有點(diǎn)不知所云。本著“不求甚解,遍歷式開(kāi)發(fā)”的原則,我把這三種方式都試了一遍,結(jié)果發(fā)現(xiàn)字體大小沒(méi)一個(gè)是對(duì)的,這就詭異了。難道這里有平行宇宙?至此,我只能翻出我的英漢大詞典,讓我們?nèi)ヌ綄ひ幌耫ocs吧。

getDimension()

  /**
   * Retrieve a dimensional for a particular resource ID. Unit 
   * conversions are based on the current {@link DisplayMetrics} associated
   * with the resources.
   * 
   * @param id The desired resource identifier, as generated by the aapt
   *      tool. This integer encodes the package, type, and resource
   *      entry. The value 0 is an invalid identifier.
   * 
   * @return Resource dimension value multiplied by the appropriate 
   * metric.
   */
  public float getDimension(@DimenRes int id) throws NotFoundException {   
  }

通過(guò)注釋我們不難發(fā)現(xiàn),getDimension()是根據(jù)指定id獲取一個(gè)基于當(dāng)前DisplayMetrics的值。這個(gè)值究竟是什么也沒(méi)有說(shuō),只知道是float,并且單位轉(zhuǎn)換是基于當(dāng)前資源的,但肯定不是像素,如果是像素應(yīng)該是int。

getDimensionPixelSize

  /**
   * Retrieve a dimensional for a particular resource ID for use
   * as a size in raw pixels. This is the same as
   * {@link #getDimension}, except the returned value is converted to
   * integer pixels for use as a size. A size conversion involves
   * rounding the base value, and ensuring that a non-zero base value
   * is at least one pixel in size.
   * 
   * @param id The desired resource identifier, as generated by the aapt
   *      tool. This integer encodes the package, type, and resource
   *      entry. The value 0 is an invalid identifier.
   * 
   * @return Resource dimension value multiplied by the appropriate 
   * metric and truncated to integer pixels.
   */
  public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
 
  }

getDimensionPixelSize()的功能與getDimension()類似,不同的是將結(jié)果轉(zhuǎn)換為int,并且小數(shù)部分四舍五入,這個(gè)結(jié)果將作為尺寸。getDimensionPixelSize()進(jìn)行了尺寸轉(zhuǎn)換,這個(gè)轉(zhuǎn)換實(shí)際是上四舍五入的結(jié)果,并且保證返回值是一個(gè)至少是1像素的非零數(shù)值。

getDimensionPixelOffset()

  /**
   * Retrieve a dimensional for a particular resource ID for use
   * as an offset in raw pixels. This is the same as
   * {@link #getDimension}, except the returned value is converted to
   * integer pixels for you. An offset conversion involves simply
   * truncating the base value to an integer.
   * 
   * @param id The desired resource identifier, as generated by the aapt
   *      tool. This integer encodes the package, type, and resource
   *      entry. The value 0 is an invalid identifier.
   * 
   * @return Resource dimension value multiplied by the appropriate 
   * metric and truncated to integer pixels.
   */
  public int getDimensionPixelOffset(@DimenRes int id) throws NotFoundException {
  }

getDimensionPixelOffset()與getDimension()功能類似,不同的是將結(jié)果轉(zhuǎn)換為int,這個(gè)結(jié)果將用作原始像素的偏移量。偏移轉(zhuǎn)換(offset conversion,函數(shù)命名中的offset是這個(gè)意思)的作用之一是將基礎(chǔ)值簡(jiǎn)單地截短為整數(shù),注意直接截?cái)嘈?shù)位,即取整(其實(shí)就是把float強(qiáng)制轉(zhuǎn)化為int,注意不是四舍五入)。

階段性總結(jié)

由此可見(jiàn),這三個(gè)函數(shù)返回的都是絕對(duì)尺寸,而不是相對(duì)尺寸(dp\sp等)。如果getDimension()返回結(jié)果是30.5f,那么getDimensionPixelSize()返回結(jié)果就是31,getDimensionPixelOffset()返回結(jié)果就是30。
至此,應(yīng)該說(shuō)getDimensionPixelSize() getDimension() getDimensionPixelOffset()我們已經(jīng)大致有所了解了,但是如果想更深入了解一下,就需要深入源碼以驗(yàn)證上述解釋。

扒源碼

深入源碼,我們可以發(fā)現(xiàn)其實(shí)這三個(gè)函數(shù)的實(shí)現(xiàn)大同小異,以getDimension()為例:

 public float getDimension(@DimenRes int id) throws NotFoundException {
    final TypedValue value = obtainTempTypedValue();
    try {
      final ResourcesImpl impl = mResourcesImpl;
      impl.getValue(id, value, true);
      if (value.type == TypedValue.TYPE_DIMENSION) {
        return TypedValue.complexToDimension(value.data, impl.getDisplayMetrics());
      }
      throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
          + " type #0x" + Integer.toHexString(value.type) + " is not valid");
    } finally {
      releaseTempTypedValue(value);
    }
  }

類TypedValue是動(dòng)態(tài)類型數(shù)據(jù)的容器,其主要用于盛放Resources的值。上述代碼第7行就是根據(jù)id獲取TypedValue的值,getDimension()、getDimensionPixelOffset()和getDimensionPixelSize()函數(shù)體唯一的不同就是第7行:

  1. getDimension()調(diào)用的是TypedValue的complexToDimension()方法
  2. getDimensionPixelSize調(diào)用的是TypedValue的complexToDimensionPixelSize()方法
  3. getDimensionPixelOffset調(diào)用的是TypedValue的complexToDimensionPixelOffset()方法

順藤摸瓜,我們繼續(xù)深入ypedValue,查看complexToDimension()、complexToDimensionPixelSize()和complexToDimensionPixelOffset()函數(shù)的區(qū)別,會(huì)發(fā)現(xiàn)這三個(gè)函數(shù)體內(nèi)容依舊大同小異,以complexToDimension()為例:

  public static float complexToDimension(int data, DisplayMetrics metrics) {
    return applyDimension(
      (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
      complexToFloat(data),
      metrics);
  }

complexToDimensionPixelOffset()與complexToDimension()不同的是將結(jié)果進(jìn)行了強(qiáng)轉(zhuǎn),實(shí)際上相當(dāng)直接截?cái)嘈?shù)部分;
complexToDimensionPixelSize()是將結(jié)果進(jìn)行四舍五入,并取整。這里的四舍五入實(shí)際上就是把結(jié)果加上0.5f然后進(jìn)行強(qiáng)轉(zhuǎn)。

applyDimension()

各位看官,源碼已經(jīng)看到了這里,是否已感覺(jué)很無(wú)趣?但applyDimension()的實(shí)現(xiàn)已經(jīng)脫光了在等著你呢:

public static float applyDimension(int unit, float value,DisplayMetrics metrics) {
    switch (unit) {
    case COMPLEX_UNIT_PX:
      return value;
    case COMPLEX_UNIT_DIP:
      return value * metrics.density;
    case COMPLEX_UNIT_SP:
      return value * metrics.scaledDensity;
    case COMPLEX_UNIT_PT:
      return value * metrics.xdpi * (1.0f/72);
    case COMPLEX_UNIT_IN:
      return value * metrics.xdpi;
    case COMPLEX_UNIT_MM:
      return value * metrics.xdpi * (1.0f/25.4f);
    }
    return 0;
  }

在上述代碼中,我們發(fā)現(xiàn)在applyDimension()中根據(jù)單位的不同,將float乘上不同的系數(shù)。如dip/dp需乘上屏幕系數(shù),sp則需乘上字號(hào)的縮放系數(shù),pt、in、mm等也是根據(jù)相應(yīng)的算法進(jìn)行換算(從COMPLEX_UNIT_PX直接返回float可以看出,該方法是將數(shù)值轉(zhuǎn)成像素?cái)?shù))。

再次總結(jié)

通過(guò)上述探索,我們不難發(fā)現(xiàn),在Adroid并沒(méi)有在java代碼中直接獲取dimens.xml中定義的dp(dip)/sp的值的API,只有g(shù)etDimension()、getDimensionPixelOffset()和getDimensionPixelSize()這個(gè)三個(gè)方法來(lái)獲取絕對(duì)尺寸。但有時(shí)候我們確實(shí)需要?jiǎng)討B(tài)獲取dimen.xml中的值,并為TextView設(shè)置字體大小。而這種方法直接應(yīng)用在textView.setTextSize(dimen);都是有問(wèn)題的。那我們將從TextView入手,尋找一個(gè)正確的姿勢(shì)來(lái)設(shè)置字體大小。

setTextSize()

首先把代碼端上來(lái):

 public void setTextSize(float size) {
    setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
  }

原來(lái)setTextSize(float)調(diào)用了他的重載方法setTextSize(int,float),并且第一個(gè)參數(shù)傳的默認(rèn)值是TypedValue.COMPLEX_UNIT_SP,眼熟嗎,沒(méi)錯(cuò)就是之前提到的。那么,我們繼續(xù)看看一下setTextSize(int,float)做了什么:

  public void setTextSize(int unit, float size) {
    if (!isAutoSizeEnabled()) {
      setTextSizeInternal(unit, size, true /* shouldRequestLayout */);
    }
  }

很顯然是調(diào)用了setTextSizeInternal(unit, size, true /* shouldRequestLayout */);??吹竭@累不,不過(guò)看都看了就再看看唄,說(shuō)不定比蒼老師好看:

  private void setTextSizeInternal(int unit, float size, boolean shouldRequestLayout) {
    Context c = getContext();
    Resources r;
    if (c == null) {
      r = Resources.getSystem();
    } else {
      r = c.getResources();
    }
    setRawTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics()),shouldRequestLayout);
  }

高能!?。ypedValue.applyDimension(unit, size, r.getDisplayMetrics())是不是很眼熟???還記得applyDimension()是怎么處理數(shù)據(jù)的嗎?

我們發(fā)現(xiàn)在applyDimension()中根據(jù)單位的不同,將float乘上不同的系數(shù)。如dip/dp需乘上屏幕系數(shù),sp則需乘上字號(hào)的縮放系數(shù),pt、in、mm等也是根據(jù)相應(yīng)的算法進(jìn)行換算(從COMPLEX_UNIT_PX直接返回float可以看出,該方法是將數(shù)值轉(zhuǎn)成像素?cái)?shù))

綜上,setTextSize(float)給傳的值的單位其實(shí)是SP,但通過(guò)getDimension()取的值卻不是這樣的。為了證實(shí)默認(rèn)單位是SP,各位看官可以直接傳個(gè)16,看看和16sp是不是一樣的。所以問(wèn)題是不得到了解決?

結(jié)論

Android中并不提供直接從dimens.xml獲取dp/sp數(shù)值的方法,通過(guò)getDimensionPixelSize() getDimension() getDimensionPixelOffset()獲取的值是經(jīng)過(guò)處理的。所以正確地動(dòng)態(tài)設(shè)置TextView字體大小的姿勢(shì)應(yīng)該是:

int dimen = getResources().getDimensionPixelSize(R.dimen.text_size);
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,dimen);

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android?線程死鎖場(chǎng)景與優(yōu)化解決

    Android?線程死鎖場(chǎng)景與優(yōu)化解決

    線程死鎖是老生常談的問(wèn)題,線程池死鎖本質(zhì)上屬于線程死鎖的一部分,線程池造成的死鎖問(wèn)題往往和業(yè)務(wù)場(chǎng)景相關(guān),本文主要介紹了Android?線程死鎖場(chǎng)景與優(yōu)化,感興趣的可以了解一下
    2023-12-12
  • android創(chuàng)建和刪除文件夾和文件的實(shí)現(xiàn)方法

    android創(chuàng)建和刪除文件夾和文件的實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇android創(chuàng)建和刪除文件夾和文件的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • Android中使用HTTP服務(wù)的用法詳解

    Android中使用HTTP服務(wù)的用法詳解

    這篇文章主要介紹了Android中使用HTTP服務(wù)的用法詳解,有需要的可以了解一下。
    2016-11-11
  • SurfaceView開(kāi)發(fā)[捉小豬]手機(jī)游戲 (二)

    SurfaceView開(kāi)發(fā)[捉小豬]手機(jī)游戲 (二)

    這篇文章主要介紹了用SurfaceView開(kāi)發(fā)[捉小豬]手機(jī)游戲 (二)本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • Android實(shí)現(xiàn)View的拖拽

    Android實(shí)現(xiàn)View的拖拽

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)View的拖拽,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • 使用Flutter實(shí)現(xiàn)一個(gè)走馬燈布局的示例代碼

    使用Flutter實(shí)現(xiàn)一個(gè)走馬燈布局的示例代碼

    這篇文章主要介紹了使用 Flutter 實(shí)現(xiàn)一個(gè)走馬燈布局的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Android的文本和輸入之創(chuàng)建輸入法教程

    Android的文本和輸入之創(chuàng)建輸入法教程

    輸入法編輯器(IME)是讓用戶輸入文本的控件,Android提供了一個(gè)可擴(kuò)展的的輸入法的框架,它允許應(yīng)用程序給用戶提供另外的輸入法,如軟鍵盤(pán)或語(yǔ)音輸入,需要的朋友可以了解下
    2012-12-12
  • Android EditText實(shí)現(xiàn)關(guān)鍵詞批量搜索示例

    Android EditText實(shí)現(xiàn)關(guān)鍵詞批量搜索示例

    本篇文章主要介紹了Android EditText實(shí)現(xiàn)關(guān)鍵詞批量搜索示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-02-02
  • Android Studio實(shí)現(xiàn)華為手機(jī)的充電動(dòng)畫(huà)效果

    Android Studio實(shí)現(xiàn)華為手機(jī)的充電動(dòng)畫(huà)效果

    本篇文章介紹了我參照華為手機(jī)的充電動(dòng)畫(huà)來(lái)仿照實(shí)現(xiàn)的樣例,這個(gè)動(dòng)畫(huà)并不難實(shí)現(xiàn),不過(guò)案例精簡(jiǎn)具有參考意義,需要的朋友快往下看吧
    2021-10-10
  • Android5.1系統(tǒng)通過(guò)包名給應(yīng)用開(kāi)放系統(tǒng)權(quán)限的方法

    Android5.1系統(tǒng)通過(guò)包名給應(yīng)用開(kāi)放系統(tǒng)權(quán)限的方法

    這篇文章主要介紹了Android5.1系統(tǒng)通過(guò)包名給應(yīng)用開(kāi)放系統(tǒng)權(quán)限的方法,此文介紹一種通過(guò)修改Android平臺(tái)系統(tǒng)層代碼,根據(jù)指定的應(yīng)用包名給對(duì)應(yīng)的應(yīng)用在該平臺(tái)上開(kāi)放系統(tǒng)權(quán)限,需要的朋友可以參考下
    2017-11-11

最新評(píng)論