Shadow: ουσία, δημιουργία σκιών σε mobile εφαρμογές

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-02-28 Χρόνος ανάγνωσης: 9 λεπ

Shadow (σκιά) — ένα οπτικό εφέ σε κινητές διεπαφές που δημιουργεί την ψευδαίσθηση βάθους και ιεραρχίας μεταξύ στοιχείων. Οι σκιές δείχνουν ποιο στοιχείο βρίσκεται ψηλότερα στο Z-επίπεδο και επομένως είναι πιο σημαντικό ή διαδραστικό. Σύμφωνα με το Material Design Guidelines (Google, 2026), οι συστημικές σκιές χρησιμοποιούν πέντε βασικά ύψη (elevation): 0 dp (επίπεδο), 1–4 dp (κουμπιά), 6–12 dp (κάρτες), 16–24 dp (διαλόγους), 24+ dp (modal παράθυρα). Διαβάστε περισσότερα για το ύψος στοιχείων στο άρθρο για το Elevation.

Κύρια σημεία

  • Σκιά (shadow) — ένα οπτικό εφέ που δημιουργεί βάθος σκουραίνοντας την περιοχή κάτω από το στοιχείο με θόλωμα στις άκρες.
  • Στο iOS οι σκιές ορίζονται μέσω ιδιοτήτων CALayer: shadowColor, shadowOffset, shadowRadius, shadowOpacity.
  • Στο Android οι σκιές διαχειρίζονται μέσω elevation (Material Design) ή προσαρμοσμένης απόδοσης μέσω OutlineProvider.
  • Το Jetpack Compose υποστηρίζει σκιές μέσω Modifier.shadow() και elevation σε Card/Surface.
  • Στο Flutter οι σκιές υλοποιούνται μέσω BoxShadow σε BoxDecoration ή μέσω PhysicalModel.

Τι είναι η σκιά στο UI;

Σκιά (shadow) στις διεπαφές χρήστη — ένα οπτικό εφέ που μιμείται τον φωτισμό και το βάθος. Η σκιά δημιουργείται με τη σχεδίαση ενός σκούρου θαμπού αντιγράφου του στοιχείου μετατοπισμένου σε σχέση με το πρωτότυπο. Στο mobile design, οι σκιές εκτελούν τρεις λειτουργίες: δείχνουν ιεραρχία (υψηλότερο στοιχείο — μεγαλύτερη σκιά), σηματοδοτούν διαδραστικότητα (κουμπιά με σκιά φαίνονται πατητά), διαχωρίζουν το περιεχόμενο από το φόντο (κάρτες με σκιά διαβάζονται ως ξεχωριστά μπλοκ).

Στο Material Design της Google, οι σκιές είναι άρρηκτα συνδεδεμένες με την έννοια του elevation (ύψους). Κάθε στοιχείο καταλαμβάνει ένα συγκεκριμένο ύψος στη Z-συντεταγμένη και η σκιά είναι η προβολή φωτισμού από πάνω. Οι Human Interface Guidelines της Apple δεν επιβάλλουν αυστηρό σύστημα υψών, αλλά συνιστούν τη χρήση σκιών για τη δημιουργία οπτικής ιεραρχίας και βάθους στις διεπαφές.

Σύμφωνα με έρευνα της Nielsen Norman Group (2024), οι σωστά τοποθετημένες σκιές μειώνουν τον χρόνο εύρεσης ενός διαδραστικού στοιχείου κατά 24%. Οι σκιές βοηθούν επίσης χρήστες με προβλήματα όρασης να διακρίνουν τα όρια των στοιχείων. Ωστόσο, η υπερβολική χρήση σκιών (3+ επίπεδα σε μια οθόνη) αυξάνει το γνωστικό φορτίο και υποβαθμίζει την αντίληψη.

Σκιές στο iOS: CALayer και SwiftUI

Στο iOS οι σκιές υλοποιούνται μέσω ιδιοτήτων CALayer: το shadowColor ορίζει το χρώμα της σκιάς, το shadowOffset — τη μετατόπιση σε CGSize (x, y), το shadowRadius — την ακτίνα θολώματος, το shadowOpacity — την αδιαφάνεια από 0 έως 1. Για απόδοση συνιστάται επίσης ο ορισμός shadowPath — UIBezierPath που περιγράφει το σχήμα της σκιάς, ώστε το Core Animation να μην το υπολογίζει αυτόματα.

