Pull-to-Refresh: əsaslar, RefreshControl və UIRefreshControl

Müəllif: IT Sectr Dərc olunub: 2026-02-27 Oxuma vaxtı: 8 dəq
Pull-to-Refresh — istifadəçinin barmağı ilə siyahını aşağı çəkərək təzə məlumatların yüklənməsini başlatdığı mobil interfeys nümunəsidir. Jest vizual göstərici — fırlanan spinner və ya animasiya edilmiş ikonka — ilə müşayiət olunur, yükləmə tamamlandıqdan sonra yox olur. Apple HIG UX təhlilinə görə, Pull-to-Refresh Tweetie (2008) tətbiqində tətbiq edilməsindən və Apple və Google tərəfindən standartlaşdırılmasından sonra xəbər lentlərində, sosial şəbəkələrdə və poçt müştərilərində məzmun yeniləmənin standart mexanizminə çevrilib.

Əsas məqamlar

  • Pull-to-Refresh — məlumatları yeniləmək üçün siyahını aşağı çəkmə jesti, yükləmə vizual göstəricisi ilə müşayiət olunur.
  • iOS-da UIRefreshControl (iOS 6+) istifadə olunur, UITableViewController və ya UIScrollView-ə refreshControl xüsusiyyəti ilə əlavə edilir.
  • Android-də SwipeRefreshLayout (Support Library-dən) istifadə olunur — RecyclerView və ya NestedScrollView üçün ViewGroup qablaşdırması.
  • Hər iki API rənglərin, göstəricilərin və geri çağırışların listener vasitəsilə fərdiləşdirilməsini dəstəkləyir (iOS: UIRefreshControl.target-action, Android: setOnRefreshListener).
  • Pull-to-Refresh siyahı yuxarı vəziyyətdə olmadıqda avtomatik bloklanır — sürüşdürmə ilə konflikt memarlıqca istisna edilib.

Pull-to-Refresh nədir?

Pull-to-Refresh — istifadəçinin məzmunu yeniləmək üçün siyahını və ya sürüşdürülən sahəni aşağı çəkdiyi istifadəçi interfeysi nümunəsidir. Vizual olaraq jest ekranın yuxarı hissəsində görünən və məlumat alındıqdan sonra yox olan yükləmə göstəricisi (spinner) ilə müşayiət olunur. Bu nümunə iPhone üçün Tweetie tətbiqi (2008) tərəfindən populyarlaşdırılıb və sonradan Apple (iOS 6 — UIRefreshControl) və Google (Android Support Library — SwipeRefreshLayout) tərəfindən standartlaşdırılıb.

Texniki baxımdan Pull-to-Refresh panlama (barmaq yerdəyişməsini izləmə) və həddə çatdıqda trigger-in kombinasiyasıdır. İstifadəçi siyahını aşağı çəkir, müqaviməti (rezistiv overscroll) aşır və həddi keçdikdən sonra (~80px iOS-da, ~64dp Android-də) göstərici animasiyası və asinxron yükləmə başlayır. İstifadəçi barmağını həddən əvvəl buraxarsa — siyahı yeniləmədən ilkin vəziyyətə qayıdır.

Material Design Guidelines-ə görə, Pull-to-Refresh istifadə edilməməlidir naviqasiya və ya tab dəyişdirmək üçün — onun yeganə məqsədi məlumat yeniləməkdir. IT Sectr-də biz Pull-to-Refresh-i xəbər lentlərində, sifariş siyahılarında və çatlarda tətbiq edirik, burada məlumatların təzəliyi istifadəçi təcrübəsi üçün vacibdir.

iOS-da Pull-to-Refresh: UIRefreshControl

UIRefreshControl — iOS 6-dan etibarən mövcud olan Pull-to-Refresh üçün standart iOS idarəetmə elementidir. UIRefreshControl UITableViewController-ə refreshControl xüsusiyyəti (iOS 10+) və ya daha köhnə versiyalarda cədvəlin subview-i kimi əlavə edilir. O, konfiqurasiya oluna bilən rəng (tintColor), title atributu və etiketli atributlaşdırılmış sətir (məsələn, “Yenilənir...”) olan daxili spinner ehtiva edir.

UIRefreshControl target-action mexanizmi ilə işləyir: jest aktivləşdirildikdə göstərilən metod (məsələn, refresh(_:)) çağırılır. Metod daxilində asinxron məlumat yükləmə aparılır. Tamamlandıqdan sonra endRefreshing() çağırılır, göstəricini animasiya ilə gizlədir. UIRefreshControl jest həssaslığını avtomatik idarə edir — yalnız cədvəlin yuxarı vəziyyətində (contentOffset.y <= 0) işə düşür.

tintColor xüsusiyyəti spinner-in rəngini təyin edir. title atributları tamamlandıqdan sonra “2 dəqiqə əvvəl yeniləndi” mətnini göstərməyə imkan verir. iOS 10-dan başlayaraq, UIRefreshControl UIActivityIndicatorView və ya davamlı fərdi görünüşlər vasitəsilə fərdi animasiyaları dəstəkləyir. IT Sectr-də biz tintColor-ı brendə uyğunlaşdırır və attributedTitle vasitəsilə son yeniləmə vaxtını göstəririk — bu istifadəçilərin məlumatlara inamını artırır.

Android-də Pull-to-Refresh: SwipeRefreshLayout

SwipeRefreshLayout — Android Support Library-dən (androidx.swiperefreshlayout) ViewGroup, sürüşdürülən məzmunu (RecyclerView, NestedScrollView, ListView) əhatə edən və Pull-to-Refresh funksionallığı əlavə edən. UIRefreshControl-dən fərqli olaraq (idarəetmə elementi, konteyner deyil), SwipeRefreshLayout uşağın toxunma hadisələrini tutan və həddi aşdıqda yeniləmə göstəricisini işə salan konteynerdir.

SwipeRefreshLayout setColorSchemeColors() ilə rəng konfiqurasiyası olan Material Design dairəvi gedişat göstəricisindən istifadə edir. setOnRefreshListener metodu asinxron yükləmənin aparıldığı onRefresh() geri çağırışını təyin edir. Tamamlandıqdan sonra göstəricini gizlətmək üçün setRefreshing(false) çağırılır. Vacib: setRefreshing(true) onRefresh()-i təkrar çağırır — buna görə proqram vasitəsilə yeniləməni başlatmaq üçün flag və ya post-metodundan istifadə edin.

setProgressBackgroundColorSchemeResource xüsusiyyəti göstəricinin fonunu dəyişir. setSize(SwipeRefreshLayout.LARGE) — spinner ölçüsü. XML layout-da SwipeRefreshLayout RecyclerView-i əhatə edir: swipe_refresh_layout → recycler_view. Google I/O 2024-ə görə, SwipeRefreshLayout məzmun lentləri olan Android tətbiqlərinin 85%-də istifadə olunur. IT Sectr-də biz asinxron yüklənən siyahıları olan bütün ekranları SwipeRefreshLayout ilə əhatə edirik — bu Android-in bütün versiyalarında vahid UX təmin edir.

Material Pull-to-Refresh (Android 12+)

Android 12-dən (Material You) başlayaraq, Google material-1.6.0+ kitabxanasından (Compose üçün androidx.compose.material3.pulltorefresh) yeni Material Pull-to-Refresh istifadə etməyi tövsiyə edir. Yeni API spring-animasiyası və divar kağızı əsasında adaptiv rəng dəstəyi olan animasiyalı göstəricidən istifadə edir. SwipeRefreshLayout Android 12-dən aşağı versiyalar üçün uyğun qalır.

Ən yaxşı təcrübələr və ümumi səhvlər

Pull-to-Refresh — tətbiqi asan nümunədir, lakin UX-i azaldan bir neçə ümumi səhv ehtiva edir. Onları və qarşısını alma yollarını nəzərdən keçirək.

  • İkiqat yeniləmə — istifadəçi yükləmə tamamlanmadan siyahını bir neçə dəfə çəkə bilər. Həll: başlanğıcda isRefreshing flag-ını təyin edin və onRefresh()-də yoxlayın. iOS-da endRefreshing() yalnız tamamlandıqdan sonra çağırılır; UIRefreshControl-də jest blokadası daxilidir.
  • Geri bildirimin olmaması — yükləmə göstəricisi yalnız istifadəçi həddi keçdikdən sonra görünməlidir. Toxunma zamanı dərhal göstəricini göstərməyin — bu çaşdırıcıdır. iOS və Android bunu avtomatik edir.
  • Yeniləmə vaxtının nəzərə alınmaması — məlumat 200 ms-də yenilənirsə, göstərici ən azı 500 ms görünməlidir ki, istifadəçi yeniləməni görsün. UIRefreshControl minimum animasiya müddətinə malikdir; Android-də minimum göstərmə müddəti üçün Handler.postDelayed istifadə edin.
  • Klaviatura ilə konflikt — açıq klaviatura olduqda Pull-to-Refresh təsadüfən işə düşə bilər. Jest başlanğıcında iOS-da view.endEditing(true) və Android-də InputMethodManager.hideSoftInputFromWindow() ilə klaviaturanı gizlədin.
  • Yeniləmə üçün deyil, naviqasiya üçün istifadə — Pull-to-Refresh-i naviqasiya (tab dəyişdirmə, geri qayıtma) üçün istifadə etməyin. Bu hər iki platformanın HIG-ni pozur və istifadəçiləri çaşdırır.

IT Sectr-də biz test serverinin loglarında təkrarlanan sorğuları aşkar etdikdən sonra hər layihədə isRefreshing yoxlamasını əlavə etdik — məlum oldu ki, sürətli barmaqları olan istifadəçilər yeniləməni ardıcıl 3 dəfəyə qədər işə salırdılar.

Swift və Kotlin-də kod nümunələri

Nümunə 1: iOS-da UIRefreshControl (Swift)

UITableViewController-ə fərdi spinner rəngi və attributed title ilə Pull-to-Refresh əlavə edir. Məlumat yükləndikdən sonra göstərici gizlənir.

swift
import UIKit

class FeedTableViewController: UITableViewController {

    private var items: [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.refreshControl = UIRefreshControl()
        refreshControl?.tintColor = .systemBlue
        refreshControl?.attributedTitle = NSAttributedString(
            string: “Yeniləmək üçön çəkin”
        )
        refreshControl?.addTarget(
            self,
            action: #selector(refreshData),
            for: .valueChanged
        )
    }

    @objc private func refreshData() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
            self.items = FeedService().fetchLatest()
            self.tableView.reloadData()
            self.refreshControl?.endRefreshing()
        }
    }
}

tableView.refreshControl xüsusiyyəti (iOS 10+) UIRefreshControl-ü təyin edir. .valueChanged hadisəsi ilə addTarget jest aktivləşdirildikdə işə düşür. endRefreshing() məcburidir — onsuz göstərici sonsuz fırlanacaq. Asinxron yükləmə DispatchQueue.main.asyncAfter ilə simulyasiya olunur — real layihədə URLSession və ya async/await olardı.

Nümunə 2: Android-də SwipeRefreshLayout (Kotlin)

RecyclerView-i fərdi göstərici rəngləri ilə SwipeRefreshLayout-da əhatə edir. onRefresh yükləməni başladır və tamamlandıqdan sonra göstəricini gizlədir.

kotlin
class FeedFragment : Fragment() {

    private var _binding: FragmentFeedBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentFeedBinding.inflate(inflater, container, false)

        binding.swipeRefreshLayout.setColorSchemeColors(
            resources.getColor(R.color.brand_blue, null),
            resources.getColor(R.color.brand_green, null)
        )
        binding.swipeRefreshLayout.setOnRefreshListener {
            loadData()
        }
        return binding.root
    }

    private fun loadData() {
        viewModelScope.launch {
            try {
                val result = repository.getLatestFeed()
                adapter.submitList(result)
            } finally {
                binding.swipeRefreshLayout.isRefreshing = false
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

setColorSchemeColors Material Design fırlanan göstəricisinin rənglərini təyin edir. isRefreshing = false mütləq finally-də çağrılır ki, yükləmə xətası zamanı belə göstərici gizlənsin. ViewModelScope.launch fragment-in həyat dövründə korutini icra edir — fragment məhv olduqda korutin avtomatik ləğv olunur, yaddaş sızmasının qarşısını alır.

Nümunə 3: SwiftUI .refreshable (iOS 15+)

Müasir SwiftUI List və ya ScrollView-ə avtomatik Pull-to-Refresh əlavə edən .refreshable modifikatorunu təqdim edir.

swift
import SwiftUI

struct FeedView: View {

    @State private var items: [String] = []

    var body: some View {
        List(items, id: \.self) { item in
            Text(item)
        }
        .refreshable {
            items = await FeedService().fetchLatestAsync()
        }
    }
}

.refreshable modifikatoru Pull-to-Refresh zamanı icra olunan async-closure qəbul edir. SwiftUI avtomatik olaraq yeniləmə göstəricisini göstərir və gizlədir, vəziyyət yarışını idarə edir (cari yükləmə tamamlanana qədər təkrar yükləməni başlatmır) və animasiyanı platformaya uyğunlaşdırır. iOS 15+ üçün bu, SwiftUI-də Pull-to-Refresh-in preferred üsuludur.

Tez-tez verilən suallar

Pull-to-Refresh SwiftUI-də işləyir?

Bəli, SwiftUI iOS 15-dən etibarən List və ya ScrollView üçün .refreshable modifikatorunu təqdim edir. Closure daxilində məlumat yükləmənin async-kodu icra olunur. SwiftUI avtomatik yeniləmə göstəricisini idarə edir və cari yükləmə tamamlanana qədər təkrar başlatmaları bloklayır — bu yeni layihələr üçün standart recommended yanaşmadır.

İkiqat yeniləmənin qarşısını necə almaq olar?

isRefreshing flag-ından istifadə edin: yükləmə başlanğıcında true, tamamlandıqdan sonra false təyin edin. iOS-da UIRefreshControl endRefreshing() çağrılana qədər təkrar çağırışı avtomatik bloklayır. Android-də onRefresh()-in əvvəlində SwipeRefreshLayout.isRefreshing yoxlayın: true olarsa — return. Bu, bir jest üçün bir sorğu təmin edir.

Pull-to-Refresh siyahının sürüşdürülməsi ilə konflikt edir?

UIRefreshControl və SwipeRefreshLayout yalnız siyahının yuxarı vəziyyətində (contentOffset == 0) işə düşür. Arxitektura konflikti istisna edir: siyahı hətta 1px sürüşdürüldükdə belə Pull-to-Refresh jesti aktivləşmir. Konflikt yaranarsa — Android-də nestedScrollingEnabled və ya toxunuşları tutan fərdi GestureRecognizer-ləri yoxlayın.

Nəticə

  • Pull-to-Refresh — bütün mobil platformalarda Apple və Google tərəfindən standartlaşdırılmış siyahını aşağı çəkərək məlumat yeniləmə nümunəsidir.
  • iOS-da UIRefreshControl — target-action, tintColor, attributedTitle və məcburi endRefreshing() ilə idarəetmə elementi.
  • Android-də SwipeRefreshLayout — setOnRefreshListener, setColorSchemeColors və isRefreshing ilə ViewGroup konteyneri.
  • Material Pull-to-Refresh (Android 12+) — spring-animasiyası ilə yeni API, yeni layihələr üçün tövsiyə olunur.
  • SwiftUI .refreshable — iOS 15-dən etibarən deklarativ modifikator.
  • isRefreshing flag-ı ikiqat yeniləmənin qarşısını alır — hər iki platformada məcburidir.
  • Pull-to-Refresh naviqasiya üçün nəzərdə tutulmayıb — yalnız Material Design və Apple HIG-ə uyğun məzmun yeniləmə üçündür.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun