রচনায় পেজার

অনুভূমিকভাবে বা উল্লম্বভাবে কন্টেন্ট উল্টানোর জন্য, আপনি HorizontalPager এবং VerticalPager কম্পোজেবল ব্যবহার করতে পারেন। ভিউ সিস্টেমে ViewPager এর মতো এগুলির ফাংশন একই রকম। ডিফল্টরূপে, HorizontalPager পূর্ণ স্ক্রিন প্রস্থ দখল করে এবং VerticalPager পূর্ণ উচ্চতা দখল করে। পেজারগুলি একবারে কেবল একটি পৃষ্ঠা উল্টে দেয়। এই সমস্ত ডিফল্ট সেটিংস কনফিগারযোগ্য।

অনুভূমিক পৃষ্ঠা

অনুভূমিকভাবে বাম এবং ডানে স্ক্রোল করে এমন একটি পেজার তৈরি করতে, HorizontalPager ব্যবহার করুন:

চিত্র ১. HorizontalPager ডেমো

// Display 10 items
val pagerState = rememberPagerState(pageCount = {
    10
})
HorizontalPager(state = pagerState) { page ->
    // Our page content
    Text(
        text = "Page: $page",
        modifier = Modifier.fillMaxWidth()
    )
}

ভার্টিক্যালপেজার

উপরে এবং নিচে স্ক্রোল করে এমন একটি পেজার তৈরি করতে, VerticalPager ব্যবহার করুন:

চিত্র ২। VerticalPager ডেমো

// Display 10 items
val pagerState = rememberPagerState(pageCount = {
    10
})
VerticalPager(state = pagerState) { page ->
    // Our page content
    Text(
        text = "Page: $page",
        modifier = Modifier.fillMaxWidth()
    )
}

অলস সৃষ্টি

HorizontalPager এবং VerticalPager উভয়ের পৃষ্ঠাগুলি অলসভাবে তৈরি করা হয় এবং প্রয়োজনে সাজানো হয়। ব্যবহারকারী যখন পৃষ্ঠাগুলি স্ক্রোল করেন, তখন কম্পোজেবল এমন কোনও পৃষ্ঠা সরিয়ে দেয় যা আর প্রয়োজন হয় না।

স্ক্রিনের বাইরে আরও পৃষ্ঠা লোড করুন

ডিফল্টরূপে, পেজার শুধুমাত্র স্ক্রিনে দৃশ্যমান পৃষ্ঠাগুলি লোড করে। স্ক্রিনের বাইরে আরও পৃষ্ঠা লোড করতে, beyondBoundsPageCount শূন্যের চেয়ে বেশি মান সেট করুন।

পেজারের একটি আইটেমে স্ক্রোল করুন

পেজারের একটি নির্দিষ্ট পৃষ্ঠায় স্ক্রোল করতে, rememberPagerState() ব্যবহার করে একটি PagerState অবজেক্ট তৈরি করুন এবং এটিকে state প্যারামিটার হিসেবে পেজারে পাঠান। আপনি CoroutineScope এর ভিতরে এই অবস্থায় PagerState#scrollToPage() কল করতে পারেন:

val pagerState = rememberPagerState(pageCount = {
    10
})
HorizontalPager(state = pagerState) { page ->
    // Our page content
    Text(
        text = "Page: $page",
        modifier = Modifier
            .fillMaxWidth()
            .height(100.dp)
    )
}

// scroll to page
val coroutineScope = rememberCoroutineScope()
Button(onClick = {
    coroutineScope.launch {
        // Call scroll to on pagerState
        pagerState.scrollToPage(5)
    }
}, modifier = Modifier.align(Alignment.BottomCenter)) {
    Text("Jump to Page 5")
}

যদি আপনি পৃষ্ঠাটি অ্যানিমেট করতে চান, PagerState#animateScrollToPage() ফাংশনটি ব্যবহার করুন:

val pagerState = rememberPagerState(pageCount = {
    10
})

HorizontalPager(state = pagerState) { page ->
    // Our page content
    Text(
        text = "Page: $page",
        modifier = Modifier
            .fillMaxWidth()
            .height(100.dp)
    )
}

// scroll to page
val coroutineScope = rememberCoroutineScope()
Button(onClick = {
    coroutineScope.launch {
        // Call scroll to on pagerState
        pagerState.animateScrollToPage(5)
    }
}, modifier = Modifier.align(Alignment.BottomCenter)) {
    Text("Jump to Page 5")
}

পৃষ্ঠার অবস্থার পরিবর্তন সম্পর্কে বিজ্ঞপ্তি পান

PagerState তিনটি বৈশিষ্ট্য রয়েছে যেখানে পৃষ্ঠাগুলি সম্পর্কে তথ্য রয়েছে: currentPage , settledPage , এবং targetPage

  • currentPage : স্ন্যাপ পজিশনের সবচেয়ে কাছের পৃষ্ঠা। ডিফল্টরূপে, স্ন্যাপ পজিশনটি লেআউটের শুরুতে থাকে।
  • settledPage : যখন কোনও অ্যানিমেশন বা স্ক্রলিং চলছে না তখন পৃষ্ঠা নম্বর। এটি currentPage বৈশিষ্ট্য থেকে আলাদা, কারণ পৃষ্ঠাটি স্ন্যাপ অবস্থানের যথেষ্ট কাছাকাছি থাকলে currentPage তাৎক্ষণিকভাবে আপডেট হয়, তবে সমস্ত অ্যানিমেশন চালানো শেষ না হওয়া পর্যন্ত settledPage একই থাকে।
  • targetPage : স্ক্রলিং মুভমেন্টের জন্য প্রস্তাবিত স্টপ পজিশন।

আপনি snapshotFlow ফাংশন ব্যবহার করে এই ভেরিয়েবলের পরিবর্তনগুলি পর্যবেক্ষণ করতে এবং সেগুলিতে প্রতিক্রিয়া জানাতে পারেন। উদাহরণস্বরূপ, প্রতিটি পৃষ্ঠার পরিবর্তনের উপর একটি বিশ্লেষণ ইভেন্ট পাঠাতে, আপনি নিম্নলিখিতগুলি করতে পারেন:

val pagerState = rememberPagerState(pageCount = {
    10
})

LaunchedEffect(pagerState) {
    // Collect from the a snapshotFlow reading the currentPage
    snapshotFlow { pagerState.currentPage }.collect { page ->
        // Do something with each page change, for example:
        // viewModel.sendPageSelectedEvent(page)
        Log.d("Page change", "Page changed to $page")
    }
}

VerticalPager(
    state = pagerState,
) { page ->
    Text(text = "Page: $page")
}

একটি পৃষ্ঠা সূচক যোগ করুন

একটি পৃষ্ঠায় একটি সূচক যোগ করতে, পৃষ্ঠার সংখ্যার মধ্যে কোন পৃষ্ঠাটি নির্বাচিত হয়েছে সে সম্পর্কে তথ্য পেতে PagerState অবজেক্ট ব্যবহার করুন এবং আপনার কাস্টম সূচকটি আঁকুন।

উদাহরণস্বরূপ, একটি বৃত্ত নির্দেশক তৈরি করতে, আপনি pagerState.currentPage ব্যবহার করে বৃত্তের সংখ্যা পুনরাবৃত্তি করতে পারেন এবং পৃষ্ঠাটি নির্বাচিত কিনা তার উপর ভিত্তি করে বৃত্তের রঙ পরিবর্তন করতে পারেন:

val pagerState = rememberPagerState(pageCount = {
    4
})
HorizontalPager(
    state = pagerState,
    modifier = Modifier.fillMaxSize()
) { page ->
    // Our page content
    Text(
        text = "Page: $page",
    )
}
Row(
    Modifier
        .wrapContentHeight()
        .fillMaxWidth()
        .align(Alignment.BottomCenter)
        .padding(bottom = 8.dp),
    horizontalArrangement = Arrangement.Center
) {
    repeat(pagerState.pageCount) { iteration ->
        val color = if (pagerState.currentPage == iteration) Color.DarkGray else Color.LightGray
        Box(
            modifier = Modifier
                .padding(2.dp)
                .clip(CircleShape)
                .background(color)
                .size(16.dp)
        )
    }
}

পেজারে কন্টেন্টের নিচে একটি বৃত্ত নির্দেশক দেখাচ্ছে
চিত্র ৩। পেজারে বিষয়বস্তুর নীচে একটি বৃত্ত নির্দেশক দেখানো হচ্ছে

কন্টেন্টে আইটেম স্ক্রোল ইফেক্ট প্রয়োগ করুন

একটি সাধারণ ব্যবহারের ক্ষেত্রে হল আপনার পেজার আইটেমগুলিতে প্রভাব প্রয়োগ করার জন্য স্ক্রোল অবস্থান ব্যবহার করা। নির্বাচিত পৃষ্ঠা থেকে একটি পৃষ্ঠা কত দূরে তা জানতে, আপনি PagerState.currentPageOffsetFraction ব্যবহার করতে পারেন। তারপরে আপনি নির্বাচিত পৃষ্ঠা থেকে দূরত্বের উপর ভিত্তি করে আপনার সামগ্রীতে রূপান্তর প্রভাব প্রয়োগ করতে পারেন।

চিত্র ৪। পেজারের বিষয়বস্তুতে রূপান্তর প্রয়োগ করা

উদাহরণস্বরূপ, কেন্দ্র থেকে কত দূরে অবস্থিত তার উপর ভিত্তি করে আইটেমগুলির অস্বচ্ছতা সামঞ্জস্য করতে, পেজারের ভিতরে থাকা কোনও আইটেমের উপর Modifier.graphicsLayer ব্যবহার করে alpha পরিবর্তন করুন:

val pagerState = rememberPagerState(pageCount = {
    4
})
HorizontalPager(state = pagerState) { page ->
    Card(
        Modifier
            .size(200.dp)
            .graphicsLayer {
                // Calculate the absolute offset for the current page from the
                // scroll position. We use the absolute value which allows us to mirror
                // any effects for both directions
                val pageOffset = (
                    (pagerState.currentPage - page) + pagerState
                        .currentPageOffsetFraction
                    ).absoluteValue

                // We animate the alpha, between 50% and 100%
                alpha = lerp(
                    start = 0.5f,
                    stop = 1f,
                    fraction = 1f - pageOffset.coerceIn(0f, 1f)
                )
            }
    ) {
        // Card content
    }
}

কাস্টম পৃষ্ঠার আকার

ডিফল্টরূপে, HorizontalPager এবং VerticalPager যথাক্রমে পূর্ণ প্রস্থ বা পূর্ণ উচ্চতা দখল করে। আপনি pageSize ভেরিয়েবলটিকে একটি Fixed , Fill (ডিফল্ট) অথবা একটি কাস্টম আকার গণনার জন্য সেট করতে পারেন।

উদাহরণস্বরূপ, 100.dp এর একটি নির্দিষ্ট প্রস্থ পৃষ্ঠা সেট করতে:

val pagerState = rememberPagerState(pageCount = {
    4
})
HorizontalPager(
    state = pagerState,
    pageSize = PageSize.Fixed(100.dp)
) { page ->
    // page content
}

ভিউপোর্টের আকারের উপর ভিত্তি করে পৃষ্ঠাগুলির আকার নির্ধারণ করতে, একটি কাস্টম পৃষ্ঠার আকার গণনা ব্যবহার করুন। একটি কাস্টম PageSize অবজেক্ট তৈরি করুন এবং আইটেমগুলির মধ্যে ব্যবধান বিবেচনা করে availableSpace কে তিন দিয়ে ভাগ করুন:

private val threePagesPerViewport = object : PageSize {
    override fun Density.calculateMainAxisPageSize(
        availableSpace: Int,
        pageSpacing: Int
    ): Int {
        return (availableSpace - 2 * pageSpacing) / 3
    }
}

কন্টেন্ট প্যাডিং

HorizontalPager এবং VerticalPager উভয়ই কন্টেন্ট প্যাডিং পরিবর্তন সমর্থন করে, যা আপনাকে পৃষ্ঠাগুলির সর্বাধিক আকার এবং সারিবদ্ধকরণকে প্রভাবিত করতে দেয়।

উদাহরণস্বরূপ, start প্যাডিং সেট করলে পৃষ্ঠাগুলি শেষের দিকে সারিবদ্ধ হয়:

শুরুর প্যাডিং সহ পেজারে কন্টেন্টটি শেষের দিকে সারিবদ্ধভাবে দেখানো হচ্ছে
চিত্র ৫। স্টার্ট প্যাডিং সহ পেজার।

val pagerState = rememberPagerState(pageCount = {
    4
})
HorizontalPager(
    state = pagerState,
    contentPadding = PaddingValues(start = 64.dp),
) { page ->
    // page content
}

start এবং end প্যাডিং উভয়কেই একই মানে সেট করলে আইটেমটি অনুভূমিকভাবে কেন্দ্রীভূত হয়:

শুরু এবং শেষ প্যাডিং সহ পেজার যেখানে কন্টেন্টকে কেন্দ্র করে দেখানো হচ্ছে
চিত্র ৬। অনুভূমিক প্যাডিং সহ পেজার।

val pagerState = rememberPagerState(pageCount = {
    4
})
HorizontalPager(
    state = pagerState,
    contentPadding = PaddingValues(horizontal = 32.dp),
) { page ->
    // page content
}

end প্যাডিং সেট করলে পৃষ্ঠাগুলি শুরুর দিকে সারিবদ্ধ হয়:

শুরু এবং শেষ প্যাডিং সহ পেজার যা শুরুর সাথে সারিবদ্ধ কন্টেন্ট দেখায়
চিত্র ৭। শেষ প্যাডিং সহ পেজার।

val pagerState = rememberPagerState(pageCount = {
    4
})
HorizontalPager(
    state = pagerState,
    contentPadding = PaddingValues(end = 64.dp),
) { page ->
    // page content
}

VerticalPager জন্য একই রকম প্রভাব অর্জনের জন্য আপনি top এবং bottom মানগুলি সেট করতে পারেন। 32.dp মানটি এখানে শুধুমাত্র উদাহরণ হিসেবে ব্যবহার করা হয়েছে; আপনি প্রতিটি প্যাডিং মাত্রাকে যেকোনো মানের সাথে সেট করতে পারেন।

স্ক্রোল আচরণ কাস্টমাইজ করুন

ডিফল্ট HorizontalPager এবং VerticalPager কম্পোজেবলগুলি পেজারের সাথে স্ক্রলিং জেসচারগুলি কীভাবে কাজ করে তা নির্দিষ্ট করে। তবে, আপনি pagerSnapDistance বা flingBehavior এর মতো ডিফল্টগুলি কাস্টমাইজ এবং পরিবর্তন করতে পারেন।

স্ন্যাপ দূরত্ব

ডিফল্টরূপে, HorizontalPager এবং VerticalPager একটি fling জেসচার একবারে একটি পৃষ্ঠায় স্ক্রোল করার জন্য সর্বোচ্চ কত পৃষ্ঠা ব্যবহার করতে পারে তা নির্ধারণ করে। এটি পরিবর্তন করতে, flingBehaviorpagerSnapDistance সেট করুন:

val pagerState = rememberPagerState(pageCount = { 10 })

val fling = PagerDefaults.flingBehavior(
    state = pagerState,
    pagerSnapDistance = PagerSnapDistance.atMost(10)
)

Column(modifier = Modifier.fillMaxSize()) {
    HorizontalPager(
        state = pagerState,
        pageSize = PageSize.Fixed(200.dp),
        beyondViewportPageCount = 10,
        flingBehavior = fling
    ) {
        PagerSampleItem(page = it)
    }
}

একটি অটো-এডভান্সিং পেজার তৈরি করুন

এই বিভাগে বর্ণনা করা হয়েছে কিভাবে কম্পোজে পৃষ্ঠা সূচক সহ একটি স্বয়ংক্রিয়-অগ্রসর পেজার তৈরি করতে হয়। আইটেমগুলির সংগ্রহ স্বয়ংক্রিয়ভাবে অনুভূমিকভাবে স্ক্রোল করে, তবে ব্যবহারকারীরা ম্যানুয়ালি আইটেমগুলির মধ্যে সোয়াইপ করতে পারেন। যদি কোনও ব্যবহারকারী পেজারের সাথে ইন্টারঅ্যাক্ট করে, তবে এটি স্বয়ংক্রিয় অগ্রগতি বন্ধ করে দেয়।

মৌলিক উদাহরণ

একসাথে, নিম্নলিখিত স্নিপেটগুলি একটি ভিজ্যুয়াল ইন্ডিকেটর সহ একটি মৌলিক অটো-অ্যাডভান্সিং পেজার বাস্তবায়ন তৈরি করে, যেখানে প্রতিটি পৃষ্ঠা একটি ভিন্ন রঙে রেন্ডার হয়:

@Composable
fun AutoAdvancePager(pageItems: List<Color>, modifier: Modifier = Modifier) {
    Box(modifier = Modifier.fillMaxSize()) {
        val pagerState = rememberPagerState(pageCount = { pageItems.size })
        val pagerIsDragged by pagerState.interactionSource.collectIsDraggedAsState()

        val pageInteractionSource = remember { MutableInteractionSource() }
        val pageIsPressed by pageInteractionSource.collectIsPressedAsState()

        // Stop auto-advancing when pager is dragged or one of the pages is pressed
        val autoAdvance = !pagerIsDragged && !pageIsPressed

        if (autoAdvance) {
            LaunchedEffect(pagerState, pageInteractionSource) {
                while (true) {
                    delay(2000)
                    val nextPage = (pagerState.currentPage + 1) % pageItems.size
                    pagerState.animateScrollToPage(nextPage)
                }
            }
        }

        HorizontalPager(
            state = pagerState
        ) { page ->
            Text(
                text = "Page: $page",
                textAlign = TextAlign.Center,
                modifier = modifier
                    .fillMaxSize()
                    .background(pageItems[page])
                    .clickable(
                        interactionSource = pageInteractionSource,
                        indication = LocalIndication.current
                    ) {
                        // Handle page click
                    }
                    .wrapContentSize(align = Alignment.Center)
            )
        }

        PagerIndicator(pageItems.size, pagerState.currentPage)
    }
}

কোড সম্পর্কে গুরুত্বপূর্ণ বিষয়সমূহ

  • AutoAdvancePager ফাংশনটি স্বয়ংক্রিয় অগ্রগতির সাথে একটি অনুভূমিকভাবে পেজিং ভিউ তৈরি করে। এটি ইনপুট হিসাবে Color বস্তুর একটি তালিকা নেয়, যা প্রতিটি পৃষ্ঠার জন্য পটভূমির রঙ হিসাবে ব্যবহৃত হয়।
  • pagerState rememberPagerState ব্যবহার করে তৈরি করা হয়, যা পেজারের অবস্থা ধরে রাখে।
  • pagerIsDragged এবং pageIsPressed ব্যবহারকারীর মিথস্ক্রিয়া ট্র্যাক করে।
  • LaunchedEffect প্রতি দুই সেকেন্ডে স্বয়ংক্রিয়ভাবে পেজারটিকে এগিয়ে নিয়ে যায়, যদি না ব্যবহারকারী পেজারটি টেনে আনেন বা কোনও একটি পৃষ্ঠা চাপেন।
  • HorizontalPager পৃষ্ঠাগুলির একটি তালিকা প্রদর্শন করে, প্রতিটি পৃষ্ঠার নম্বর প্রদর্শনকারী একটি Text composable সহ। মডিফায়ার পৃষ্ঠাটি পূরণ করে, pageItems থেকে পটভূমির রঙ সেট করে এবং পৃষ্ঠাটিকে ক্লিকযোগ্য করে তোলে।

@Composable
fun PagerIndicator(pageCount: Int, currentPageIndex: Int, modifier: Modifier = Modifier) {
    Box(modifier = Modifier.fillMaxSize()) {
        Row(
            modifier = Modifier
                .wrapContentHeight()
                .fillMaxWidth()
                .align(Alignment.BottomCenter)
                .padding(bottom = 8.dp),
            horizontalArrangement = Arrangement.Center
        ) {
            repeat(pageCount) { iteration ->
                val color = if (currentPageIndex == iteration) Color.DarkGray else Color.LightGray
                Box(
                    modifier = modifier
                        .padding(2.dp)
                        .clip(CircleShape)
                        .background(color)
                        .size(16.dp)
                )
            }
        }
    }
}

কোড সম্পর্কে গুরুত্বপূর্ণ বিষয়সমূহ

  • একটি Box কম্পোজেবল মূল উপাদান হিসেবে কাজ করে এবং পৃষ্ঠার সূচকগুলিকে অনুভূমিকভাবে সাজানোর জন্য একটি Row ধারণ করে।
  • একটি কাস্টম পৃষ্ঠা নির্দেশক বৃত্তের সারি হিসাবে প্রদর্শিত হয়, যেখানে একটি CircleShape এ ক্লিপ করা প্রতিটি Box একটি পৃষ্ঠাকে প্রতিনিধিত্ব করে।
  • বর্তমান পৃষ্ঠার বৃত্তটি DarkGray রঙে রঞ্জিত, অন্য বৃত্তগুলি LightGray রঙে রঞ্জিত। currentPageIndex প্যারামিটার নির্ধারণ করে যে কোন বৃত্তটি গাঢ় ধূসর রঙে রেন্ডার হবে।

ফলাফল

এই ভিডিওটিতে পূর্ববর্তী স্নিপেটগুলি থেকে মৌলিক অটো-অ্যাডভান্সিং পেজারটি দেখানো হয়েছে:

চিত্র ৮। প্রতিটি পৃষ্ঠার অগ্রগতির মধ্যে দুই সেকেন্ড বিলম্ব সহ একটি স্বয়ংক্রিয়-অগ্রসর পেজার।

অতিরিক্ত সম্পদ

{% অক্ষরে অক্ষরে %} {% এন্ডভারব্যাটিম %}