Pull-to-Refresh: মৌলিক বিষয়, RefreshControl এবং UIRefreshControl

লেখক: IT Sectr প্রকাশিত: 2026-02-27 পড়ার সময়: 8 মিনিট
Pull-to-Refresh একটি মোবাইল ইন্টারফেস প্যাটার্ন যেখানে ব্যবহারকারী আঙুল দিয়ে তালিকা নিচে টানে, নতুন ডেটা লোড শুরু করে। অঙ্গভঙ্গিটি একটি ভিজ্যুয়াল নির্দেশক — ঘূর্ণায়মান স্পিনার বা অ্যানিমেটেড আইকন — দ্বারা \u09b8\u0999\u09cd\u0997\u09c7 হয়, যা লোডিং শেষ হলে অদৃশ্য হয়ে যায়। Apple HIG UX বিশ্লেষণ অনুসারে, Pull-to-Refresh Tweetie (2008) এ প্রবর্তন এবং Apple ও Google দ্বারা পরবর্তী মান নির্ধারণের পর থেকে নিউজ ফিড, সোশ্যাল নেটওয়ার্ক এবং ইমেল ক্লায়েন্টে কন্টেন্ট রিফ্রেশের আদর্শ প্রক্রিয়া হয়ে উঠেছে।

মূল পয়েন্ট

  • Pull-to-Refresh হল একটি ভিজ্যুয়াল লোডিং নির্দেশক সহ ডেটা রিফ্রেশ করতে তালিকা নিচে টানার অঙ্গভঙ্গি।
  • iOS এ UIRefreshControl (iOS 6+) ব্যবহার করা হয়, যা refreshControl প্রপার্টির মাধ্যমে UITableViewController বা UIScrollView এ যোগ করা হয়।
  • Android এ SwipeRefreshLayout (Support Library থেকে) ব্যবহার করা হয় — RecyclerView বা NestedScrollView এর জন্য একটি ViewGroup র‍্যাপার।
  • উভয় API লিসেনারের মাধ্যমে রঙ, নির্দেশক এবং কলব্যাক কাস্টমাইজেশন সমর্থন করে (iOS: UIRefreshControl.target-action, Android: setOnRefreshListener)।
  • যখন তালিকা উপরের অবস্থানে না থাকে তখন Pull-to-Refresh স্বয়ংক্রিয়ভাবে ব্লক হয়ে যায় — স্ক্রোল করার সাথে দ্বন্দ্ব আর্কিটেকচারালি বাদ দেওয়া হয়েছে।

Pull-to-Refresh কী?

Pull-to-Refresh একটি ইউজার ইন্টারফেস প্যাটার্ন যেখানে ব্যবহারকারী কন্টেন্ট রিফ্রesh করতে একটি তালিকা বা স্ক্রোলযোগ্য এলাকা নিচে টানে (pull down)। দৃশ্যত, অঙ্গভঙ্গিটি একটি লোডিং নির্দেশক (স্পিনার) সহ আসে যা স্ক্রিনের শীর্ষে দেখা যায় এবং ডেটা প্রাপ্তির পরে অদৃশ্য হয়ে যায়। প্যাটার্নটি iPhone এর জন্য Tweetie অ্যাপ (2008) দ্বারা জনপ্রিয় হয়েছিল এবং পরবর্তীতে Apple (iOS 6 — UIRefreshControl) এবং Google (Android Support Library — SwipeRefreshLayout) দ্বারা মান নির্ধারণ করা হয়েছিল।

প্রযুক্তিগত দৃষ্টিকোণ থেকে, Pull-to-Refresh হল প্যানিং (আঙুলের স্থানচ্যুতি ট্র্যাক করা) এবং একটি থ্রেশহোল্ডে পৌঁছালে ট্রিগারের সংমিশ্রণ। ব্যবহারকারী প্রতিরোধ (প্রতিরোধী ওভারস্ক্রোল) অতিক্রম করে তালিকা নিচে টানে এবং থ্রেশহোল্ড (~80px iOS এ, ~64dp Android এ) অতিক্রম করার পরে নির্দেশকের অ্যানিমেশন এবং অ্যাসিঙ্ক্রোনাস লোডিং শুরু হয়। যদি ব্যবহারকারী থ্রেশহোল্ডের আগে আঙুল ছেড়ে দেয়, তাহলে তালিকা রিফ্রesh না করেই তার মূল অবস্থানে ফিরে আসে।

Material Design Guidelines অনুসারে, Pull-to-Refresh ন্যাভিগেশন বা ট্যাব পরিবর্তনের জন্য ব্যবহার করা উচিত নয় — এর একমাত্র উদ্দেশ্য ডেটা রিফ্রesh। IT Sectr এ, আমরা নিউজ ফিড, অর্ডার ফিড এবং চ্যাটে Pull-to-Refresh ব্যবহার করি যেখানে ডেটার সতেজতা ব্যবহারকারীর অভিজ্ঞতার জন্য গুরুত্বপূর্ণ।

iOS এ Pull-to-Refresh: UIRefreshControl

UIRefreshControl Pull-to-Refresh এর জন্য মানক iOS নিয়ন্ত্রণ, যা iOS 6 থেকে উপলব্ধ। UIRefreshControl refreshControl প্রপার্টি (iOS 10+) এর মাধ্যমে UITableViewController এ বা পুরনো সংস্করণে টেবিলের সাবভিউ হিসাবে যোগ করা হয়। এতে কাস্টমাইজযোগ্য রঙ (tintColor), title অ্যাট্রিবিউট এবং একটি লেবেল সহ অ্যাট্রিবিউটেড স্ট্রিং (যেমন "আপডেট হচ্ছে...") সহ একটি বিল্ট-ইন স্পিনার রয়েছে।

UIRefreshControl target-action মেকানিজমের মাধ্যমে কাজ করে: যখন অঙ্গভঙ্গি সক্রিয় হয়, নির্দিষ্ট মেথড কল করা হয় (যেমন refresh(_:))। মেথডের ভিতরে, অ্যাসিঙ্ক্রোনাস ডেটা লোডিং করা হয়। শেষ হলে, অ্যানিমেশন সহ নির্দেশক লুকানোর জন্য endRefreshing() কল করা হয়। UIRefreshControl স্বয়ংক্রিয়ভাবে অঙ্গভঙ্গির সংবেদনশীলতা পরিচালনা করে — এটি কেবল তখনই ট্রিগার হয় যখন টেবিল উপরের অবস্থানে থাকে (contentOffset.y <= 0)।

tintColor প্রপার্টি স্পিনারের রঙ সেট করে। attributedTitle শেষ হওয়ার পরে "২ মিনিট আগে আপডেট করা হয়েছে" এর মতো টেক্সট দেখাতে দেয়। iOS 10 থেকে, UIRefreshControl UIActivityIndicatorView বা স্থায়ী কাস্টম ভিউ এর মাধ্যমে কাস্টম অ্যানিমেশন সমর্থন করে। IT Sectr এ, আমরা ব্র্যান্ড অনুযায়ী tintColor কনফিগার করি এবং attributedTitle এর মাধ্যমে শেষ আপডেটের সময় দেখাই — এটি ব্যবহারকারীদের ডেটার উপর আস্থা বাড়ায়।

Android এ Pull-to-Refresh: SwipeRefreshLayout

SwipeRefreshLayout Android Support Library (androidx.swiperefreshlayout) থেকে একটি ViewGroup যা স্ক্রোলযোগ্য কন্টেন্ট (RecyclerView, NestedScrollView, ListView) র‍্যাপ করে এবং Pull-to-Refresh কার্যকারিতা যোগ করে। UIRefreshControl (যা একটি নিয়ন্ত্রণ, কন্টেইনার নয়) এর বিপরীতে, SwipeRefreshLayout একটি কন্টেইনার যা চাইল্ডের টাচ ইভেন্ট ইন্টারসেপ্ট করে এবং থ্রেশহোল্ড অতিক্রম করলে রিফ্রesh নির্দেশক ট্রিগার করে।

