Android Academy · Oppitunti

Mukautetut näkymät

Piirtäkää mukautettuja käyttöliittymäkomponentteja alusta alkaen. Laajentakaa View-luokkaa, toteuttakaa onMeasure ja onDraw Canvasin ja Paintin avulla, määrittäkää mukautettuja XML-attribuutteja ja rakentakaa yhdistelmänäkymiä.

Oppitunti 3/513 vaihetta

Mukautetut näkymät on ilmainen Android Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/5. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Android Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Android Academy-kurssilla on yhteensä 5 oppituntia.

Miksi mukautettuja näkymiä?

Androidin valmiit näkymät eivät aina tee täsmälleen sitä, mitä tarvitsette. Mukautettujen näkymien avulla voitte:

  • Piirtää muotoja, kuvaajia, edistymisrenkaita tai kaavioita, joita SDK:ssa ei ole valmiina
  • Luoda brändin mukaisia käyttöliittymäkomponentteja, joita käytetään yhtenäisesti koko sovelluksessa
  • Yhdistää useita näkymiä yhdeksi uudelleenkäytettäväksi komponentiksi (Compound View)
  • Parantaa suorituskykyä poistamalla sisäkkäisiä asetteluhierarkioita

View-luokan laajentaminen

Luokaa mukautettu näkymä laajentamalla View-luokkaa (tai aliluokkaa, kuten ImageView). Korvatkaa tarvittava konstruktori:

class CircleProgressView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    var progress: Float = 0f
        set(value) {
            field = value.coerceIn(0f, 100f)
            invalidate()   // trigger redraw
        }

    // onMeasure and onDraw go here
}

onMeasure()

onMeasure() kertoo ylätasolle, kuinka suureksi näkymä haluaa tulla. Kutsukaa aina setMeasuredDimension()-metodia lopuksi:

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    val desiredSize = 200  // dp → pixels
    val px = (desiredSize * resources.displayMetrics.density).toInt()

    val width  = resolveSize(px, widthMeasureSpec)
    val height = resolveSize(px, heightMeasureSpec)

    // Square: same width and height
    val size = minOf(width, height)
    setMeasuredDimension(size, size)
}

Paint — piirtotyökalu

Paint-olio sisältää piirtotyylin tiedot (väri, viivan leveys ja antialiasointi). Luokaa se kerran — älkää koskaan luoko sitä onDraw()-metodin sisällä:

class CircleProgressView ... : View(...) {

    // Create Paint in init, not in onDraw!
    private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.LTGRAY
        style = Paint.Style.STROKE
        strokeWidth = 20f
        strokeCap = Paint.Cap.ROUND
    }

    private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.parseColor("#6750A4")
        style = Paint.Style.STROKE
        strokeWidth = 20f
        strokeCap = Paint.Cap.ROUND
    }
}

onDraw() — näkymän piirtäminen

onDraw(canvas) kutsutaan aina, kun näkymä on piirrettävä uudelleen. Piirtäkää muotoja, tekstiä ja bittikarttoja Canvas-olion avulla:

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)

    val cx = width / 2f
    val cy = height / 2f
    val radius = (minOf(width, height) / 2f) - 30f

    // Draw background circle
    canvas.drawCircle(cx, cy, radius, backgroundPaint)

    // Draw progress arc
    val oval = RectF(cx - radius, cy - radius, cx + radius, cy + radius)
    val sweepAngle = 360f * (progress / 100f)
    canvas.drawArc(oval, -90f, sweepAngle, false, progressPaint)
}

invalidate() ja requestLayout()

Kaksi tapaa käynnistää päivitys:

  • invalidate() — piirtää näkymän uudelleen (kutsuu onDraw-metodia). Käyttäkää tätä, kun sisältö muuttuu mutta koko pysyy samana.
  • requestLayout() — mittaa ja piirtää näkymän uudelleen (kutsuu ensin onMeasure- ja sitten onDraw-metodia). Käyttäkää tätä, kun näkymän koko muuttuu.

Mukautetut määritteet (attrs.xml)

Määritelkää mukautetut XML-määritteet, jotta näkymä voidaan määrittää asettelutiedostoista:

<!-- res/values/attrs.xml -->
<resources>
    <declare-styleable name="CircleProgressView">
        <attr name="progressColor" format="color" />
        <attr name="trackColor"    format="color" />
        <attr name="strokeWidth"   format="dimension" />
        <attr name="progress"      format="float" />
    </declare-styleable>
</resources>

Mukautettujen määritteiden lukeminen

Lukekaa määritteet konstruktorissa komennolla obtainStyledAttributes:

init {
    context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView).use { ta ->
        progressPaint.color = ta.getColor(
            R.styleable.CircleProgressView_progressColor,
            Color.parseColor("#6750A4")
        )
        backgroundPaint.color = ta.getColor(
            R.styleable.CircleProgressView_trackColor,
            Color.LTGRAY
        )
        val sw = ta.getDimension(R.styleable.CircleProgressView_strokeWidth, 20f)
        progressPaint.strokeWidth = sw
        backgroundPaint.strokeWidth = sw
        progress = ta.getFloat(R.styleable.CircleProgressView_progress, 0f)
    }
}

Mukautetun näkymän käyttäminen XML:ssä

Käyttäkää mukautettua näkymää asettelun XML:ssä täydellisen luokkapolun ja mukautettujen määritteiden avulla:

<!-- In any layout XML -->
<com.example.myapp.CircleProgressView
    android:id="@+id/progressView"
    android:layout_width="120dp"
    android:layout_height="120dp"
    app:progress="65"
    app:progressColor="@color/primary"
    app:trackColor="@color/surface_variant"
    app:strokeWidth="12dp" />

<!-- Control in code: -->
binding.progressView.progress = 75f

Yhdistelmänäkymät

Yhdistelmänäkymä yhdistää olemassa olevia näkymiä yhdeksi uudelleenkäytettäväksi komponentiksi. Laajentakaa asetteluluokkaa, kuten LinearLayout-luokkaa:

class SearchBarView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : LinearLayout(context, attrs) {

    private val binding = ViewSearchBarBinding.inflate(LayoutInflater.from(context), this)

    init {
        orientation = HORIZONTAL
        binding.ivSearch.setOnClickListener {
            onSearchClick?.invoke(binding.etSearch.text.toString())
        }
    }

    var onSearchClick: ((String) -> Unit)? = null

    fun setHint(hint: String) { binding.etSearch.hint = hint }
}

Tekstin piirtäminen

Piirtäkää teksti Canvasille komennolla drawText(). Keskittäkää se tarkasti komennon Paint.getFontMetrics() avulla:

private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
    color = Color.BLACK
    textSize = 48f
    textAlign = Paint.Align.CENTER
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    val cx = width / 2f
    val cy = height / 2f

    // Vertically center the text:
    val fm = textPaint.fontMetrics
    val textY = cy - (fm.ascent + fm.descent) / 2f
    canvas.drawText("${progress.toInt()}%", cx, textY, textPaint)
}

Pikatarkistus

Mitä metodia kutsutte mukautetun näkymän piirtämiseksi uudelleen, kun data muuttuu mutta koko pysyy samana?

Kertaus: mukautetut näkymät

Osaatte nyt piirtää näytölle mitä tahansa:

  • Laajentakaa View-luokkaa käyttämällä @JvmOverloads constructor -määritystä
  • onMeasure() — ilmoittakaa haluttu koko komennolla setMeasuredDimension()
  • Paint — määrittää tyylin; luokaa kerran, ei onDraw()-metodin sisällä
  • onDraw(canvas) — piirtäkää ympyröitä, kaaria, tekstiä ja bittikarttoja
  • invalidate() piirtää uudelleen, requestLayout() mittaa uudelleen
  • Mukautetut määritteet attrs.xml-tiedoston kautta XML-määrityksiä varten
  • Yhdistelmänäkymä — laajentakaa asettelua olemassa olevien näkymien yhdistämiseksi

Seuraavaksi: herättäkää käyttöliittymänne eloon animaatioilla ja siirtymillä.

Aloita maksutta

Opi Kotlin tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
36
Oppitunnit
152

Usein kysytyt kysymykset

Onko oppitunti ”Mukautetut näkymät” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Android Academy-oppimispolun 3 oppituntia, myös oppitunnin “Mukautetut näkymät”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Android Academy-kurssilla on yhteensä 5 oppituntia.

Mitä opin oppitunnilla ”Mukautetut näkymät”?

Piirtäkää mukautettuja käyttöliittymäkomponentteja alusta alkaen. Laajentakaa View-luokkaa, toteuttakaa onMeasure ja onDraw Canvasin ja Paintin avulla, määrittäkää mukautettuja XML-attribuutteja ja r… Harjoittelet Android Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Android Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Android Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/5.

Kuinka kauan ”Mukautetut näkymät”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Android Academy-oppitunnilla?

Kyllä. Jokainen Android Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Material Designin perusteet
  2. Teemat ja tyylit
  3. Mukautetut näkymät
  4. Animaatiot ja siirtymät
  5. Alareunan navigointi ja välilehdet
← Takaisin: Android Academy