swift
// UIKit: ρύθμιση σκιάς μέσω CALayer
import UIKit

let cardView = UIView()
cardView.backgroundColor = .systemBackground
cardView.layer.cornerRadius = 12

// Ρύθμιση σκιάς
cardView.layer.shadowColor = UIColor.black.cgColor
cardView.layer.shadowOpacity = 0.15
cardView.layer.shadowOffset = CGSize(width: 0, height: 4)
cardView.layer.shadowRadius = 8

"> Βελτιστοποίηση: ρητό shadowPath
cardView.layer.shadowPath = UIBezierPath(
    roundedRect: cardView.bounds,
    cornerRadius: 12
).cgPath

Στο SwiftUI οι σκιές ορίζονται μέσω του modifier .shadow() με παραμέτρους color, radius, x, y. Το SwiftUI εφαρμόζει αυτόματα το shadowPath και διαχειρίζεται την απόδοση. Για προχωρημένες σκιές (εσωτερικές σκιές, πολλαπλές σκιές) χρησιμοποιήστε overlay() με LinearGradient.

swift
// SwiftUI: σκιά μέσω του modifier shadow
import SwiftUI

VStack {
    Text("Κάρτα με σκιά")
        .padding()
        .background(Color.white)
        .cornerRadius(16)
        .shadow(
            color: .black.opacity(0.15),
            radius: 10,
            x: 0,
            y: 4
        )
}

Απόδοση σκιών στο iOS: εάν το shadowPath δεν έχει οριστεί, το Core Animation υπολογίζει τη σκιά βάσει του σχήματος του layer σε κάθε καρέ, γεγονός που μπορεί να προκαλέσει καθυστερήσεις κατά την κινούμενη εικόνα. Για στατικά στοιχεία ορίζετε πάντα shadowPath. Για κινούμενα στοιχεία χρησιμοποιήστε shouldRasterize = true στο CALayer για αποθήκευση της σκιάς σε ξεχωριστό layer. Στο SwiftUI η ραστεροποίηση διαχειρίζεται μέσω .drawingGroup().

Σκιές στο Android: elevation και προσαρμοσμένες σκιές

Στο Android οι σκιές στο Material Design υλοποιούνται μέσω elevation — της ιδιότητας View που ορίζει το ύψος του στοιχείου στη Z-συντεταγμένη. Το σύστημα σχεδιάζει αυτόματα τη σκιά βάσει του elevation και του outlineProvider (περιγράμματος στοιχείου). Όσο υψηλότερο είναι το elevation, τόσο μεγαλύτερη και πιο θαμπή είναι η σκιά. Για View που δεν κληρονομούν το Material Design (π.χ. AppCompat), οι σκιές λειτουργούν μόνο με ενεργοποιημένη επιτάχυνση υλικού.

xml
<!-- XML: elevation μέσω ιδιοτήτων -->
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="12dp"
    app:cardElevation="6dp">
    <!-- Περιεχόμενο κάρτας -->
</androidx.cardview.widget.CardView>

Για προσαρμοσμένες σκιές στο Android View System χρησιμοποιείται το OutlineProvider. Το ViewOutlineProvider επιτρέπει τον ορισμό αυθαίρετου σχήματος μέσω outline.setRoundRect() ή outline.setPath(). Χωρίς OutlineProvider η σκιά σχεδιάζεται βάσει του ορθογώνιου σχήματος του View, το οποίο δεν λαμβάνει υπόψη τη στρογγυλοποίηση γωνιών.

kotlin
// Kotlin: προσαρμοσμένο OutlineProvider για σκιά
import android.graphics.Outline
import android.view.View
import android.view.ViewOutlineProvider

val myView: View = findViewById(R.id.myView)
myView.outlineProvider = object : ViewOutlineProvider() {
    override fun getOutline(view: View, outline: Outline) {
        outline.setRoundRect(
            0, 0, view.width, view.height,
            12f  // ακτίνα γωνίας
        )
    }
}
myView.elevation = 8f  // ύψος σκιάς σε px
myView.translationZ = 4f  // επιπλέον ύψος κατά το πάτημα