SwipeRefreshLayout setColorSchemeColors() এর মাধ্যমে রঙ কাস্টমাইজেশন সহ একটি বৃত্তাকার Material Design প্রগতি নির্দেশক ব্যবহার করে। setOnRefreshListener মেথড onRefresh() কলব্যack সেট করে, যাতে অ্যাসিঙ্ক্রোনাস লোডিং করা হয়। শেষ হওয়ার পরে, নির্দেশক লুকানোর জন্য setRefreshing(false) কল করা হয়। গুরুত্বপূর্ণ: setRefreshing(true) আবার onRefresh() কল করে — তাই প্রোগ্রাম্যাটিকভাবে রিফ্রesh শুরু করতে, একটি ফ্ল্যাগ বা post-মেথড ব্যবহার করুন।

setProgressBackgroundColorSchemeResource প্রপার্টি নির্দেশকের পটভূমি পরিবর্তন করে। setSize(SwipeRefreshLayout.LARGE) স্পিনারের আকার সেট করে। XML লেআউটে, SwipeRefreshLayout RecyclerView র‍্যাপ করে: swipe_refresh_layout → recycler_view। Google I/O 2024 অনুসারে, SwipeRefreshLayout 85% Android অ্যাপে কন্টেন্ট ফিড সহ ব্যবহৃত হয়। IT Sectr এ, আমরা অ্যাসিঙ্ক্রোনাসভাবে লোড করা তালিকা সহ সমস্ত স্ক্রিন SwipeRefreshLayout এ র‍্যাপ করি — এটি সমস্ত Android সংস্করণে একটি অভিন্ন UX প্রদান করে।

Material Pull-to-Refresh (Android 12+)

Android 12 (Material You) থেকে শুরু করে, Google material-1.6.0+ লাইব্রেরি (Compose এর জন্য androidx.compose.material3.pulltorefresh) থেকে নতুন Material Pull-to-Refresh ব্যবহার করার পরামর্শ দেয়। নতুন API স্প্রিং অ্যানিমেশন সমর্থন এবং ওয়ালপেপারের উপর ভিত্তি করে অভিযোজিত রঙ সহ একটি অ্যানিমেটেড নির্দেশক ব্যবহার করে। SwipeRefreshLayout Android 12 এর নিচের সংস্করণগুলির জন্য সামঞ্জস্যপূর্ণ থাকে।

সেরা অনুশীলন এবং সাধারণ ভুল

Pull-to-Refresh বাস্তবায়নে সহজ প্যাটার্ন, কিন্তু এতে বেশ কয়েকটি সাধারণ ভুল রয়েছে যা UX হ্রাস করে। আসুন সেগুলি এবং প্রতিরোধের উপায়গুলি দেখি।

  • ডাবল রিফ্রesh — ব্যবহারকারী লোডিং শেষ হওয়ার আগে বেশ কয়েকবার তালিকা টানতে পারে। সমাধান: শুরুতে isRefreshing ফ্ল্যাগ সেট করুন এবং onRefresh() এ এটি পরীক্ষা করুন। iOS এ, endRefreshing() শুধুমাত্র শেষ হওয়ার পরে কল করা হয়; UIRefreshControl এ অঙ্গভঙ্গি ব্লকিং বিল্ট-ইন।
  • প্রতিক্রিয়ার অভাব — লোডিং নির্দেশক ব্যবহারকারী থ্রেশহোল্ড অতিক্রম করার পরেই দেখা উচিত। স্পর্শ করার সাথে সাথে নির্দেশক দেখাবেন না — এটি ব্যবহারকারীদের বিভ্রান্ত করে। iOS এবং Android এটি স্বয়ংক্রিয়ভাবে পরিচালনা করে।
  • রিফ্রesh সময়কাল উপেক্ষা করা — যদি ডেটা 200 ms এ রিফ্রesh হয়, তাহলে নির্দেশকটি কমপক্ষে 500 ms এর জন্য দেখানো উচিত যাতে ব্যবহারকারী আপডেটটি লক্ষ্য করে। UIRefreshControl এর ন্যূনতম অ্যানিমেশন সময়কাল রয়েছে; Android এ, ন্যূনতম প্রদর্শন সময়ের জন্য Handler.postDelayed ব্যবহার করুন।
  • কীবোর্ড দ্বন্দ্ব — খোলা কীবোর্ডের সাথে, Pull-to-Refresh দুর্ঘটনাক্রমে ট্রিগার হতে পারে। iOS এ view.endEditing(true) এবং Android এ InputMethodManager.hideSoftInputFromWindow() এর মাধ্যমে অঙ্গভঙ্গি শুরু হলে কীবোর্ড লুকান।
  • রিফ্রesh ছাড়া অন্য ব্যবহার — ন্যাভিগেশন (ট্যাব পরিবর্তন, পিছনে যাওয়া) এর জন্য Pull-to-Refresh ব্যবহার করবেন না। এটি উভয় প্ল্যাটফর্মের HIG লঙ্ঘন করে এবং ব্যবহারকারীদের দিশেহারা করে।

