Ymmärrys mukautetusta näkymästäMeasure

Understanding Custom View Onmeasure



viite: Androidin mukautettu näkymä (kolme, perusteellinen analyysi kontrollimittauksesta onMeasuressa)

Vanhempien hallinta kutsuu onMeasure-menetelmää, ja kaikki ylätason ohjaimet ovat ViewGroupin alaluokkia.
ViewGroup on abstrakti luokka, sillä on abstrakti menetelmä onLayoutissa, tämän menetelmän tehtävänä on sijoittaa kaikki alatason ohjaimet (järjestelyasento),
Koska se on abstrakti luokka eikä voi suoraan uusia objekteja, voimme käyttää näkymää asettelutiedostossa, mutta emme voi suoraan käyttää ViewGroupia.



Ennen lapsilukon sijainnin määrittämistä on saatava lapsen ohjaimen koko (vain lapsen ohjaimen koko voidaan määrittää oikein, jotta voidaan määrittää neljän pisteen koordinaatit ylös, alas, vasemmalle ja oikealle),
Ja ViewGroup ei ohita näkymän onMeasure-menetelmää, mikä tarkoittaa, että abstraktilla luokalla ViewGroup ei ole kykyä mitata lapsiohjainten kokoa, se voi mitata vain omaa kokoa.
Mutta koska ViewGroup on säilö, johon mahtuu aliohjaimia, tietysti järjestelmä ottaa myös huomioon ongelman alisäätimien mittaamisessa.
SoViewGroup tarjoaa kolme lastenhallinnan mittaamiseen liittyvää menetelmää (MeasuireChildren MeasuireChild MeasureChildWithMargins),
älä vain soita heille ViewGroupissa, joten sillä ei ole kykyä mitata lasten ohjainten kokoa.



Miksi on olemassa alimenetelmien mittausmenetelmiä, mutta onMeasure-menetelmää ei ohiteta suoraan ViewGroupissa ja kutsutaan sitten onMeasureen?
Koska eri säilöillä on erilaisia ​​tapoja sijoittaa aliohjaimia, kuten kahden ViewGroups -suhteen RelativeLayout- ja LinearLayout-alaluokat,
Heillä on erilaisia ​​tapoja sijoittaa alikontrolleja, jotkut sijoittuvat lineaarisesti ja toiset ovat päällekkäin, mikä johtaa erilaisiin tapoihin mitata alikontrolleja.
Joten ViewGroup ei mittaa suoraan alaohjaimia ollenkaan. Jos sen alaluokat haluavat mitata alikontrolleja, ne kirjoittavat onMeasure-menetelmän uudelleen omien mitoitettavien asetteluominaisuuksiensa mukaan.



Mittauksen aikana vanhemman valvonnan onMeasure-menetelmä kulkee läpi kaikki lapsen ohjaimet ja kutsuu lapsi-ohjainten mittausmenetelmän yksi kerrallaan, ja mittausmenetelmä kutsuu OnMeasure-toimintoa.
Sitten se kutsuu setMeasureDimension-menetelmää tallentaakseen mitatun koon. Kun olet käynyt sen läpi yhden kerran, ensimmäinen lapsilukko ja kaikki tämän lapsilukon lapsilukot suorittavat mittaustöiden loppuun
Aloita sitten toisen lapsisäätimen mittaaminen ... Lopuksi, kun kaikki vanhemman ohjauksen lapsen ohjaimet ovat suorittaneet mittauksen, kutsutaan setMeasureDimension-menetelmää mittauskoonsa tallentamiseksi.
On syytä huomata, että tätä prosessia ei suoriteta vain kerran, mikä tarkoittaa, että se voidaan suorittaa toistuvasti.
Koska vanhempainvalvonta havaitsee joskus mittauskierroksen jälkeen, että lapsilukon koko ei täytä vaatimuksia, ja se mittaa sen uudelleen.

Jos haluat mukauttaa ViewGroupia, sinun on ohitettava onMeasure-menetelmä, jossa lapsiohjainten koko mitataan. ViewGroup tarjoaa kolme menetelmää aliohjainten mittaamiseen. Lähdekoodi on seuraava:

/** *Traverse all the child controls in the ViewGroup, call measuireChild to measure the width and height */ protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) { final int size = mChildrenCount final View[] children = mChildren for (int i = 0 i final View child = children[i] if ((child.mViewFlags & VISIBILITY_MASK) != GONE) { measureChild(child, widthMeasureSpec, heightMeasureSpec) } } } /** * Measure the width and height of a child */ protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) { final LayoutParams lp = child.getLayoutParams() final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight, lp.width) final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop + mPaddingBottom, lp.height) child.measure(childWidthMeasureSpec, childHeightMeasureSpec) } /** * Measure the width and height of a child, considering the margin value */ protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams() final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin + widthUsed, lp.width) final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin + heightUsed, lp.height) child.measure(childWidthMeasureSpec, childHeightMeasureSpec) }

kuva



onMeasure-lähdekoodi:

protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension( getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)) } /** * Get a recommended minimum value for the width */ protected int getSuggestedMinimumWidth () { return (mBackground == null) ? mMinWidth : max(mMinWidth , mBackground.getMinimumWidth()) } /** * Get the default width and height values */ public static int getDefaultSize (int size, int measureSpec) { int result = size int specMode = MeasureSpec. getMode(measureSpec) int specSize = MeasureSpec. getSize(measureSpec) switch (specMode) { case MeasureSpec. UNSPECIFIED: result = size break case MeasureSpec. AT_MOST: case MeasureSpec. EXACTLY: result = specSize break } return result }

Opimme lähdekoodista:

Jos näkymän leveys- ja korkeustilaa ei ole määritetty, sen leveys ja korkeus asetetaan suurimpaan androidista: minWidth / Height = '' ja taustan leveys- ja korkeusarvoon.
Jos näkymän leveys- ja korkeustila on TÄYSIN (tietty koko), lopullinen leveys ja korkeus ovat tämä kokoarvo
Jos näkymän leveys- ja korkeustila on TARKKA (täytä vanhemman hallinta), lopullinen leveys ja korkeus täyttävät pääohjaimen
Jos näkymän leveys- ja korkeustila on AT_MOST (paketin sisältö), lopullinen leveys ja korkeus täyttävät myös pääohjaimen.

Jos mukautettu ohjausobjektimme on asettelutiedostossa, meidän on asetettava vain määritetty leveys ja korkeus, tai jos MATCH_PARENT, meidän ei tarvitse ohittaa onMeasure-menetelmää.
mutta jos mukautetun ohjausobjektin on määritettävä paketin sisältö WRAP_CONTENT, meidän on ohitettava onMeasure-menetelmä, jotta asetetaan tarvittava koko ohjaukselle oletusarvoisesti, WRAP_CONTENT-käsittely täyttää myös koko ylätason ohjauksen.
OnMeasure-menetelmän on lopuksi kutsuttava setMeasuredDimension-menetelmä tallentaakseen mitatut leveys- ja korkeusarvot.

Kontrollin koon mittaaminen aloitetaan vanhemman kontrollin avulla
Jos vanhempien hallinta haluaa mitata lapsilukon koon, sinun on kirjoitettava onMeasure-menetelmä uudelleen ja kutsuttava sitten methodChildren- tai measureChildWithMargin-menetelmä
On Measure -menetelmän parametrit luodaan getChildMeasureSpec
Jos meidän on käytettävä wrap_content mukautetussa ohjauksessa, meidän on ohitettava onMeasure-menetelmä
Vaiheet kontrollien mittaamiseen:
Vanhempien hallinta onMeasure-> measureChildren measureChildWithMargin->getChildMeasureSpec->
measure->onMeasure->setMeasureDimension-> of the child control
parent control onMeasure ends calling setMeasureDimension
Tallenna oma koko

ViewGroupin mukauttamisen vaiheet määritellään seuraavasti:
1. Peri ViewGroup ja ohita rakennusmenetelmä
2. Kirjoita onMeasure-menetelmä uudelleen mitataksesi lapsilukon leveyden ja korkeuden
3. Toteuta onLayout-menetelmä lastenhallinnan sijoittamiseksi

Mukautetun näkymän kutsuprosessi:

ViewWas created onFinishInflate() onMeasure() onMeasure() onSizeChanged(),w:1080,h:1080,oldw:0,oldh0 onLayout() onDraw()