Στο Jetpack Compose οι σκιές διαχειρίζονται μέσω Modifier.shadow() και elevation στα components Card και Surface. Το Modifier.shadow() δέχεται elevation και shape. Σε αντίθεση με το View System, το Compose σχεδιάζει σκιές στο δικό του pipeline απόδοσης, προσφέροντας πιο προβλέψιμη συμπεριφορά σε όλες τις εκδόσεις Android.

kotlin
// Jetpack Compose: σκιά μέσω Modifier.shadow
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Card(
    modifier = Modifier.shadow(
        elevation = 6.dp,
        shape = RoundedCornerShape(12.dp),
        clip = false
    ),
    colors = CardDefaults.cardColors(containerColor = Color.White)
) {
    Text("Card με προσαρμοσμένη σκιά")
}

Συστάσεις για τη χρήση σκιών

Η σωστή χρήση σκιών βελτιώνει την αντίληψη της διεπαφής, η λανθασμένη — δημιουργεί οπτικό θόρυβο και υποβαθμίζει την απόδοση. Το Material Design ορίζει πέντε επίπεδα elevation: 0 dp (χωρίς σκιά), 1–4 dp (κουμπιά, chips), 6–12 dp (κάρτες, μενού), 16–24 dp (διάλογοι, κάτω πάνελ), 24+ dp (modal παράθυρα, FAB).

ΕπίπεδοElevationΣτοιχείαΧαρακτηριστικό σκιάς
00 dpΚείμενο, εικονίδια, φόντοΧωρίς σκιά, επίπεδο layer
11–4 dpΚουμπιά, πεδία εισόδουΕλαφριά σκιά, μικρή μετατόπιση
26–12 dpΚάρτες, SnackbarΜέτρια σκιά, αισθητό θόλωμα
316–24 dpΔιάλογοι, μενούΒαθιά σκιά, μεγάλο θόλωμα
424+ dpModal παράθυραΜέγιστη σκιά, στοιχείο αιωρείται

Κανόνες ορθής πρακτικής: (1) μη χρησιμοποιείτε σκιές για στοιχεία που δεν πρέπει να τραβούν την προσοχή (φόντα, διαχωριστικά), (2) το ύψος της σκιάς πρέπει να αντιστοιχεί στη σημασία του στοιχείου — όσο πιο σημαντικό, τόσο υψηλότερα, (3) κατά το πάτημα κουμπιού μειώστε το elevation με κίνηση για απτική ανάδραση, (4) αποφύγετε σκιές σε σκούρα φόντα — χρησιμοποιήστε overlay (φωτισμός/σκούρασμα) αντί σκιάς. Στο Material You (Android 12+) οι σκιές προσαρμόζονται στο θέμα: σε σκούρο φόντο το elevation αντικαθίσταται από έγχρωμο layer (surface tint).

Σκιές στο Flutter: BoxShadow και PhysicalModel

Στο Flutter οι σκιές υλοποιούνται μέσω BoxShadow εντός BoxDecoration. Το BoxShadow δέχεται color, offset, blurRadius και spreadRadius. Το Flutter υποστηρίζει πολλαπλές σκιές: η μετάδοση λίστας BoxShadow επιτρέπει τη δημιουργία σύνθετων εφέ — για παράδειγμα, εξωτερική σκιά + εσωτερικός φωτισμός. PhysicalModel — ένα εναλλακτικό που προσομοιώνει φυσική σκιά βάσει σχήματος (BeveledRectangleBorder, CircleBorder).

dart
// Flutter: σκιά μέσω BoxDecoration + BoxShadow
import 'package:flutter/material.dart';

Container(
    decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12.0),
        boxShadow: [
            BoxShadow(
                color: Colors.black.withOpacity(0.15),
                offset: Offset(0, 4),
                blurRadius: 8.0,
                spreadRadius: 0,
            ),
        ],
    ),
    child: Text('Container με σκιά'),
)

// PhysicalModel για φυσική σκιά
PhysicalModel(
    color: Colors.white,
    elevation: 6.0,
    shadowColor: Colors.black.withOpacity(0.2),
    borderRadius: BorderRadius.circular(12.0),
    child: Text('Φυσικό μοντέλο με σκιά'),
)

Απόδοση: Το BoxShadow με πολλαπλές σκιές μπορεί να προκαλέσει ανασχεδίαση (repaint) σε κάθε αλλαγή. Για στατικά στοιχεία χρησιμοποιήστε PhysicalModel — αποθηκεύει τη σκιά σε ξεχωριστό layer (RepaintBoundary). Στο Flutter 3.16+ προστέθηκε υποστήριξη για Material 3 elevation με προσαρμοστικές σκιές που αλλάζουν χρώμα και θόλωμα ανάλογα με το θέμα (φωτεινό/σκοτεινό).

Συχνές Ερωτήσεις

Σε τι διαφέρει το elevation από τη σκιά;

Elevation — είναι το αριθμητικό ύψος του στοιχείου στη Z-συντεταγμένη, ενώ το shadow (σκιά) — το οπτικό εφέ που δημιουργείται από αυτό το ύψος. Στο Android, το elevation — ιδιότητα View που παράγει αυτόματα σκιά. Στο design, το elevation και το shadow χρησιμοποιούνται συχνά ως εναλλάξιμοι όροι, αλλά τεχνικά το elevation είναι η αιτία και το shadow το αποτέλεσμα.

Γιατί δεν εμφανίζεται η σκιά στο Android;

Ελέγξτε: (1) το View έχει elevation μεγαλύτερο από 0, (2) έχει οριστεί outlineProvider (αν το View δεν είναι από τη βιβλιοθήκη Material), (3) είναι ενεργοποιημένη η επιτάχυνση υλικού (android:hardwareAccelerated="true" στο manifest). Το CardView διαχειρίζεται αυτόματα το outlineProvider. Για προσαρμοσμένα View καλέστε view.outlineProvider = ViewOutlineProvider.BACKGROUND.

Πώς να δημιουργήσω εσωτερική σκιά (inner shadow) στο iOS;

Το CALayer δεν υποστηρίζει άμεσα εσωτερικές σκιές. Χρησιμοποιήστε συνδυασμό: CAGradientLayer με μαύρο χρώμα και διαφάνεια εντός της μάσκας (mask), ή τοποθετήστε UIImageView με raster εσωτερική σκιά. Στο SwiftUI η εσωτερική σκιά υλοποιείται μέσω overlay με LinearGradient και blendMode(.multiply).

Πώς να κάνετε κίνηση στη σκιά κατά το πάτημα κουμπιού;

Στο Android χρησιμοποιήστε translationZ για κίνηση: σε ηρεμία elevation = 2 dp, κατά το πάτημα translationZ = 4 dp (συνολικό ύψος 6 dp). Στο iOS κάντε κίνηση shadowOffset και shadowRadius ταυτόχρονα με τον μετασχηματισμό του κουμπιού. Στο SwiftUI χρησιμοποιήστε withAnimation με αλλαγή elevation μέσω Modifier.shadow(). Στο Flutter — AnimatedContainer με αλλαγή BoxShadow.

Πόσες σκιές μπορούν να χρησιμοποιηθούν σε μία οθόνη;

Το Material Design συνιστά όχι περισσότερα από τρία επίπεδα elevation σε μία οθόνη. Εάν υπάρχουν περισσότερα στοιχεία με σκιά — ομαδοποιήστε τα σε ομάδες με ίδιο ύψος. Ο υπερβολικός αριθμός σκιών δημιουργεί οπτικό θόρυβο και μειώνει την απόδοση σε συσκευές μεσαίου και οικονομικού τμήματος.

Σύνοψη

  • Σκιά (shadow) — ένα οπτικό εφέ βάθους βάσει του elevation του στοιχείου στη Z-συντεταγμένη.
  • Στο iOS οι σκιές διαμορφώνονται μέσω CALayer: shadowColor, shadowOffset, shadowRadius, shadowOpacity.
  • Στο Android οι σκιές διαχειρίζονται μέσω elevation και OutlineProvider για προσαρμοσμένο σχήμα.
  • Το Material Design ορίζει πέντε επίπεδα elevation: 0, 1–4, 6–12, 16–24 και 24+ dp.
  • Jetpack Compose χρησιμοποιεί Modifier.shadow() και elevation σε Card/Surface για διαχείριση σκιών.
  • Το Flutter υλοποιεί σκιές μέσω BoxShadow (BoxDecoration) και PhysicalModel (φυσική σκιά).
  • Βελτιστοποίηση: ορίστε shadowPath (iOS), outlineProvider (Android), χρησιμοποιήστε PhysicalModel (Flutter).

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης