Pull-to-Refresh: asoslar, RefreshControl va UIRefreshControl

Muallif: IT Sectr Nashr etilgan: 2026-02-27 O'qish vaqti: 8 daq
Pull-to-Refresh — mobil interfeys namunasi bo'lib, unda foydalanuvchi ro'yxatni barmog'i bilan pastga tortadi va yangi ma'lumotlarning yuklanishini boshlaydi. Imo-ishora vizual indikator — aylanadigan spinner yoki animatsiyalangan ikonka — bilan birga keladi va yuklash tugagandan so'ng yo'qoladi. Apple HIG UX tahliliga ko'ra, Pull-to-Refresh Tweetie (2008) da joriy etilishi va Apple va Google tomonidan standartlashtirilishidan so'ng yangiliklar lentalari, ijtimoiy tarmoqlar va pochta mijozlarida kontent yangilashning standart mexanizmiga aylandi.

Asosiy fikrlar

  • Pull-to-Refresh — ma'lumotlarni yangilash uchun ro'yxatni pastga tortish imo-ishorasi, yuklash vizual indikatori bilan birga.
  • iOS da UIRefreshControl (iOS 6+) ishlatiladi, UITableViewController yoki UIScrollView ga refreshControl xususiyati orqali qo'shiladi.
  • Android da SwipeRefreshLayout (Support Library dan) ishlatiladi — RecyclerView yoki NestedScrollView uchun ViewGroup o'rami.
  • Ikkala API ranglar, indikatorlar va qayta chaqiruvlarni listener orqali sozlashni qo'llab-quvvatlaydi (iOS: UIRefreshControl.target-action, Android: setOnRefreshListener).
  • Pull-to-Refresh ro'yxat yuqori holatda bo'lmaganda avtomatik bloklanadi — aylantirish bilan ziddiyat arxitektura bo'yicha istisno qilingan.

Pull-to-Refresh nima?

Pull-to-Refresh — foydalanuvchi kontentni yangilash uchun ro'yxat yoki aylanadigan maydonni pastga tortadigan foydalanuvchi interfeysi namunasidir. Vizual ravishda imo-ishora ekranning yuqori qismida paydo bo'ladigan va ma'lumot olingandan so'ng yo'qoladigan yuklash indikatori (spinner) bilan birga keladi. Ushbu namuna iPhone uchun Tweetie ilovasi (2008) tomonidan ommalashtirilgan va keyinchalik Apple (iOS 6 — UIRefreshControl) va Google (Android Support Library — SwipeRefreshLayout) tomonidan standartlashtirilgan.

Texnik nuqtai nazardan, Pull-to-Refresh panlash (barmoq siljishini kuzatish) va chegaraga yetganda trigger kombinatsiyasidir. Foydalanuvchi ro'yxatni pastga tortadi, qarshilikni (rezistiv overscroll) yengadi va chegaradan o'tgandan so'ng (~80px iOS da, ~64dp Android da) indikator animatsiyasi va asinxron yuklash boshlanadi. Agar foydalanuvchi barmog'ini chegaradan oldin qo'yib yuborsa — ro'yxat yangilanmasdan boshlang'ich holatga qaytadi.

Material Design Guidelines ga ko'ra, Pull-to-Refresh ishlatilmasligi kerak navigatsiya yoki varaqlarni almashtirish uchun — uning yagona maqsadi ma'lumotlarni yangilashdir. IT Sectr da biz Pull-to-Refresh ni yangiliklar lentalari, buyurtma ro'yxatlari va chatlarda qo'llaymiz, bu yerda ma'lumotlarning yangiligi foydalanuvchi tajribasi uchun muhimdir.

iOS da Pull-to-Refresh: UIRefreshControl

UIRefreshControl — iOS 6 dan boshlab mavjud bo'lgan Pull-to-Refresh uchun standart iOS boshqaruv elementidir. UIRefreshControl UITableViewController ga refreshControl xususiyati (iOS 10+) yoki eski versiyalarda jadvalning subview i sifatida qo'shiladi. U sozlanishi mumkin bo'lgan rang (tintColor), title atributi va yorliqli atributlashtirilgan satr (masalan, “Yangilanmoqda...”) bilan o'rnatilgan spinnerni o'z ichiga oladi.

UIRefreshControl target-action mexanizmi orqali ishlaydi: imo-ishora faollashtirilganda ko'rsatilgan metod (masalan, refresh(_:)) chaqiriladi. Metod ichida asinxron ma'lumot yuklash amalga oshiriladi. Tugatgandan so'ng endRefreshing() chaqiriladi, indikatorni animatsiya bilan yashiradi. UIRefreshControl imo-ishora sezgirligini avtomatik boshqaradi — faqat jadvalning yuqori holatida (contentOffset.y <= 0) ishga tushadi.

tintColor xususiyati spinner rangini o'rnatadi. title atributlari tugagandan so'ng “2 daqiqa oldin yangilandi” matnini ko'rsatishga imkon beradi. iOS 10 dan boshlab, UIRefreshControl UIActivityIndicatorView yoki doimiy maxsus ko'rinishlar orqali maxsus animatsiyalarni qo'llab-quvvatlaydi. IT Sectr da biz tintColor ni brendga moslashtiramiz va attributedTitle orqali oxirgi yangilanish vaqtini ko'rsatamiz — bu foydalanuvchilarning ma'lumotlarga ishonchini oshiradi.

Android da Pull-to-Refresh: SwipeRefreshLayout

SwipeRefreshLayout — Android Support Library dan (androidx.swiperefreshlayout) ViewGroup bo'lib, aylanadigan kontentni (RecyclerView, NestedScrollView, ListView) o'rab oladi va Pull-to-Refresh funksionalligini qo'shadi. UIRefreshControl dan farqli o'laroq (boshqaruv elementi, konteyner emas), SwipeRefreshLayout bolaning teginish hodisalarini tutib oladigan va chegaradan o'tganda yangilanish indikatorini ishga tushiradigan konteynerdir.

SwipeRefreshLayout setColorSchemeColors() orqali rang sozlash bilan Material Design aylana progress indikatoridan foydalanadi. setOnRefreshListener metodi asinxron yuklash amalga oshiriladigan onRefresh() qayta chaqiruvini o'rnatadi. Tugatgandan so'ng indikatorni yashirish uchun setRefreshing(false) chaqiriladi. Muhim: setRefreshing(true) onRefresh() ni qayta chaqiradi — shuning uchun dasturiy yangilashni boshlash uchun flag yoki post metoddan foydalaning.

setProgressBackgroundColorSchemeResource xususiyati indikator fonini o'zgartiradi. setSize(SwipeRefreshLayout.LARGE) — spinner o'lchami. XML layout da SwipeRefreshLayout RecyclerView ni o'rab oladi: swipe_refresh_layout → recycler_view. Google I/O 2024 ga ko'ra, SwipeRefreshLayout kontent lentalari bo'lgan Android ilovalarining 85% ida ishlatiladi. IT Sectr da biz asinxron yuklanadigan ro'yxatlari bo'lgan barcha ekranlarni SwipeRefreshLayout bilan o'raymiz — bu Android ning barcha versiyalarida yagona UX ni ta'minlaydi.

Material Pull-to-Refresh (Android 12+)

Android 12 (Material You) dan boshlab, Google material-1.6.0+ kutubxonasidan (Compose uchun androidx.compose.material3.pulltorefresh) yangi Material Pull-to-Refresh dan foydalanishni tavsiya qiladi. Yangi API spring animatsiyasi va devor qog'ozi asosida adaptiv rang qo'llab-quvvatlashi bilan animatsiyalangan indikatordan foydalanadi. SwipeRefreshLayout Android 12 dan past versiyalar uchun mos keladi.

Eng yaxshi amaliyotlar va keng tarqalgan xatolar

Pull-to-Refresh — amalga oshirish oson bo'lgan namuna, ammo UX ni pasaytiradigan bir nechta odatiy xatolarni o'z ichiga oladi. Keling, ularni va oldini olish usullarini ko'rib chiqaylik.

  • Ikki marta yangilash — foydalanuvchi yuklash tugashidan oldin ro'yxatni bir necha marta tortishi mumkin. Yechim: boshida isRefreshing flag ini o'rnating va onRefresh() da tekshiring. iOS da endRefreshing() faqat tugagandan so'ng chaqiriladi; UIRefreshControl da imo-ishora blokadasi o'rnatilgan.
  • Teskari aloqaning yo'qligi — yuklash indikatori foydalanuvchi chegaradan o'tgandan keyingina paydo bo'lishi kerak. Tegish paytida darhol indikatorni ko'rsatmang — bu chalkashtiradi. iOS va Android buni avtomatik qiladi.
  • Yangilanish vaqtini e'tiborsiz qoldirish — agar ma'lumotlar 200 ms da yangilansa, indikator kamida 500 ms ko'rinishi kerak, shunda foydalanuvchi yangilanishni sezadi. UIRefreshControl minimal animatsiya vaqtiga ega; Android da minimal ko'rinish vaqti uchun Handler.postDelayed dan foydalaning.
  • Klaviatura bilan ziddiyat — ochiq klaviatura bilan Pull-to-Refresh tasodifan ishga tushishi mumkin. Imo-ishora boshida iOS da view.endEditing(true) va Android da InputMethodManager.hideSoftInputFromWindow() orqali klaviaturam yashiring.
  • Yangilash uchun emas, navigatsiya uchun ishlatish — Pull-to-Refresh ni navigatsiya (varaqlarni almashtirish, orqaga qaytish) uchun ishlatmang. Bu ikkala platformaning HIG ini buzadi va foydalanuvchilarni chalg'itadi.