IT Sectr এ, আমরা টেস্ট সার্ভার লগে ডুপ্লিকেট অনুরোধ খুঁজে পাওয়ার পরে প্রতিটি প্রকল্পে isRefreshing চেক যুক্ত করেছি — দেখা গেছে যে দ্রুত আঙুলের ব্যবহারকারীরা টানা 3 বার পর্যন্ত রিফ্রesh ট্রিগার করছিল।

Swift এবং Kotlin এ কোড উদাহরণ

উদাহরণ 1: iOS এ UIRefreshControl (Swift)

কাস্টম স্পিনার রঙ এবং অ্যাট্রিবিউটেড শিরোনাম সহ UITableViewController এ Pull-to-Refresh যোগ করে। ডেটা লোড হওয়ার পরে, নির্দেশক লুকিয়ে যায়।

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: "রিফ্রesh করতে টানুন"
        )
        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 প্রপার্টি (iOS 10+) UIRefreshControl সেট করে। .valueChanged ইভেন্ট সহ addTarget অঙ্গভঙ্গি সক্রিয় হলে ফায়ার হয়। endRefreshing() বাধ্যতামূলক — এটি ছাড়া নির্দেশক অনির্দিষ্টকালের জন্য ঘুরতে থাকে। অ্যাসিঙ্ক্রোনাস লোডিং DispatchQueue.main.asyncAfter দিয়ে সিমুলেটেড — বাস্তব প্রকল্পে, URLSession বা async/await ব্যবহার করুন।

উদাহরণ 2: Android এ SwipeRefreshLayout (Kotlin)

কাস্টম নির্দেশক রঙ সহ SwipeRefreshLayout এ RecyclerView র‍্যাপ করে। onRefresh লোডিং শুরু করে এবং শেষ হওয়ার পরে নির্দেশক লুকায়।

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 নির্দেশকের রঙ সেট করে। isRefreshing = false finally ব্লকে কল করা হয় যাতে লোডিং ত্রুটিতেও নির্দেশক লুকিয়ে যায়। ViewModelScope.launch ফ্র্যাগমেন্ট জীবনচক্রের মধ্যে একটি coroutine চালায় — ফ্র্যাগমেন্ট ধ্বংস হলে, coroutine স্বয়ংক্রিয়ভাবে বাতিল হয়, মেমরি লিক প্রতিরোধ করে।

উদাহরণ 3: SwiftUI .refreshable (iOS 15+)

আধুনিক SwiftUI .refreshable মডিফায়ার প্রদান করে যা স্বয়ংক্রিয়ভাবে List বা ScrollView এ Pull-to-Refresh যোগ করে।

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 মডিফায়ার একটি async-ক্লোজার নেয় যা Pull-to-Refresh এ এক্সিকিউট হয়। SwiftUI স্বয়ংক্রিয়ভাবে রিফ্রesh নির্দেশক দেখায় এবং লুকায়, স্টেট রেস পরিচালনা করে (বর্তমান রিফ্রesh শেষ না হওয়া পর্যন্ত নতুন রিফ্রesh শুরু করে না), এবং প্ল্যাটফর্ম অনুযায়ী অ্যানিমেশন অভিযোজিত করে। iOS 15+ এর জন্য, SwiftUI এ Pull-to-Refresh বাস্তবায়নের এটি পছন্দের উপায়।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

SwiftUI এ কি Pull-to-Refresh কাজ করে?

হ্যাঁ, SwiftUI List বা ScrollView এর জন্য .refreshable মডিফায়ার প্রদান করে, যা iOS 15 থেকে উপলব্ধ। ক্লোজারের ভিতরে, async ডেটা লোডিং কোড এক্সিকিউট হয়। SwiftUI স্বয়ংক্রিয়ভাবে রিফ্রesh নির্দেশক পরিচালনা করে এবং বর্তমান লোডিং শেষ না হওয়া পর্যন্ত পুনরাবৃত্ত ট্রিগার ব্লক করে — এটি নতুন প্রকল্পের জন্য প্রস্তাবিত মানক পদ্ধতি।

ডাবল রিফ্রesh কীভাবে প্রতিরোধ করবেন?

isRefreshing ফ্ল্যাগ ব্যবহার করুন: লোডিং শুরুতে true এবং শেষে false সেট করুন। iOS এ, UIRefreshControl স্বয়ংক্রিয়ভাবে পুনরাবৃত্ত কল ব্লক করে যতক্ষণ না endRefreshing() কল করা হয়। Android এ, onRefresh() এর শুরুতে SwipeRefreshLayout.isRefreshing চেক করুন: true হলে — return করুন। এটি প্রতি অঙ্গভঙ্গিতে একটি অনুরোধ নিশ্চিত করে।

Pull-to-Refresh কি তালিকা স্ক্রোল করার সাথে দ্বন্দ্ব করে?

UIRefreshControl এবং SwipeRefreshLayout কেবল তখনই ট্রিগার হয় যখন তালিকা উপরের অবস্থানে থাকে (contentOffset == 0)। আর্কিটেকচার দ্বন্দ্ব দূর করে: যতক্ষণ তালিকা 1px স্ক্রোল করা থাকে, Pull-to-Refresh অঙ্গভঙ্গি সক্রিয় হয় না। যদি দ্বন্দ্ব দেখা দেয়, Android এ nestedScrollingEnabled বা টাচ ইন্টারসেপ্ট করা কাস্টম GestureRecognizer চেক করুন।

সারাংশ

  • Pull-to-Refresh সব মোবাইল প্ল্যাটফর্মে Apple এবং Google দ্বারা মান নির্ধারিত নিচে টানার অঙ্গভঙ্গি দিয়ে ডেটা রিফ্রesh করার প্যাটার্ন।
  • iOS এ UIRefreshControl — target-action, tintColor, attributedTitle এবং বাধ্যতামূলক endRefreshing() সহ একটি নিয়ন্ত্রণ।
  • Android এ SwipeRefreshLayout — setOnRefreshListener, setColorSchemeColors এবং isRefreshing সহ একটি ViewGroup কন্টেইনার।
  • Material Pull-to-Refresh (Android 12+) — স্প্রিং অ্যানিমেশন সহ নতুন API, নতুন প্রকল্পের জন্য প্রস্তাবিত।
  • SwiftUI .refreshable — async ক্লোজার সহ একটি ডিক্লেয়ারেটিভ মডিফায়ার, iOS 15 থেকে উপলব্ধ।
  • isRefreshing ফ্ল্যাগ ডাবল রিফ্রesh প্রতিরোধ করে — উভয় প্ল্যাটফর্মে বাধ্যতামূলক।
  • Pull-to-Refresh ন্যাভিগেশনের জন্য নয় — শুধুমাত্র Material Design এবং Apple HIG অনুযায়ী কন্টেন্ট রিফ্রeshের জন্য।

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন