ScrollView 內(nèi)放置自定義View的坑

前言

做程序開發(fā),基礎(chǔ)很重要延都。同樣是擰螺絲人家擰出來的可以經(jīng)久不壞雷猪,你擰出來的遇到點(diǎn)風(fēng)浪就開始顫抖,可見基本功的重要性晰房。此系列求摇,專門收錄一些看似基礎(chǔ),但是沒那么簡單的小細(xì)節(jié)殊者,同時(shí)提供權(quán)威解決方案与境。喜歡的同志們點(diǎn)個(gè)贊就是對(duì)我最大的鼓勵(lì)!先行謝過猖吴!

網(wǎng)上可能有一些其他文章摔刁,提供了解決方案,但是要么就是沒有提供可運(yùn)行demo海蔽,要么就是demo不夠純粹共屈,讓人探索起來受到其他代碼因素的影響,無法專注于當(dāng)前這個(gè)知識(shí)點(diǎn)(比如准潭,我只是想了解Activity的生命周期趁俊,你把生命周期探究的過程混入到一個(gè)很復(fù)雜的大雜燴Demo中,讓人一眼就沒有了閱讀Demo代碼的欲望)刑然,所以我覺得有必要做一個(gè)專題,用最純粹的方式展示一個(gè)的解決方案.

干貨

如下圖所示暇务,如果 你有一個(gè)自定義的TestView代碼如下:只是簡單的繪制一個(gè)文字

package study.hank.com.draw001.custom;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import study.hank.com.draw001.R;
import study.hank.com.draw001.Utils;

public class TestView extends View {

    public TestView(Context context) {
        this(context, null);
    }

    public TestView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setColor(getResources().getColor(R.color.aoyun_4));
        paint.setStyle(Paint.Style.FILL);
        paint.setTextAlign(Paint.Align.LEFT);
        paint.setTextSize(Utils.dp2px(50));

        canvas.drawText("測試文字", 100, 200, paint);

    }
}

然而你不知道出于什么原因泼掠,將它放到了ScrollView里面:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorF">

    <study.hank.com.draw001.custom.TestView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</ScrollView>

然后你運(yùn)行起來,看到的:是這樣的

image.png

哎呀垦细?什么都沒有择镇?是的,什么都沒有括改,但是如果我在 TextView里面加上onMeasure腻豌,變成下面這樣

package study.hank.com.draw001.custom;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import study.hank.com.draw001.R;
import study.hank.com.draw001.Utils;

public class TestView extends View {

   public TestView(Context context) {
       this(context, null);
   }

   public TestView(Context context, @Nullable AttributeSet attrs) {
       this(context, attrs, 0);
   }

   public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
       super(context, attrs, defStyleAttr);
   }

   //比之前多出這個(gè)方法重寫
   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
       super.onMeasure(widthMeasureSpec, heightMeasureSpec);

       int widthSize = MeasureSpec.getSize(widthMeasureSpec);
       int heightMode = MeasureSpec.getMode(heightMeasureSpec);

       if (heightMode == MeasureSpec.UNSPECIFIED) {
           setMeasuredDimension(widthSize, widthSize * 2);
       }

   }

   @Override
   protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);

       Paint paint = new Paint();
       paint.setColor(getResources().getColor(R.color.aoyun_4));
       paint.setStyle(Paint.Style.FILL);
       paint.setTextAlign(Paint.Align.LEFT);
       paint.setTextSize(Utils.dp2px(50));

       canvas.drawText("測試文字", 100, 200, paint);

   }
}

再運(yùn)行:就有文字顯示了

image.png

原理

一般來說,很少有人會(huì)把自定義View放到ScrollView里面,但是如果發(fā)生了這種問題吝梅,我們應(yīng)該要知道往哪個(gè)方向思考虱疏,所以探究一下原理,為什么我們自己對(duì)UNSPECIFIED進(jìn)行處理之后苏携,就能顯示了呢做瞪?

進(jìn)入ScrollView的源碼, 找到onMeasure方法:

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (!mFillViewport) {
            return;
        }

        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (heightMode == MeasureSpec.UNSPECIFIED) {
            return;
        }

           ...省略一大段
        }
    }

我們可以看到ScrollView對(duì)高的 UNSPECIFIED 并未做處理右冻,直接return了.
直接導(dǎo)致我們TestView (如果TestView自己也不作處理的話) 默認(rèn)的測量方式得出的高度就是 初始值 0装蓬,所以你什么都看不到.

image.png

image.png

所以,當(dāng)我們自己給TestView重寫onMeasure之后纱扭,

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if (heightMode == MeasureSpec.UNSPECIFIED) {
            setMeasuredDimension(widthSize, 500);
            Log.d("onMeasureTag", "第" + c++ + "次測量 - 之后的寬是:" + 
                          getMeasuredWidth() + "   /   高是:" + getMeasuredHeight());
        }

    }

就能看到文字了(為了表示TestView的范圍牍帚,我加了個(gè)橙色背景)

image.png

這是此時(shí)的日志:
image.png

至于更深層次的原因,比如乳蛾,為何ScrollView要對(duì)UNSPECIED不作處理暗赶。那就不得而知了,也沒必要知道的這么清楚屡久,誰知道谷歌大佬的想法呢···就這樣了忆首,歐了!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市被环,隨后出現(xiàn)的幾起案子糙及,更是在濱河造成了極大的恐慌,老刑警劉巖筛欢,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浸锨,死亡現(xiàn)場離奇詭異,居然都是意外死亡版姑,警方通過查閱死者的電腦和手機(jī)柱搜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剥险,“玉大人聪蘸,你說我怎么就攤上這事”碇疲” “怎么了健爬?”我有些...
    開封第一講書人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長么介。 經(jīng)常有香客問我娜遵,道長,這世上最難降的妖魔是什么壤短? 我笑而不...
    開封第一講書人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任设拟,我火速辦了婚禮慨仿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纳胧。我一直安慰自己镰吆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開白布躲雅。 她就那樣靜靜地躺著指蚜,像睡著了一般挣输。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評(píng)論 1 291
  • 那天座云,我揣著相機(jī)與錄音层坠,去河邊找鬼退盯。 笑死奄喂,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绵脯。 我是一名探鬼主播佳励,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蛆挫!你這毒婦竟也來了赃承?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤悴侵,失蹤者是張志新(化名)和其女友劉穎瞧剖,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體可免,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抓于,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浇借。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捉撮。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖妇垢,靈堂內(nèi)的尸體忽然破棺而出巾遭,到底是詐尸還是另有隱情,我是刑警寧澤闯估,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布恢总,位于F島的核電站,受9級(jí)特大地震影響睬愤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纹安,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一尤辱、第九天 我趴在偏房一處隱蔽的房頂上張望砂豌。 院中可真熱鬧,春花似錦光督、人聲如沸阳距。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筐摘。三九已至,卻和暖如春船老,著一層夾襖步出監(jiān)牢的瞬間咖熟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來泰國打工柳畔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留馍管,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓薪韩,卻偏偏與公主長得像确沸,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子俘陷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350