IT Sectr da biz test serverining loglarida takrorlanuvchi so'rovlarni aniqlaganimizdan so'ng har bir loyihada isRefreshing tekshiruvini qo'shdik — ma'lum bo'lishicha, tez barmoqli foydalanuvchilar yangilanishni ketma-ket 3 martagacha ishga tushirgan.

Swift va Kotlin da kod misollari

Misol 1: iOS da UIRefreshControl (Swift)

UITableViewController ga maxsus spinner rangi va attributed title bilan Pull-to-Refresh qo'shadi. Ma'lumot yuklangandan so'ng indikator yashiriladi.

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: “Yangilash uchun torting”
        )
        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 xususiyati (iOS 10+) UIRefreshControl ni o'rnatadi. .valueChanged hodisasi bilan addTarget imo-ishora faollashganda ishga tushadi. endRefreshing() majburiy — usiz indikator cheksiz aylanadi. Asinxron yuklash DispatchQueue.main.asyncAfter bilan simulyatsiya qilinadi — haqiqiy loyihada URLSession yoki async/await bo'ladi.

Misol 2: Android da SwipeRefreshLayout (Kotlin)

RecyclerView ni maxsus indikator ranglari bilan SwipeRefreshLayout da o'rab oladi. onRefresh yuklashni boshlaydi va tugagandan so'ng indikatorni yashiradi.

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 aylanma indikatorining ranglarini o'rnatadi. isRefreshing = false majburiy ravishda finally da chaqiriladi, shunda yuklash xatosi bo'lganda ham indikator yashiriladi. ViewModelScope.launch fragmentning hayot aylanishida korutinni bajaradi — fragment yo'q qilinganda korutin avtomatik bekor qilinadi, xotira oqishining oldini oladi.

Misol 3: SwiftUI .refreshable (iOS 15+)

Zamonaviy SwiftUI List yoki ScrollView ga avtomatik Pull-to-Refresh qo'shadigan .refreshable modifikatorini taqdim etadi.

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 modifikatori Pull-to-Refresh vaqtida bajariladigan async-closure ni qabul qiladi. SwiftUI avtomatik ravishda yangilash indikatorini ko'rsatadi va yashiradi, holat poygasini boshqaradi (joriy yuklash tugamaguncha qayta yuklashni boshlamaydi) va animatsiyani platformaga moslashtiradi. iOS 15+ uchun bu SwiftUI da Pull-to-Refresh ni amalga oshirishning preferred usulidir.

Tez-tez beriladigan savollar

Pull-to-Refresh SwiftUI da ishlaydimi?

Ha, SwiftUI iOS 15 dan boshlab List yoki ScrollView uchun .refreshable modifikatorini taqdim etadi. Closure ichida ma'lumot yuklashning async kodi bajariladi. SwiftUI avtomatik yangilash indikatorini boshqaradi va joriy yuklash tugamaguncha qayta ishga tushirishlarni bloklaydi — bu yangi loyihalar uchun standart recommended yondashuvdir.

Ikki marta yangilashni qanday oldini olish mumkin?

isRefreshing flagidan foydalaning: yuklash boshida true va tugagandan so'ng false o'rnating. iOS da UIRefreshControl endRefreshing() chaqirilmaguncha qayta chaqiruvni avtomatik bloklaydi. Android da onRefresh() boshida SwipeRefreshLayout.isRefreshing ni tekshiring: true bo'lsa — return. Bu bir imo-ishora uchun bitta so'rovni kafolatlaydi.

Pull-to-Refresh ro'yxatni aylantirish bilan ziddiyat qiladimi?

UIRefreshControl va SwipeRefreshLayout faqat ro'yxatning yuqori holatida (contentOffset == 0) ishga tushadi. Arxitektura ziddiyatni istisno qiladi: ro'yxat hatto 1px aylantirilgan bo'lsa ham, Pull-to-Refresh imo-ishorasi faollashmaydi. Agar ziddiyat yuzaga kelsa — Android da nestedScrollingEnabled ni yoki teginishlarni tutib oladigan maxsus GestureRecognizer larni tekshiring.

Xulosa

  • Pull-to-Refresh — barcha mobil platformalarda Apple va Google tomonidan standartlashtirilgan ro'yxatni pastga tortib ma'lumot yangilash namunasidir.
  • iOS da UIRefreshControl — target-action, tintColor, attributedTitle va majburiy endRefreshing() bilan boshqaruv elementi.
  • Android da SwipeRefreshLayout — setOnRefreshListener, setColorSchemeColors va isRefreshing bilan ViewGroup konteyneri.
  • Material Pull-to-Refresh (Android 12+) — spring animatsiyasi bilan yangi API, yangi loyihalar uchun tavsiya etiladi.
  • SwiftUI .refreshable — iOS 15 dan boshlab deklarativ modifikator.
  • isRefreshing flagi ikki marta yangilashning oldini oladi — ikkala platformada majburiy.
  • Pull-to-Refresh navigatsiya uchun mo'ljallanmagan — faqat Material Design va Apple HIG ga muvofiq kontent yangilash uchun.

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing